File tree 5 files changed +50
-0
lines changed
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]
21
21
22
22
include::query-optimization.adoc[leveloffset=+1]
23
23
24
+ include::redo-log.adoc[leveloffset=+1]
25
+
26
+ include::undo-log.adoc[leveloffset=+1]
27
+
24
28
include::locks.adoc[leveloffset=+1]
25
29
26
30
include::sharding.adoc[leveloffset=+1]
Original file line number Diff line number Diff line change @@ -48,12 +48,31 @@ AUTO_INCREMENT 有两种实现方式:
48
48
49
49
=== Record Lock
50
50
51
+ Record Lock 即是常说的行锁,仅仅把一条记录锁上。
52
+
53
+ Record Lock 有 S 锁 和 X 锁之分。
54
+
55
+ [NOTE]
56
+ ====
57
+ S 锁 和 X 锁类似 Java 中的 `ReadWriteLock`,其行为和 `ReentrantReadWriteLock` 几乎一模一样:读读并发、读写互斥、写写互斥。
58
+ ====
59
+
51
60
=== 间隙锁 Gap Lock
52
61
62
+ 间隙锁主要是为了解决插入时的幻读问题。由于插入时,还没有数据记录,所以,无法创建该数据对应的 Record Lock。所以,提出了 Gap Lock 锁。
63
+
64
+ Gap Lock 的作用仅仅是为了防止插入幻影记录而已。
65
+
66
+ 给一条记录加 Gap 锁,则不允许其他事务向这条记录前面的插入新记录。为了解决之后可能插入新记录的问题,可以在索引中最后一条记录所在页面的 `Supremum` 记录(表示该页中最大的记录)上加 Gap 锁,这样就可以阻止其他事务插入新记录了。
67
+
53
68
=== Next-Key Lock
54
69
55
70
Next-Key Lock = Record Lock + Gap Lock。
56
71
57
72
=== 插入意向锁 Insert Intention Lock
58
73
74
+ 在内存中生成的一个锁结构,表示有事务想在某个间隙插入新记录,但是现在处于等待状态。
75
+
76
+ 插入意向锁并不会阻止别的事务继续获取该记录上的任何类型的锁,非常鸡肋。
77
+
59
78
=== 隐式锁
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 16
16
17
17
在 Read Uncommitted 级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为**脏读(Dirty Read)**。性能不会好太多,但是问题却一大堆,实际应用中一般很少使用。
18
18
19
+ 直接读取记录的最新版本,可能出现脏读、不可重复读和幻读等现象。
20
+
19
21
=== Read Committed(提交读)
20
22
21
23
大多数数据库系统的默认隔离级别都是 Read Committed。Read Committed 满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说:一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。有时也叫不可重复读(Nonrepeatable Read)。
22
24
25
+ 在每次执行 `SELECT` 时都生成一个 ReadView,可以避免脏读,但是无法避免不可重复读和幻读。
26
+
23
27
=== Repeatable Read(可重复读)
24
28
25
29
Repeatable Read 解决了脏读的问题。但是还是无法解决领一个**幻读(Phantom Read)**问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB 和 XtraDB 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
26
30
31
+ 只在第一次执行 `SELECT` 语句时,生成一个 ReadView,可以避免出现脏读、不可重复读和幻读。
32
+
27
33
=== Serializable(可串行化)
28
34
29
35
Serializable 是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读问题。简单来说,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