事务隔离级别
1. 读未提交:a事务可以读取到b事务尚未提交的数据,存在脏读,不可重复读和幻读
2. 读已提交:a事务只能读取b事务已提交的数据,存在不可重复读和幻读
3. 可重复读:同一事务中多次读取的数据相同,InnoDB默认的隔离级别,通过mvcc(多版本并发控制)实现,InnoDB通过间隙锁和临键锁部分解决幻读问题
4. 串行化:最高的隔离级别,所有事务串行执行,并发最低,性能最差
锁机制
1. 主键或唯一索引
a. 等值查询-命中:记录锁
b. 等值查询-未命中:间隙锁
c. 范围查询-命中/未命中:临键锁
2. 非唯一索引
a. 等值查询-命中:记录锁+回表主键加锁
b. 等值查询-未命中:间隙锁
c. 范围查询-命中/未命中:临键锁+回表主键加锁(这里注意只会给命中的记录主键加锁,对于临键锁的最后一个key的主键是不会加锁的)
MVCC(多版本并发控制)
MVCC核心机制包含3个关键点:
1、隐藏列,innodb每行记录包好3个隐藏列,DB_TRX_ID:最近修改该行的事务ID;DB_ROLL_PTR:回滚指针,指向undo log记录;DB_ROW_ID:行ID,无主键时自动生成
2、Undo Log,存储记录的历史版本,组成版本链,用来支持事务回滚和一致性读
3、ReadView,事务执行快照读时产生的读视图,里面包含4个关键信息。creator_trx_id:创建该ReadView的事务id;min_trx_id:最小活跃事务id;max_trx_id:预分配的下一个事务id;m_ids:当前未提交事务id列表。
MVCC工作原理:
1、版本链构建:每次数据修改时,将当前记录拷贝到undo log,修改数据行的DB_TRX_ID为当前事务ID,将DB_ROLL_PTR指向undo log中的旧版本
2、可见性判断算法:DB_TRX_ID==creator_trx_id 当前事务修改:可见;DB_TRX_ID<min_trx_id 事务已提交:可见;DB_TRX_ID>=max_trx_id 事务未开始:不可见;DB_TRX_ID在m_ids中 事务未提交:不可见;DB_TRX_ID不在m_ids中 事务已提交:可见
不同隔离级别的实现:
1、读未提交:不使用MVCC,直接读表中的最新记录
2、读已提交:每次select都生成新的ReadView
3、可重复读:第一次select时生成ReadView,后续复用