auto commit
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
|
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207211851299.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222237925.png"/> </div><br>
|
||||||
|
|
||||||
## ACID
|
## ACID
|
||||||
|
|
||||||
@ -94,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR
|
|||||||
|
|
||||||
T<sub>1</sub> 和 T<sub>2</sub> 两个事务都对一个数据进行修改,T<sub>1</sub> 先修改,T<sub>2</sub> 随后修改,T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改。
|
T<sub>1</sub> 和 T<sub>2</sub> 两个事务都对一个数据进行修改,T<sub>1</sub> 先修改,T<sub>2</sub> 随后修改,T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207205105044.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221744244.png"/> </div><br>
|
||||||
|
|
||||||
## 读脏数据
|
## 读脏数据
|
||||||
|
|
||||||
T<sub>1</sub> 修改一个数据,T<sub>2</sub> 随后读取这个数据。如果 T<sub>1</sub> 撤销了这次修改,那么 T<sub>2</sub> 读取的数据是脏数据。
|
T<sub>1</sub> 修改一个数据,T<sub>2</sub> 随后读取这个数据。如果 T<sub>1</sub> 撤销了这次修改,那么 T<sub>2</sub> 读取的数据是脏数据。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207205339747.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221920368.png"/> </div><br>
|
||||||
|
|
||||||
## 不可重复读
|
## 不可重复读
|
||||||
|
|
||||||
T<sub>2</sub> 读取一个数据,T<sub>1</sub> 对该数据做了修改。如果 T<sub>2</sub> 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
|
T<sub>2</sub> 读取一个数据,T<sub>1</sub> 对该数据做了修改。如果 T<sub>2</sub> 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207210118304.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222102010.png"/> </div><br>
|
||||||
|
|
||||||
## 幻影读
|
## 幻影读
|
||||||
|
|
||||||
T<sub>1</sub> 读取某个范围的数据,T<sub>2</sub> 在这个范围内插入新的数据,T<sub>1</sub> 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
|
T<sub>1</sub> 读取某个范围的数据,T<sub>2</sub> 在这个范围内插入新的数据,T<sub>1</sub> 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207210802815.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222134306.png"/> </div><br>
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -162,17 +162,12 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
|
|
||||||
各种锁的兼容关系如下:
|
各种锁的兼容关系如下:
|
||||||
|
|
||||||
| - | X | IX | S | IS |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207214442687.png"/> </div><br>
|
||||||
| :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| **X** |× |× |× | ×|
|
|
||||||
| **IX** |× |√ |× | √|
|
|
||||||
| **S** |× |× |√ | √|
|
|
||||||
| **IS** |× |√ |√ | √|
|
|
||||||
|
|
||||||
解释如下:
|
解释如下:
|
||||||
|
|
||||||
- 任意 IS/IX 锁之间都是兼容的,因为它们只是表示想要对表加锁,而不是真正加锁;
|
- 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁;
|
||||||
- 这里的 X/IX/S/IS 锁都是表级锁,IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T<sub>1</sub> 想要对数据行 R<sub>1</sub> 加 X 锁,事务 T<sub>2</sub> 想要对同一个表的数据行 R<sub>2</sub> 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
|
- 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T<sub>1</sub> 想要对数据行 R<sub>1</sub> 加 X 锁,事务 T<sub>2</sub> 想要对同一个表的数据行 R<sub>2</sub> 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
|
||||||
|
|
||||||
## 封锁协议
|
## 封锁协议
|
||||||
|
|
||||||
@ -184,20 +179,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
|
|
||||||
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
|
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207220440451.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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 锁了,也就是不会读入数据。
|
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207220831843.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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 锁,从而避免了在读的期间数据发生改变。
|
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221313819.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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. 两段锁协议
|
### 2. 两段锁协议
|
||||||
|
|
||||||
加锁和解锁分为两个阶段进行。
|
加锁和解锁分为两个阶段进行。
|
||||||
|
|
||||||
可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。
|
可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题。
|
||||||
|
|
||||||
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
|
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
|
||||||
|
|
||||||
@ -253,7 +210,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
|
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
|
||||||
```
|
```
|
||||||
|
|
||||||
但不是必要条件,例如以下操作不满足两段锁协议,但是它还是可串行化调度。
|
但不是必要条件,例如以下操作不满足两段锁协议,但它还是可串行化调度。
|
||||||
|
|
||||||
```html
|
```html
|
||||||
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
|
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
|
||||||
|
BIN
notes/pics/image-20191207214442687.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
notes/pics/image-20191207220440451.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
notes/pics/image-20191207220831843.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
notes/pics/image-20191207221128997.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
notes/pics/image-20191207221313819.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
notes/pics/image-20191207221744244.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
notes/pics/image-20191207221920368.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
notes/pics/image-20191207222102010.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
notes/pics/image-20191207222134306.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
notes/pics/image-20191207222237925.png
Normal file
After Width: | Height: | Size: 46 KiB |
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
|
事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207211851299.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222237925.png"/> </div><br>
|
||||||
|
|
||||||
## ACID
|
## ACID
|
||||||
|
|
||||||
@ -94,25 +94,25 @@ MySQL 默认采用自动提交模式。也就是说,如果不显式使用`STAR
|
|||||||
|
|
||||||
T<sub>1</sub> 和 T<sub>2</sub> 两个事务都对一个数据进行修改,T<sub>1</sub> 先修改,T<sub>2</sub> 随后修改,T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改。
|
T<sub>1</sub> 和 T<sub>2</sub> 两个事务都对一个数据进行修改,T<sub>1</sub> 先修改,T<sub>2</sub> 随后修改,T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207205105044.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221744244.png"/> </div><br>
|
||||||
|
|
||||||
## 读脏数据
|
## 读脏数据
|
||||||
|
|
||||||
T<sub>1</sub> 修改一个数据,T<sub>2</sub> 随后读取这个数据。如果 T<sub>1</sub> 撤销了这次修改,那么 T<sub>2</sub> 读取的数据是脏数据。
|
T<sub>1</sub> 修改一个数据,T<sub>2</sub> 随后读取这个数据。如果 T<sub>1</sub> 撤销了这次修改,那么 T<sub>2</sub> 读取的数据是脏数据。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207205339747.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221920368.png"/> </div><br>
|
||||||
|
|
||||||
## 不可重复读
|
## 不可重复读
|
||||||
|
|
||||||
T<sub>2</sub> 读取一个数据,T<sub>1</sub> 对该数据做了修改。如果 T<sub>2</sub> 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
|
T<sub>2</sub> 读取一个数据,T<sub>1</sub> 对该数据做了修改。如果 T<sub>2</sub> 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207210118304.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222102010.png"/> </div><br>
|
||||||
|
|
||||||
## 幻影读
|
## 幻影读
|
||||||
|
|
||||||
T<sub>1</sub> 读取某个范围的数据,T<sub>2</sub> 在这个范围内插入新的数据,T<sub>1</sub> 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
|
T<sub>1</sub> 读取某个范围的数据,T<sub>2</sub> 在这个范围内插入新的数据,T<sub>1</sub> 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
|
||||||
|
|
||||||
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207210802815.png"/> </div><br>
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207222134306.png"/> </div><br>
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -162,17 +162,12 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
|
|
||||||
各种锁的兼容关系如下:
|
各种锁的兼容关系如下:
|
||||||
|
|
||||||
| - | X | IX | S | IS |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207214442687.png"/> </div><br>
|
||||||
| :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| **X** |× |× |× | ×|
|
|
||||||
| **IX** |× |√ |× | √|
|
|
||||||
| **S** |× |× |√ | √|
|
|
||||||
| **IS** |× |√ |√ | √|
|
|
||||||
|
|
||||||
解释如下:
|
解释如下:
|
||||||
|
|
||||||
- 任意 IS/IX 锁之间都是兼容的,因为它们只是表示想要对表加锁,而不是真正加锁;
|
- 任意 IS/IX 锁之间都是兼容的,因为它们只表示想要对表加锁,而不是真正加锁;
|
||||||
- 这里的 X/IX/S/IS 锁都是表级锁,IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T<sub>1</sub> 想要对数据行 R<sub>1</sub> 加 X 锁,事务 T<sub>2</sub> 想要对同一个表的数据行 R<sub>2</sub> 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
|
- 这里兼容关系针对的是表级锁,而表级的 IX 锁和行级的 X 锁兼容,两个事务可以对两个数据行加 X 锁。(事务 T<sub>1</sub> 想要对数据行 R<sub>1</sub> 加 X 锁,事务 T<sub>2</sub> 想要对同一个表的数据行 R<sub>2</sub> 加 X 锁,两个事务都需要对该表加 IX 锁,但是 IX 锁是兼容的,并且 IX 锁与行级的 X 锁也是兼容的,因此两个事务都能加锁成功,对同一个表中的两个数据行做修改。)
|
||||||
|
|
||||||
## 封锁协议
|
## 封锁协议
|
||||||
|
|
||||||
@ -184,20 +179,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
|
|
||||||
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
|
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207220440451.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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 锁了,也就是不会读入数据。
|
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207220831843.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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 锁,从而避免了在读的期间数据发生改变。
|
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
|
||||||
|
|
||||||
| T<sub>1</sub> | T<sub>2</sub> |
|
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/image-20191207221313819.png"/> </div><br>
|
||||||
| :--: | :--: |
|
|
||||||
| 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. 两段锁协议
|
### 2. 两段锁协议
|
||||||
|
|
||||||
加锁和解锁分为两个阶段进行。
|
加锁和解锁分为两个阶段进行。
|
||||||
|
|
||||||
可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。
|
可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。串行执行的事务互不干扰,不会出现并发一致性问题。
|
||||||
|
|
||||||
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
|
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
|
||||||
|
|
||||||
@ -253,7 +210,7 @@ MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
|
|||||||
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
|
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
|
||||||
```
|
```
|
||||||
|
|
||||||
但不是必要条件,例如以下操作不满足两段锁协议,但是它还是可串行化调度。
|
但不是必要条件,例如以下操作不满足两段锁协议,但它还是可串行化调度。
|
||||||
|
|
||||||
```html
|
```html
|
||||||
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
|
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
|
||||||
|