Skip to content

Commit

Permalink
修改 事务隔离级别 && 封锁协议
Browse files Browse the repository at this point in the history
  • Loading branch information
HaoyangShi committed Oct 20, 2016
1 parent 20f3fab commit 38b1847
Showing 1 changed file with 26 additions and 32 deletions.
58 changes: 26 additions & 32 deletions basic/database/transaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,71 +26,65 @@

并发控制的主要方法是封锁(Locking)。

### 封锁

数据库系统提供两种锁:

- 排他锁(写锁):若事务T对数据对象A加写锁,则只允许T读取和修改A,其他事务都不能再对A加任何类型的锁,直到T释放A上的锁为止。
### 读写异常

- 共享锁(读锁):若事务T对数据对象A加读锁,则只允许T可以读取但不能修改A,其他事务只能再对A加读锁,而不能加写锁,直到T释放A上的读锁为止。
数据库是要被广大客户所共享访问的,那么在数据库操作过程中很可能出现以下几种不确定情况:

### 封锁协议
- **丢失修改**:两个事务T1,T2读入同一数据并修改,T2提交的结果被T1破坏了,导致T1的修改丢失。(订票系统)

使用读锁和写锁时,需要约定一定的规则。比如:何时申请、持续时间、何时释放等。这些规则被称为封锁协议。针对不同的事务隔离级别,有不同的封锁协议
- **不可重复读**:事务T1读取数据后,事务T2执行更新操作,使T1无法再次读取结果

- 一级封锁协议:事务T在修改数据R之前必须先对其加写锁,直到事务结束才释放。一级封锁协议防止了丢失修改,但不能保证可重复读和不读脏数据。
- 二级封锁协议:在一级封锁协议的基础上增加事务T在读数据R前必须加读锁,读完就可以释放。二级封锁协议进一步防止读脏数据,但不能保证可重复读。
- 三级封锁协议:一级封锁协议的基础上增加事务T在读数据R前必须加读锁,直到事务结束才释放。三阶封锁协议除了防止丢失修改和读脏数据外,进一步防止了不可重复读。
- **读脏数据**:事务T1修改某个数据并写回磁盘,事务T2读取同一数据,但T1由于某种原因撤销了,这时T1修改过的数据恢复原来的值,T2读取的数据就与数据库中的数据不一致。

### 读写异常
- **幻读**:事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据(这里并不要求两次查询SQL语句相同)**这是因为在两次查询过程中有另外一个事务插入数据造成的**

数据库并发操作存在的异常情况:

- 丢失修改:两个事务T1,T2读入同一数据并修改,T2提交的结果被T1破坏了,导致T1的修改丢失。(订票系统)
### 封锁

- 不可重复读:事务T1读取数据后,事务T2执行更新操作,使T1无法再次读取结果。
封锁是实现并发控制的一个非常重要的技术,所谓 **封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁**。数据库系统提供两种锁:

- 读脏数据:事务T1修改某个数据并写回磁盘,事务T2读取同一数据,但T1由于某种原因撤销了,这时T1修改过的数据恢复原来的值,T2读取的数据就与数据库中的数据不一致
- **排他锁(写锁)**:若事务T对数据对象A加写锁,则只允许T读取和修改A,其他事务都不能再对A加任何类型的锁,直到T释放A上的锁为止

