数据库事务知识整理
什么是数据库事务?
事务,就是一系列操作的整体,其结果就是这一系列操作要么全部成功,要么全部失败。
譬如说,一个经典的例子--转账。
A要转帐给B 100块钱,要经历以下步骤:
1、扣除A账户100块钱。
2、增加B账户100块钱。
以上例子里的两个步骤,要么全部成功,要么全部失败,不然,就乱套了。在这里,我们可以看出,事务保证了完整性。那么,说到数据库事务,就是一系列对数据库的操作,要么全部成功(提交),要么全部失败(回滚),保证了数据的完整性。
数据库事务的四大特性(ACID)
ACID,指数据库事务四个特性的英文单词缩写,包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务的数据库,必需要具有这四种特性,否则在事务过程当中无法保证数据的正确性。
1、原子性(Atomicity)
说的是一个事务内所有操作共同组成一个原子包,要么全部成功,要么全部失败。这是最基本的特性。
2、一致性(Consistency)
计算机指令是有先后顺序的,这样就决定了数据库提交事务会有一个过程。如果提交的时候,存在一个时间差,在提交的第一秒,一个删除过程还没完成到了第三秒才完成,会不会第一秒访问的人和第三秒访问的人得到不同的结果?出现不一致,状态的混沌?为了防止这样的情况,数据库事务的一致性就规定了事务提交前后,永远只可能存在事务提交前的状态或事务提交后的状态,从一个一致性的状态到另一个一致性状态,而不可能出现中间的过程态。也就是说事务的执行结果是量子化状态,而不是线性状态。 这就是一致性得保证的只会有前状态和后状态,绝不会出现中间态。
3、隔离性(Isolation)
当多个事务并发执行时,有可能会出现脏读,不可重复读,幻读等问题,事务的隔离就是为了解决这些问题。数据库为了保证事务隔离性,会有很多锁方案。
4、持久性(Durability)
当一个事务提交之后,数据库状态永远的发生了改变。这个事务只要提交了,哪怕提交后宕机,他也确确实实的提交了,不会出现因为刚刚宕机了而让提交不生效。
事务并发产生的问题
一个系统,在同一时刻,往往有多个人在使用。这样,就有可能出现事务并发。事务并发就是多个事务在同时执行。如果没有事务隔离,那么事务并发有可能产生更新丢失、脏读、不可重复读、幻读等问题。
更新丢失
两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。
脏读
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据。例如,事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
不可重复读
指在同一个事务内,对同一行数据的多次查询,返回了不同的结果。例如,事务T1第一次查询了某行数据,然后事务T2对这行数据的某个字段做了修改,并且提交了数据。事务T1第二次查询该行数据的时候,得到了事务T2修改过的结果。不可重复读和脏读的区别在于,脏读是读了未提交的数据,而不可重复读是读了提交了的数据。当然,不可重复读在某些情况下并不是问题,有时候我们就是要在同一事务下查询到数据的最新状态。
幻读
幻读又称虚读。同一条SQL语句在同一个事务中的多次查询,得到的数据量(条数)不一样。例如,事务T1第一次统计某个表的数据量,有100行。这时,事务T2对这个表插入了一行数据。事务T1第二次统计这个表的数据量,有101行。这就是幻读。幻读和不可重复读的区别在于,不可重复读的重点是修改,同样的条件,第一次和第二次读取的值不一样。而幻读的重点在于新增或者删除,同样的条件, 第一次和第二次读出来的记录数不一样。
事务隔离级别
事务隔离就是为了解决事务并发带来的问题。事务隔离级别,就是多个事务之间的数据互不影响的程度。级别越高,越能保证数据的完整性和一致性。下面由低到高介绍事务隔离级别。
READ_UNCOMMITTED(未授权读取级别)
以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他写事务(但允许其他读事务)。此隔离级别可以防止更新丢失,但不能防止脏读、不可重复读、幻读。此隔离级别可以通过“排他写锁”实现。
READ_COMMITTED(授权读取级别)
以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。
REPEATABLE_READ(可重复读取级别)
以操作同一行数据为前提,读事务禁止其他写事务(但允许其他读事务),未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。此隔离级别可以通过“共享读锁”和“排他写锁”实现。
SERIALIZABLE(序列化级别)
提供最严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
事务隔离级别越高越好吗?
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免更新丢失、脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
本文来自博客园,作者:Y00,转载请注明原文链接:https://www.cnblogs.com/ayic/p/16704699.html
聊聊技术,聊聊人生。欢迎关注我的公众号!^_^