一:事务的定义

事务是一个操作序列,要么执行所有操作要么都不执行,是一个不可分割的工作单位

二:ACID

  1. ACID是可靠的数据库管理系统(DBMS),事务所应该具有的四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(LsoLation)、持久性(Durability

2.1:原子性

原子性是事务中的一个不可在分割的工作单位,事务中的操作要么都发生,要么都不发生

例如:汇款事件————A向B汇款

事务中的扣款和加款的两条语句,要么都执行要么都不执行。如果没有原子性,那遇到了异常情况只执行了扣款语句,就提交成功,A成功扣款且B没有加款,就会引起纠纷

解决办法

`在数据库管理系统中(DBMS),默认情况的一条SQL就是一个单独事务,且自动提交`。只有显示的使用start transaction开启一个事务,才可以将一个代码放在事务中执行。`保障事务的原子性是数据库管理系统的责任`,所以许多的数据源采用的日志机制。比如SQL server使用一个预写事务日志,在将数据提交到实际数据页面前,会先写在事务日志上

2.2:一致性

一致性是在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。就是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性

例如:A有50元,B有50元,A向B转账20元。不管事务是否成功,在事务结束之后A与B的总和应该为100元

解决方法

1.数据库机制层面

`数据库层面的一致性是指在一个事务执行之前和之后,数据会符合设置的约束(唯一约束&外键约束&check约束等)和触发器设置。这个是由SQL server来进行保证的`,比如转账,就可以使用CHECK约束两个账户之间的总和为100来达到一致性

2.业务层面

`对于业务层面来说,一致性就是保持业务的一致性`。一般需要由开发人员进行保证,很多业务方面的一致性,也可以通过转移到数据库机制层面进行保证

2.3:隔离性

`隔离性是指,多个事务并发访问的时候,事务之间是隔离的,一个事务不应该影响其他事务的运行效果`。

这是指在并发环境中,当不同的事务同时提供操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是修改之后的状态,而不是在中间状态的数据

在Window中,多个进程同时对一个文件进行修改是不允许的,Windows通过这种方式来保证不同进程的隔离性

在企业开发中,事务最复杂问题都是由事务隔离性引起的。`当多个事务并发时,SQL server利用加锁和阻塞来保证事务之间的不同等级的隔离性。一般情况下完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能`。想要理解SQL server中对于隔离性的保障,首先来了解一下事务之间是如何干扰的:

1.事物之间的相互影响

事物之间的相互影响分为几种:脏读、不可重复读、幻读、丢失更新

1.1脏读

脏读就是指A事务读取了B事务在进行中且未提交的数据,但是B事务的数据是有可能进行回滚的,如果B事务进行了回滚,那么读取了数据的A事务所操作的项目大概就会出现损失

1.2不可重复读

不可重复读意味着在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交引起的,A事务查询Tom的账户余额,B事务给Tom的账户减少了100元,A事务在同一个事务中再次查询Tom的账户余额,同一个事务中的两次查询得到的账户余额并不相同

1.3幻读(虚读)

幻读是指事务不是独立执行时发生的一种现象。如A事务向一个表中的数据进行修改,删除这个表的所有数据,这个操作就涉及到了表中的全部数据行。同时,在一定的时间差内,B事务也去修改这个表中的数据,向表中插入一行新的数据。那么,以后A事务的用户对表进行查询的时候就会发现表中还有一行没有删除的数据,就好像发生了幻觉

1.4丢失更新

两个事务同时读取同一条记录,A先修改记录,B也修改记录(B并不知道A进行过修改),B提交数据后B的修改结果覆盖了A的修改结果。

理解SQL server中的隔离级别

数据库的事务隔离规则(TRANSACTION ISOLATION LEVEL)是一个数据库上很基本的一个概念。`事务隔离级别的前提是一个多用户、多进程、多线程的并发系统,在这个系统中为了保证数据的一致性和完整性,引入了事务隔离级别这个概念`。对于一个单用户、单进程、单线程的应用来说就不存在这个问题

为了避免上述几种事务之间的影响,SQL server通过设置不同的隔离级别来进行不同程度的避免。`因为高的隔离等级以为着更多的锁,会牺牲性能`,所以这个选项是一个给用户开放选择,根据具体需求来进行设置,不过默认的隔离级别Read Commited符合多数的实际需求

`SQL server隔离事务之间的影响是通过锁来实现的,通过阻塞来阻止上述的影响`。不同的隔离级别是通过加不同的锁,来造成阻塞实现的,所以会付出性能作为代价。安全级别越高,处理效果就会越低。安全级别越低,效率就会越高。

使用方法:`SET TRANSACTIONISOLATION LEVEL REPEATABLE READ`

`未提交读:在读数据时不会检查或使用任何锁。因此,在这种隔离级别中可能读取到没有提交的数据`

`已提交读:只读取提交的数据并等待其他事务释放排它锁。读数据的共享锁在读操作完成后立即释放。已提交读是SQL server的默认隔离级别`

`可重复读:像已提交读级别那样读数据,但会保持共享锁直到事务结束`

`可串行读:工作方式类似于可重复读。但它不仅会锁定受影响的数据,还会锁定这个范围。这就阻止了新数据插入查询所涉及的范围`

2.4:持久性

`持久性,意味着在事务完成以后,该事务对数据库所做的更改便持久的保存在数据库之中,并不会被回滚`。即便出现了任何的事故,比如断电等,事务一旦提交,则持久化的保存在数据库中。

`SQL server通过write-ahead transaction log 来保证持久性。write-ahead transaction log 的意思是,事务中对数据库的改变在写入到数据库之前,首先写入到事务日志中。而事务日志是按照顺序排号的(LSN)。当数据库崩溃或者服务器断点时,重新启动SQL server,SQL server首先会检查日志顺序排号,将本应对应数据库做更改但是没有做的部分持久化到数据库`,从而保证了持久性。

三:总结

`事务的(ACID)特性由关系数据库管理系统(RDBMS,数据库系统)来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生了错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到之前的初始状态`

`数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允持有锁的事务能更新该数据,其他事物必须等待,知道前一个事务释放了锁,其他事务才有机会更新该数据`