- 幻读:事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据(这里并不要求两次查询SQL语句相同**这是因为在两次查询过程中有另外一个事务插入数据造成的**
- **共享锁(读锁**:若事务T对数据对象A加读锁,则只允许T可以读取但不能修改A,其他事务只能再对A加读锁,而不能加写锁,直到T释放A上的读锁为止

### 事务隔离级别

为了避免上面出现几种情况在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同 。

#### 可序列化(Serializable)
#### 未提交读(Read Uncommitted)

最高的隔离级别
未提交读(READ UNCOMMITTED)是最低的隔离级别。**允许脏读(dirty reads),但不允许更新丢失,事务可以看到其他事务“尚未提交”的修改**

在基于锁机制并发控制的DBMS实现可序列化,要求在选定对象上的读锁和写锁保持直到事务结束后才能释放。在SELECT 的查询中使用一个“WHERE”子句来描述一个范围时应该获得一个“范围锁(range-locks)”。这种机制可以避免“幻影读(phantom reads)”现象(详见下文)。
#### 提交读(Read Committed)

当采用不基于锁的并发控制时不用获取锁。但当系统探测到几个并发事务有“写冲突”的时候,只有其中一个是允许提交的。这种机制的详细描述见“快照隔离”
**允许不可重复读取,但不允许脏读取**。这可以通过“瞬间共享读锁”和“排他写锁”实现。**读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行**

#### 可重复读
#### 可重复读(Repeatable Read)

在可重复读(REPEATABLE READS)隔离级别中,基于锁机制并发控制的DBMS需要对选定对象的读锁(read locks)和写锁(write locks)一直保持到事务结束,但不要求“范围锁(range-locks)”,因此可能会发生“幻影读(phantom reads)”
**禁止不可重复读取和脏读取,但是有时可能出现幻读数据**。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务

#### 提交读
#### 可序列化(Serializable)

在提交读级别中,基于锁机制并发控制的DBMS需要对选定对象的写锁一直保持到事务结束,但是读锁在SELECT操作完成后马上释放(因此“不可重复读”现象可能会发生)。和前一种隔离级别一样,也不要求“范围锁”
最高的隔离级别,**它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行**。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到

简而言之,提交读这种隔离级别保证了读到的任何数据都是提交的数据,避免读到中间的未提交的数据,脏读(dirty reads)。但是不保证事务重新读的时候能读到相同的数据,因为在每次数据读完之后其他事务可以修改刚才读到的数据
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大

#### 未提交读
### 封锁协议

未提交读(READ UNCOMMITTED)是最低的隔离级别。允许脏读(dirty reads),事务可以看到其他事务“尚未提交”的修改
使用读锁和写锁时,需要约定一定的规则。比如:何时申请、持续时间、何时释放等。这些规则被称为 *封锁协议*。针对不同的事务隔离级别,有不同的封锁协议

通过比低一级的隔离级别要求更多的限制,高一级的级别提供更强的隔离性。标准允许事务运行在更强的事务隔离级别上。(如在可重复读(REPEATABLE READS)隔离级别上执行提交读(READ COMMITTED)的事务是没有问题的)
- **一级封锁协议**:事务T在修改数据R之前必须先对其加写锁,直到事务结束才释放。一级封锁协议防止了丢失修改,但不能保证可重复读和不读脏数据。
- **二级封锁协议**:在一级封锁协议的基础上增加事务T在读数据R前必须加读锁,读完就可以释放。二级封锁协议进一步防止读脏数据,但不能保证可重复读。
- **三级封锁协议**:一级封锁协议的基础上增加事务T在读数据R前必须加读锁,直到事务结束才释放。三阶封锁协议除了防止丢失修改和读脏数据外,进一步防止了不可重复读。
- **四级封锁协议**:四级封锁协议是对三级封锁协议的增强,其实现机制也最为简单,直接对事务中所读取或者更改的数据所在的表加表锁,也就是说,其他事务不能 *读写* 该表中的任何数据。

## 并行调度

调度是一个或多个事务的重要操作按时间排序的一个序列。如果一个调度的动作首先是一个事务的所有动作,然后是另一个事务的所有动作,以此类推,而没有动作的混合,那么我们说这一调度是串行的。

事务的正确性原则告诉我们,每个串行调度都将保持数据库状态的一致性。 通常,不管数据库初态怎样,一个调度对数据库状态的影响都和某个串行调度相同,我们就说这个调度是可串行化的。

可串行性是并行调度正确性的唯一准则,两段锁(简称2PL)协议是为保证并行调度可串行性而提供的封锁协议。两段锁协议规定:

在对任何数据进行读、写操作之前,事务道首先要获得对该数据的封锁,而且在释放一个封锁之生,事务不再获得任何其他封锁。
**可串行性是并行调度正确性的唯一准则,两段锁(简称2PL)协议是为保证并行调度可串行性而提供的封锁协议**。两段锁协议规定:在对任何数据进行读、写操作之前,事务道首先要获得对该数据的封锁,而且在释放一个封锁之生,事务不再获得任何其他封锁。

所谓“两段”锁的含义是:**事务分为两个阶段,第一阶段是获得封锁,也称为扩展阶段,第二阶段是释放封锁,也称为收缩阶段**

Expand Down

0 comments on commit 38b1847

Please sign in to comment.