diff --git a/docs/notes/数据库系统原理.md b/docs/notes/数据库系统原理.md
index 7b84e897..8531af97 100644
--- a/docs/notes/数据库系统原理.md
+++ b/docs/notes/数据库系统原理.md
@@ -47,7 +47,7 @@
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
-
+
## ACID
@@ -94,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR
T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
-
+
## 读脏数据
T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
-
+
## 不可重复读
T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
-
+
## 幻影读
T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
-
+
----
@@ -162,17 +162,12 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
各种锁的兼容关系如下:
-| - | X | IX | S | IS |
-| :--: | :--: | :--: | :--: | :--: |
-| **X** |× |× |× | ×|
-| **IX** |× |√ |× | √|
-| **S** |× |× |√ | √|
-| **IS** |× |√ |√ | √|
+
解释如下:
-- 任意 IS/IX 锁之间都是兼容的,因为它们只是表示想要对表加锁,而不是真正加锁;
-- 这里的 X/IX/S/IS 锁都是表级锁,IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
+- 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁;
+- 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
## 封锁协议
@@ -184,20 +179,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
-| T1 | T2 |
-| :--: | :--: |
-| lock-x(A) | |
-| read A=20 | |
-| | lock-x(A) |
-| | wait |
-| write A=19 |. |
-| commit |. |
-| unlock-x(A) |. |
-| | obtain |
-| | read A=19 |
-| | write A=21 |
-| | commit |
-| | unlock-x(A)|
+
**二级封锁协议**
@@ -205,20 +187,8 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
-| T1 | T2 |
-| :--: | :--: |
-| lock-x(A) | |
-| read A=20 | |
-| write A=19 | |
-| | lock-s(A) |
-| | wait |
-| rollback | .|
-| A=20 |. |
-| unlock-x(A) |. |
-| | obtain |
-| | read A=20 |
-| | unlock-s(A)|
-| | commit |
+
+
**三级封锁协议**
@@ -226,26 +196,13 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
-| T1 | T2 |
-| :--: | :--: |
-| lock-s(A) | |
-| read A=20 | |
-| |lock-x(A) |
-| | wait |
-| read A=20| . |
-| commit | .|
-| unlock-s(A) |. |
-| | obtain |
-| | read A=20 |
-| | write A=19|
-| | commit |
-| | unlock-X(A)|
+
### 2. 两段锁协议
加锁和解锁分为两个阶段进行。
-可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。
+可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题。
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
@@ -253,7 +210,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
```
-但不是必要条件,例如以下操作不满足两段锁协议,但是它还是可串行化调度。
+但不是必要条件,例如以下操作不满足两段锁协议,但它还是可串行化调度。
```html
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
diff --git a/notes/pics/image-20191207214442687.png b/notes/pics/image-20191207214442687.png
new file mode 100644
index 00000000..d4babb56
Binary files /dev/null and b/notes/pics/image-20191207214442687.png differ
diff --git a/notes/pics/image-20191207220440451.png b/notes/pics/image-20191207220440451.png
new file mode 100644
index 00000000..fbb4854e
Binary files /dev/null and b/notes/pics/image-20191207220440451.png differ
diff --git a/notes/pics/image-20191207220831843.png b/notes/pics/image-20191207220831843.png
new file mode 100644
index 00000000..0d172aeb
Binary files /dev/null and b/notes/pics/image-20191207220831843.png differ
diff --git a/notes/pics/image-20191207221128997.png b/notes/pics/image-20191207221128997.png
new file mode 100644
index 00000000..c3b256ca
Binary files /dev/null and b/notes/pics/image-20191207221128997.png differ
diff --git a/notes/pics/image-20191207221313819.png b/notes/pics/image-20191207221313819.png
new file mode 100644
index 00000000..38fd7d69
Binary files /dev/null and b/notes/pics/image-20191207221313819.png differ
diff --git a/notes/pics/image-20191207221744244.png b/notes/pics/image-20191207221744244.png
new file mode 100644
index 00000000..32c0ded2
Binary files /dev/null and b/notes/pics/image-20191207221744244.png differ
diff --git a/notes/pics/image-20191207221920368.png b/notes/pics/image-20191207221920368.png
new file mode 100644
index 00000000..c1df6edb
Binary files /dev/null and b/notes/pics/image-20191207221920368.png differ
diff --git a/notes/pics/image-20191207222102010.png b/notes/pics/image-20191207222102010.png
new file mode 100644
index 00000000..a0d37b69
Binary files /dev/null and b/notes/pics/image-20191207222102010.png differ
diff --git a/notes/pics/image-20191207222134306.png b/notes/pics/image-20191207222134306.png
new file mode 100644
index 00000000..3a30fe59
Binary files /dev/null and b/notes/pics/image-20191207222134306.png differ
diff --git a/notes/pics/image-20191207222237925.png b/notes/pics/image-20191207222237925.png
new file mode 100644
index 00000000..4199f624
Binary files /dev/null and b/notes/pics/image-20191207222237925.png differ
diff --git a/notes/数据库系统原理.md b/notes/数据库系统原理.md
index 7b84e897..8531af97 100644
--- a/notes/数据库系统原理.md
+++ b/notes/数据库系统原理.md
@@ -47,7 +47,7 @@
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
-
+
## ACID
@@ -94,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR
T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
-
+
## 读脏数据
T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
-
+
## 不可重复读
T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
-
+
## 幻影读
T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
-
+
----
@@ -162,17 +162,12 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
各种锁的兼容关系如下:
-| - | X | IX | S | IS |
-| :--: | :--: | :--: | :--: | :--: |
-| **X** |× |× |× | ×|
-| **IX** |× |√ |× | √|
-| **S** |× |× |√ | √|
-| **IS** |× |√ |√ | √|
+
解释如下:
-- 任意 IS/IX 锁之间都是兼容的,因为它们只是表示想要对表加锁,而不是真正加锁;
-- 这里的 X/IX/S/IS 锁都是表级锁,IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
+- 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁;
+- 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T1 想要对数据行 R1 加 X 锁,事务 T2 想要对同一个表的数据行 R2 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
## 封锁协议
@@ -184,20 +179,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
-| T1 | T2 |
-| :--: | :--: |
-| lock-x(A) | |
-| read A=20 | |
-| | lock-x(A) |
-| | wait |
-| write A=19 |. |
-| commit |. |
-| unlock-x(A) |. |
-| | obtain |
-| | read A=19 |
-| | write A=21 |
-| | commit |
-| | unlock-x(A)|
+
**二级封锁协议**
@@ -205,20 +187,8 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
-| T1 | T2 |
-| :--: | :--: |
-| lock-x(A) | |
-| read A=20 | |
-| write A=19 | |
-| | lock-s(A) |
-| | wait |
-| rollback | .|
-| A=20 |. |
-| unlock-x(A) |. |
-| | obtain |
-| | read A=20 |
-| | unlock-s(A)|
-| | commit |
+
+
**三级封锁协议**
@@ -226,26 +196,13 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
-| T1 | T2 |
-| :--: | :--: |
-| lock-s(A) | |
-| read A=20 | |
-| |lock-x(A) |
-| | wait |
-| read A=20| . |
-| commit | .|
-| unlock-s(A) |. |
-| | obtain |
-| | read A=20 |
-| | write A=19|
-| | commit |
-| | unlock-X(A)|
+
### 2. 两段锁协议
加锁和解锁分为两个阶段进行。
-可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。
+可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题。
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
@@ -253,7 +210,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
```
-但不是必要条件,例如以下操作不满足两段锁协议,但是它还是可串行化调度。
+但不是必要条件,例如以下操作不满足两段锁协议,但它还是可串行化调度。
```html
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)