三大日志
一个SQL执行的时候,会在buffer pool里面做哪些操作
undo log 在对数据执行操作之前就进行了记录
undo log主要记录了数据的逻辑变化,比如一条INSERT语句,对应一条DELETE的undo log,对于每个UPDATE语句,对应一条相反的UPDATE的undo log,这样在发生错误时,就能回滚到事务之前的数据状态。
redo log 是属于InnoDB引擎的,binlog是属于MySQL数据库的
redo log是物理日志,记录的是“在某个数据页上做了什么修改”(数据页上某个偏移量的值);
binlog是逻辑日志,记录的是这个语句的原始逻辑(sql、数据行)
redo log是循环写入的,当空间不足的时候,就会覆盖之前的数据,而binlog是追加方式写入,一块区域写满了,就会新开一个
MVCC
MVCC与undolog
正确的理解MySQL的MVCC及实现原理
undolog多版本链+ReadView机制实现mvcc多版本并发控制
InnoDB存储引擎在 RR 级别下通过 MVCC和 Next-key Lock 来解决幻读问题:
1、执行普通 select,此时会以 MVCC 快照读的方式读取数据
在快照读的情况下,RR 隔离级别只会在事务开启后的第一次查询生成 Read View ,并使用至事务提交。所以在生成 Read View 之后其它事务所做的更新、插入记录版本对当前事务并不可见,实现了可重复读和防止快照读下的 “幻读”
2、执行 select…for update/lock in share mode、insert、update、delete 等当前读
在当前读下,读取的都是最新的数据,如果其它事务有插入新的记录,并且刚好在当前事务查询范围内,就会产生幻读!InnoDB 使用 Next-key Lock 来防止这种情况。当执行当前读时,会锁定读取到的记录的同时,锁定它们的间隙,防止其它事务在查询范围内插入数据。只要我不让你插入,就不会发生幻读
间隙锁
MySQL记录锁、间隙锁、临键锁(Next-Key Locks)详解 - 简书 (jianshu.com)
心灵拷问:MySQL 到底是怎么加行级锁、间隙锁、临键锁的?
假设有如下表:
InnoDB,RR隔离级别:id主键, age 普通索引
该表中 age 列潜在的临键锁有:
(-∞, 10],
(10, 24],
(24, 32],
(32, 45],
(45, +∞],
在事务 A 中执行如下命令:
– 根据非唯一索引列 UPDATE 某条记录
UPDATE table SET name = Vladimir WHERE age = 24;
– 或根据非唯一索引列 锁住某条记录
SELECT * FROM table WHERE age = 24 FOR UPDATE;
不管执行了上述 SQL 中的哪一句,之后如果在事务 B 中执行以下命令,则该命令会被阻塞:
INSERT INTO table VALUES(100, 26, ‘tianqi’);
很明显,事务 A 在对 age 为 24 的列进行 UPDATE 操作的同时,也获取了 (24, 32] 这个区间内的临键锁。