数据库事物四种特性的理解

事务

参考: 彻底理解数据库事务


事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在计算机术语中,事务通常就是指数据库事务。

事务是将一组读写操作组合在一起形成一个逻辑单元。这些操作要么全部执行成功提交(commit),要么全部中止失败(abort,rollback),不会留下一个中间状态的烂摊子。所以,失败后程序可以安全的重试,分析原因等。 相反,如果没有对事务的支持,数据库可能持久化很多中间状态,留下无法解释的业务,开发人员处理起来也很麻烦。所以,事务是为了简化编程,提供数据安全/正确性/一致性。当然,任何便利都是有代价的,事务也有一些问题,所以NoSQL数据库,分布式数据库在某种程度上会弱化事务。有些甚至完全放弃事务。

概念

一个数据库事务通常包含对数据库进行读或写的一个操作序列。它的存在包含有以下两个目的:

1、为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
2、当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

当一个事务被提交给了DBMS(数据库管理系统),则DBMS需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中,如果事务中有的操作没有成功完成,则事务中的所有操作都需要被回滚,回到事务执行前的状态(要么全执行,要么全都不执行);同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行。

但在现实情况下,失败的风险很高。在一个数据库事务的执行过程中,有可能会遇上事务操作失败、数据库系统/操作系统失败,甚至是存储介质失败等情况。这便需要DBMS对一个执行失败的事务执行恢复操作,将其数据库状态恢复到一致状态(数据的一致性得到保证的状态)。为了实现将数据库状态恢复到一致状态的功能,DBMS通常需要维护事务日志以追踪事务中所有影响数据库数据的操作。

特性

并非任意的对数据库的操作序列都是数据库事务。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。

这里的原子性更多的是表达失败和成功的结果。
当有多次写入的时候,中间可能会出现各种问题(进程崩溃,断电,网络故障,硬盘满,违反约束等),如果这些操作被分配到一个事务中, 那么提交(commit)动作会失败,事务随即中止,但是数据库会保证故障之前对系统做的任何修改,写入都被撤销。
随后,可以安全地重试失败的事务。

  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。

所有的规则必须应用到事务的修改上,以便维护所有数据的完整性。

事务可以不同程度的一致性:
强一致性:读操作可以立即读到提交的更新操作。
弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。
最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。

其他一致性变体还有:
单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。
会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。

当多个客户端同时访问数据库的同一对象时,就会有并发问题,或者叫竞态条件(race condition)。
隔离性保证同时执行的事务是相互隔离的,它们不能互相影响。简言之,一个事务只能看到另一个事务开始之前或者结束之后的结果,不能看到任何中间状态。
隔离性分好几种级别,每一种隔离级别都在权衡性能和某种安全保障。

  • 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

持久性保证当用户提交事务并完成后,数据最终会被永久安全地保存到磁盘中,而不管是否发生故障或者系统崩溃。在单节点的数据库中,通过日志,可以保证系统在崩溃之后起来,依然能够自动完成一致性和持久化的要求(rollforward,rollback)。通过归档日志,当磁盘损坏后,还能恢复到某个时间点。为了进一步保证持久性,对日志和归档日志可以进行多副本设置。
当然,没有完美的持久性,如果由于机房起火,所有数据(备份,日志等)都销毁。所以,更严格的保证可以通过异地备份实现,但也不是完美的。

举例

用一个常用的“A账户向B账号汇钱”的例子来说明如何通过数据库事务保证数据的准确性和完整性。熟悉关系型数据库事务的都知道从帐号A到帐号B需要6个操作:
1、从A账号中把余额读出来(500)。
2、对A账号做减法操作(500-100)。
3、把结果写回A账号中(400)。
4、从B账号中把余额读出来(500)。
5、对B账号做加法操作(500+100)。
6、把结果写回B账号中(600)。

原子性:
保证1-6所有过程要么都执行,要么都不执行。一旦在执行某一步骤的过程中发生问题,就需要执行回滚操作。 假如执行到第五步的时候,B账户突然不可用(比如被注销),那么之前的所有操作都应该回滚到执行事务之前的状态。

一致性 :
在转账之前,A和B的账户中共有500+500=1000元钱。在转账之后,A和B的账户中共有400+600=1000元。也就是说,数据的状态在执行该事务操作之后从一个状态改变到了另外一个状态。同时一致性还能保证账户余额不会变成负数等。

隔离性 :
在A向B转账的整个过程中,只要事务还没有提交(commit),查询A账户和B账户的时候,两个账户里面的钱的数量都不会有变化。
如果在A给B转账的同时,有另外一个事务执行了C给B转账的操作,那么当两个事务都结束的时候,B账户里面的钱应该是A转给B的钱加上C转给B的钱再加上自己原有的钱。

持久性 :
一旦转账成功(事务提交),两个账户的里面的钱就会真的发生变化(会把数据写入数据库做持久化保存)!


备注:

  • 一致性更强调一个事物的完整
  • 隔离性强调的是不同事物间的并发处理。

一致性包括两方面:

1.数据库机制层面

数据库层面的一致性是,在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,Check约束等)和触发器设置.这一点是由SQL SERVER进行保证的.

2.业务层面

对于业务层面来说,一致性是保持业务的一致性.这个业务一致性需要由开发人员进行保证.很多业务方面的一致性可以通过转移到数据库机制层面进行保证.比如,产品只有两个型号,则可以转移到使用CHECK约束使某一列必须只能存这两个型号.

你可能感兴趣的:(数据库)