一、当前读。
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行枷锁,对于我们日常的操作,如:
select ... lock in share mode(共享锁),select .... for update、insert、delete(排他锁)都是一种当前读。
加上共享锁即可读。
二、快照读。
简单的select(不加锁)就是快照读,快照读读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
1、read committed:每次select,都生成一个快照读。
2、repeatable read:开启事务后第一个select语句才是快照读的地方。
3、serializable:快照读会退化为当前读。
三、MVCC。
MVCC全程Multi-version Concurrency Control,多版本并发控制,指维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录的三个隐式字段、undo log日志和readbview。
四、隐式字段。
隐藏字段 | 含义 |
DB_TRX_ID | 最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。 |
DB_ROLL_PTR | 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。 |
DB_ROW_ID | 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。 |
查看ibd文件:ibd2sdi stu.idb
五、undo log
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会被立即删除。
undo log版本链
不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最新的记录,链表尾部是最早的旧记录。