多版本并发控制
明确两个概念:快照读,当前读。
快照读:读的可能是旧的数据,普通的select
当前读:读的是最新的数据,加锁了的select和update,insert
select ... lock in share mode
select ... for update
insert
、update
、delete
操作
隐藏字段
DB_TRX_ID 修改数据的最近的
事务id
DB_POLL_PTR 回滚指针指向undo_log当前节点的上一个节点的指针
DB_ROW_ID 保证表一定有一个唯一索引。也就是说如果没有设置主键且该表没有唯一非空索引时,
Read View 主要是用来做可见性判断
class ReadView {
/* ... */
private:
trx_id_t m_low_limit_id; /* 大于等于这个 ID 的事务均不可见 */
trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */
trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */
trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */
ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */
m_closed; /* 标记 Read View 是否 close */
}
主要有以下字段:
m_low_limit_id
:目前出现过的最大的事务 ID+1,即下一个将被分配的事务 ID。大于等于这个 ID 的数据版本均不可见m_up_limit_id
:活跃事务列表m_ids
中最小的事务 ID,如果m_ids
为空,则m_up_limit_id
为m_low_limit_id
。小于这个 ID 的数据版本均可见m_ids
:Read View
创建时其他未提交的活跃事务 ID 列表。创建Read View
时,将当前未提交事务 ID 记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。m_ids
不包括当前事务自己和已提交的事务(正在内存中)m_creator_trx_id
:创建该Read View
的事务 id
如果DB_TRX_ID >m_low_limit_id不可见,进入这条undo_log的指针所指的下一个事务id,否则进入下一个判断
如果DB_TRX_ID < m_up_limit_id,可见,否进入下一个判断
如果DB_TRX_ID 存在与活跃事务列表,不可见,如果不存在,说明这个事务在创建Read View之前就已经提交,则可见。
RC和RP的隔离级别的差别就在于创建Read View的时机不同,RC下创建Read View是在每一次select的时候创建,而RP是在事务的第一个select的时候创建。
MVCC通过邻键锁来避免幻读问题。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读