Home  >  Article  >  Database  >  概念回忆数据库事务

概念回忆数据库事务

WBOY
WBOYOriginal
2016-06-07 14:59:391169browse

本文内容 事务 ACID 特征 并发调度——隔离级别 加锁机制 加锁协议 数据库事务,简称事务,是一组按顺序执行的操作单元。 事务 ACID 特征 事务有四个特征,称为 ACID: 原子性(Atomic)- 事务必须同时成功或同时失败。 比如,ATM 取钱和记入客户账户是一个

本文内容

  • 事务 ACID 特征
  • 并发调度——隔离级别
  • 加锁机制
  • 加锁协议

数据库事务,简称事务,是一组按顺序执行的操作单元。

 

事务 ACID 特征


事务有四个特征,称为 ACID:

  • 原子性(Atomic)- 事务必须同时成功或同时失败。

比如,ATM 取钱和记入客户账户是一个原子事务。如果 ATM 只是吐出钱,而未记入账户,或是已记入账户,但没有吐出钱。这两种情况都是不允许的。

  • 一致性(Consistency)- 事务必须遵循某个规则或法律协议系统。简单说,就是符合我们的所有期望。

事务必须以一种遵循系统规则的方式,成功地选择、插入、更新或删除记录。不遵循规则的事务,不能提交。如果没有绝对的规则,则持久性(数据完整性)将没有保证。比如,航班数据库,一个座位不能分配给两名不同的乘客。这就是一个一致性。在事务处理过程中的某个时刻,乘客之间可能需要调换座位,这可能会违背这个约束。但事务结束后,事务必须保证数据库满足所有的一致性条件。

  • 隔离性(Isolation)- 用户不能看到其他用户的事务,直到那些事务全部完成并提交。

事务并发时,一个事务不应影响其他事务。事务之间是隔离的。比如,两个机票售票口,正在出售同一个航班的座位,而该航班只剩下一个座位,那么,只能满足一个售票口的请求,而拒绝另一个。如果由于并发操作而导致同一个座位卖给了两位乘客,或是没卖出去,都是不允许的。

  • 持久性(Durability)- 事务必须持久有效。

事务一旦被提交,即使系统出现故障,也要保证事务的结果不能丢失。许多灾难性条件可能导致记录无法永久性保存到磁盘,包括电源、网络、系统和硬盘等设备的失败。数据丢失还可能由于心怀不满的员工或黑客的恶意操作引起。

但是,持久性不是自动化过程。DBA的主要职责之一就是创建并维护数据恢复策略。

James Nicholas Gray、Theo Haerder 和 Andreas Reuter 这三人为术语“数据库 ACID 测试”做出了很大贡献。

  • James Nicholas Gray。他早在 1981 年,就为 Tandem Computers, Inc. 公司编写了白皮书 "The Transaction Concept: Virtues and Limitations"。在这篇文章中,Gray 认为事务应该是合法的、绑定的,并且必须具备如下特征:一致性、原子性、持久性。最后,他大致定义了提交(commit)、回滚(rollback)、取消(undo)和重做(redo)日志文件。这篇文章在当时很有前瞻性的,对现代数据库系统的影响非常显著。
  • Theo Haerder 和 Andreas Reuter 为美国计算机协会(Association for Computing Machinery,ACM)写了一篇后续文章,题为 "Principles of Transaction-Oriented Database Recovery"。在这篇文章中,他们进一步扩展了 Gray的思想,增加了“事务必须相互隔离”的思想。新的事物特性如下:原子性、一致性、隔离性、持久性。

 

并发调度——隔离级别


如果对并发操作不进行合理调度,那么,会破坏事务 ACID 特性。可能会带来如下问题:

  • 影子读取(丢失修改):一个事务读取了另一个事务已提交的数据。

例如,假设,两个事务 T1 和 T2:

事务 T1 和 T2 都从数据库读入同一记录,并各自修改数据,在两个事务都完成了读入数据的操作以后,T1 先完成修改操作,并将更新的数据写回数据库。

随后,T2 也完成了修改,并将结果写回数据库,这样就覆盖了 T1 的操作结果,导致 T1 对该数据的修改好像从未发生过。

这种情形称为“丢失修改”。

  • 脏读取(dirty read):一个事务读取了未提交的事务。

例如,假设,两个事务 T1 和 T2:

事务 T1 修改了某个数据,并将其写回数据库。事务 T2 随之读入这个被 T1 修改过的数据,之后 T1 出于某种原因又撤销了,它所修改的数据被恢复。

这时,T2 所读取的数据就与数据库中的数据不同。

这种情形称为“脏读取”。

  • 不可重复读取(non-repeatable read):一个事务多次读取同一个数据的返回结果不同。

例如,假设,两个事务 T1 和 T2:

事务 T1 按一定条件从数据库读取某些数据。随后,事务 T2 对其进行修改,并将其结果写回数据库。当 T1 再次按同一条件读取数据时,结果发现已经跟刚才不一样了。有些可能发生改变,有些可能已经删除,还可能增加了某些数据。

这种情况称为“不可重复读取”。

为了解决事务之间并发带来的问题,必须在事务之间建立隔离关系。如果应用程序使用完全隔离的事务,那么,同时执行多个事务的效果将完全等效于串行(一个接一个地)执行。隔离级别如下表所示。

隔离级别

脏读

不可重复读取

影子读取

描述

可序列化

(SERIALIZABLE)

不可能

不可能

不可能

最严格的级别。事务串行执行,资源消耗最大

可重复读取

(REPEATABLE READ)

不可能

不可能

可能

读取数据的事务允许其他事务继续访问该行数据,但未提交的写事务将会禁止其他事务访问该行。避免“脏读取”和“不可重复读取”,只是带来更多的性能损失

未提交读取

(READ UNCOMMITED)

不可能

可能

可能

最低的事务隔离级别,保证读取过程中不会读取到非法数据

 

提交读取

(READ COMMITTED)

 

可能

可能

可能

大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统

 

加锁机制


数据库采用锁机制来实现事务隔离。

  • 共享锁(share lock,S 锁,读锁):共享锁用于读取数据操作,它允许其他事务同时读取某锁定的资源,但不允许其他事务更新它——可以读,但不能改。

例如,事务 T 对数据 A 加了 S 锁,则 T 就可以对 A 进行读取,但不能修改;在 T 释放 A 上的 S 锁前,其他事务可以再对 A 加 S 锁,但不能加 X 锁,这样,可以读取 A,但不能修改 A。

  • 排他锁(exclusive lock,X 锁,写锁):排它锁用于修改数据的场合。它锁定的资源,其他事务不能读取也不能修改——读都不让,更不用说改。

例如,若事务 T 对数据 A 加了 X 锁,则 T 就可以对 A 进行读取,以及修改 A;在 T 释放 A 上的 X 锁前,任何事务都不能对 A 加任何类型的锁,这样也就不能读取和修改 A。

 

加锁协议


为了保证并发控制的正确性,在使用加锁机制时,必须遵循一定原则,如何时申请 X 锁或 S 锁,何时释放锁等。不同的加锁协议(locking protocol)约定不同——保证数据一致性的三级锁协议和保证并行调度的两段锁(two-phase locking)协议,为并发提供不同程度的保证。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn