数据库事务总结

2017-07-05  本文已影响0人  程序猿胖子

引言

事务,体现的是部分与整体的思想,多个部分组成一个整体,要么全部生效,要么全部失效。事务就是实现这种效果的一个抽象概念。这种实现反映到数据库中,就是多条SQL语句,要么所有执行成功,要么所有执行失败。

ACID

在数据库当中,一个事务必须同时满足4个特性即:原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)和持久性(Durabiliy)简称ACID。

在这些事务特性中,数据“一致性”是最终目标,其他特性都是为达到这个目标而采取的措施,要求或手段。

数据库管理系统一般采用重执行日志来保证原子性、一致性、持久性。重执行日志记录了数据库变化的每一个动作,数据库在一个事务中执行一部分操作后发生错误退出,数据库即可根据重执行日志撤销已经执行的操作,此外,对于已经提交的事务,即使数据库崩溃,在重启数据库时也能够根据日志对尚未持久化的数据进行相应的重执行操作。

采用数据库锁机制 保证事务的隔离性。当多个事务试图对相同的数据进行操作时,只有持有锁的事务才能操作数据,直到前一个事务完成后,后面的事务才有机会对数据进行操作。

并发

一个数据库可能拥有多个访问客户端,这些客户端都可用并发的方式访问数据库。数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。这些问题可以归结为读与写两类操作上。

读并发

1、脏读

A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的,如下:

脏读.png

在这个场景中,B希望取款500元,而后又撤消了动作,而A往相同的账户中转账100元,就因为A事务读取了B事务尚未提交的数据,因而造成账户白白丢失了500元。

2、不可重复读

不可重复读是指A事务读取了B事务已经提交的更改数据。假设A在取款事务的过程中,B往该账户转账100元,A两次读取账户的余额发生不一致。

不可重复读.png

在同一事务中,T4时间点和T7时间点读取的账户存款余额不一致。

3、幻象读

A事务读取B事务提交的新增数据,这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中。如下:


幻读.png

在这个场景中,假设银行系统在同一个事务中两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时两次统计的总金额将不一致。

注:
不可重复读是指读到了已经提交事务的更改数据(UPDATE 或DELETE),只需对操作的数据添加行锁就可以解决了。
幻象读是指读到了其他已经提交事务的新增数据(INSERT),而为了防止读到新增的数据,往往需要添加表锁,将整张表锁定。

写并发

1、第一类丢失更新(回滚丢失更新)
A事务撤消时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,如下:


第一类丢失更新.png

A事务在撤销时,“不小心”将B事务已经转入账户的金额给抹去了。

2、第二类丢失更新(提交丢失更新)
A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失。


第二类丢失更新.png

在上面这个场景中,由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失了100元。相反,如果转账事务先提交,那么用户账户将损失100元。

隔离级别

要解决上面的问题,我们很容易想到的解决办法可能就是给数据加锁,但如果直接给数据加锁是非常麻烦的,而且容易出错,因此数据库为用户提供了自动锁机制,这种自动锁机制就是我们常说的事务隔离级别,只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据资源添加适合的锁。

ANSI/ISO SQL92标准定义了4个等级的事务隔离级别,在相同的数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可能导致不同的结果。如下所示:

隔离级别.png
注:
事务的隔离级别和数据库并发性是对立的。隔离级别越高并发性和吞吐量越低,发生的问题也就越少。

参考资料

1、《精通Spring4.x 企业应用开发实战--第11章 Spring的事务管理》
2、知乎--如何理解数据库事务中的一致性的概念?
3、《Hibernate5讲义》

上一篇 下一篇

猜你喜欢

热点阅读