和隔离级别密切相关的概念是脏读、幻读和不可重复读 这三个读异常。
- 脏读:读到了别的事务还没有提交的数据。之所以叫做脏读,就是因为未提交数据可能会被回滚掉。
- 不可重复读:在一个事务执行过程中,对同一行数据读到的结果不同
- 幻读:事务执行过程中,别的事务插入了新的数据并且提交了,然后事务在后续步骤里读到了这个新的数据。
用一个表用来描述隔离级别和三种读异常的关系:
理论上,可重复读是没有解决幻读的,但是因为MySQL因为使用了临键锁,因此它的可重复读隔离级别已经解决了幻读问题。
此外还有一个相似的概念:快照读和当前读。
快照读就是在事务开始的时候创建了一个数据的快照,在整个事务过程中都读这个快照;
当前读,则是每次都去读最新数据。
MySQL在可重复读这个隔离级别下,查询的执行效果和快照读非常接近。
为了实现MVCC,InnoDB引擎给每一行都加了两个额外的字段trx_id
和roll_ptr
trx_id
:事务ID,也叫做事务版本号。MVCC里面的V指的是这个数字,每一个事务在开始的时候就会获得一个ID,然后这个事务内操作的行的事务ID,都会被修改为这个事务的IDroll_ptr
:回滚指针,InnoDB通过roll_ptr
把每一行的历史版本串联在一起。
实际上,InnoDB引擎还隐式地插入了另外一个列row_id
,如果你没有设置任何主键,那么这个列就会被当作主键来使用。但是它其实和MVCC没太大关系,所以不需要关注。