File tree Expand file tree Collapse file tree 5 files changed +50
-0
lines changed Expand file tree Collapse file tree 5 files changed +50
-0
lines changed Original file line number Diff line number Diff line change @@ -21,6 +21,10 @@ include::high-performance-index.adoc[leveloffset=+1]
2121
2222include::query-optimization.adoc[leveloffset=+1]
2323
24+ include::redo-log.adoc[leveloffset=+1]
25+
26+ include::undo-log.adoc[leveloffset=+1]
27+
2428include::locks.adoc[leveloffset=+1]
2529
2630include::sharding.adoc[leveloffset=+1]
Original file line number Diff line number Diff line change @@ -48,12 +48,31 @@ AUTO_INCREMENT 有两种实现方式:
4848
4949=== Record Lock
5050
51+ Record Lock 即是常说的行锁,仅仅把一条记录锁上。
52+
53+ Record Lock 有 S 锁 和 X 锁之分。
54+
55+ [NOTE]
56+ ====
57+ S 锁 和 X 锁类似 Java 中的 `ReadWriteLock`,其行为和 `ReentrantReadWriteLock` 几乎一模一样:读读并发、读写互斥、写写互斥。
58+ ====
59+
5160=== 间隙锁 Gap Lock
5261
62+ 间隙锁主要是为了解决插入时的幻读问题。由于插入时,还没有数据记录,所以,无法创建该数据对应的 Record Lock。所以,提出了 Gap Lock 锁。
63+
64+ Gap Lock 的作用仅仅是为了防止插入幻影记录而已。
65+
66+ 给一条记录加 Gap 锁,则不允许其他事务向这条记录前面的插入新记录。为了解决之后可能插入新记录的问题,可以在索引中最后一条记录所在页面的 `Supremum` 记录(表示该页中最大的记录)上加 Gap 锁,这样就可以阻止其他事务插入新记录了。
67+
5368=== Next-Key Lock
5469
5570Next-Key Lock = Record Lock + Gap Lock。
5671
5772=== 插入意向锁 Insert Intention Lock
5873
74+ 在内存中生成的一个锁结构,表示有事务想在某个间隙插入新记录,但是现在处于等待状态。
75+
76+ 插入意向锁并不会阻止别的事务继续获取该记录上的任何类型的锁,非常鸡肋。
77+
5978=== 隐式锁
Original file line number Diff line number Diff line change 1+ [#redo]
2+ = redo 日志,说到做到
3+
4+ 每条记录修改到具体数据表空间,页号,以及每个具体的值(可以是具体的指针地址,也可以是指定字段)。
5+
6+ 一批 redo 日志组成一个不可分割的组;多个组对应一条 SQL 语句(比如需要页分裂的悲观插入);多个语句组成一个事务。
7+
8+ 对底层页面的一次原子访问过程称为一个 Mini-Transaction,简称 MTR。多个 MTR 组成一个 block;内存中若干个连续的 block,组成一个 log buffer。
9+
10+
11+
12+
Original file line number Diff line number Diff line change 1616
1717在 Read Uncommitted 级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为**脏读(Dirty Read)**。性能不会好太多,但是问题却一大堆,实际应用中一般很少使用。
1818
19+ 直接读取记录的最新版本,可能出现脏读、不可重复读和幻读等现象。
20+
1921=== Read Committed(提交读)
2022
2123大多数数据库系统的默认隔离级别都是 Read Committed。Read Committed 满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说:一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。有时也叫不可重复读(Nonrepeatable Read)。
2224
25+ 在每次执行 `SELECT` 时都生成一个 ReadView,可以避免脏读,但是无法避免不可重复读和幻读。
26+
2327=== Repeatable Read(可重复读)
2428
2529Repeatable Read 解决了脏读的问题。但是还是无法解决领一个**幻读(Phantom Read)**问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB 和 XtraDB 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
2630
31+ 只在第一次执行 `SELECT` 语句时,生成一个 ReadView,可以避免出现脏读、不可重复读和幻读。
32+
2733=== Serializable(可串行化)
2834
2935Serializable 是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读问题。简单来说,Serializable 会在读取的每一行数据上都加锁,所以导致大量的超时和锁争用的问题。实际中,极少使用。
Original file line number Diff line number Diff line change 1+ [#undo]
2+ = undo 日志,后悔药
3+
4+ 在更新操作时,会把旧版本写入到 undo 中,最新的记录有一个 `roll_pointer` 指针执行旧版本,各个版本的记录依次用指针链接,组成一个版本链。
5+
6+ 查询时生成 ReadView,根据其中的事务 ID 去查找 undo 版本链中的数据,这就是 MVCC 的原理。
7+
8+ 删除操作,是先打标;事务提交后,会有专门的清理线程来把记录删除掉。
9+
You can’t perform that action at this time.
0 commit comments