数据库事务
- 一、数据库事务4大特性(ACID)
- 二、使用数据库事务的方式对数据库进行访问的优点
- 三、数据库的四种隔离级别
- 四、InnoDB引擎的MVCC机制
- 五、查询MySQL数据库当前的隔离级别
- 六、最新总结
- 七、传播机制
- 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
- 在数据库系统中,事务是工作的离散单位,它可以是修改一个用户的账户余额,也可以是库存项的写操作。在单用户、单数据库环境下执行事务比较简单,但在分布式环境下,维护多个数据库的完整性就比较复杂。大多数联机事务处理系统是在大型计算机上实现的,这是由于它的操作复杂,需要快速的输入/输出和完善的管理。如果一个事务在多个场地进行修改,那就需要管理机制来防止数据重写并提供同步。另外还需要具有返回失效事务的能力,提供安全保障和提供数据恢复能力。
- 比如,我们去银行转账,操作可以分为下面两个环节:
(1) 从第一个账户划出款项。
(2) 将款项存入第二个账户。 - 在这个过程中,两个环节是关联的。第一个账户划出款项必须保证正确的存入第二个账户,如果第二个环节没有完成,整个的过程都应该取消,否则就会发生丢失款项的问题。整个交易过程,可以看作是一个事物,成功则全部成功,失败则需要全部撤消,这样可以避免当操作的中间环节出现问题时,产生数据不一致的问题。
- 数据库事务是一个逻辑上的划分,有的时候并不是很明显,它可以是一个操作步骤也可以是多个操作步骤。我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在自己的终端可以预览变化,直到全部修改完成,并经过检查确认无误后,一次性提交并写入数据库,在提交之前,必要的话所做的修改都可以取消。提交之后,就不能撤销,提交成功后其他用户才可以通过查询浏览数据的变化。
一、数据库事务4大特性(ACID)
1、原子性(Atomicity)
事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。在执行过程中出现错误便根据日志进行回滚操作。此时数据还在缓存中。实现在异常情况下对数据库保持一致性。
2、一致性(Consistency)
几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。比如A与B同时抢票,B先抢走了最后一张,A便不可能抢到票,若是B最后没有按时付款,因为原子性,数据回滚,购票系统里还会出现最后一张票,A便有机会抢到。不可能说二者同时抢到,出现票数为-1的情况。
3、隔离性(Isolation)
事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。通过加锁来实现,A与B同时抢票,给票加上锁,同时只能允许一个人对票数进行操作,避免只剩最后一张票,却因为线程的影响,二人都购票成功。
4、持久性(Durability)
对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。 也就是一旦事务全部完成,数据写入数据库中,便不能进行回滚操作。
- 事务的ACID特性是由关系数据库系统(DBMS)来实现的,DBMS采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所作的更新,如果某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使得数据库回滚到执行事务前的初始状态。
- 对于事务的隔离性,DBMS是采用锁机制来实现的。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
二、使用数据库事务的方式对数据库进行访问的优点
- 把逻辑相关的操作分成了一个组;
- 在数据永久改变前,可以预览数据变化;
- 能够保证数据的读一致性。
三、数据库的四种隔离级别
1、读未提交 read uncommitted:
(1)任何时刻都能读取到实时的数据
- 所谓的脏读,其实就是读到了别的事务回滚前的脏数据。
- 比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
- 就是说,当前事务读到的数据是别的事务想要修改成功却又没有最终修改成功的无用数据。
(2)对于锁,读未提交是锁行的(其他事务不能对那一行进行删改)
2、读已提交 read committed
(1)就是一个事务要等另一个事务提交后才能读取数据。这样就不会脏读了。
- 若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。
- (事务B开启了十分钟),假设A第一次查看银行卡余额(事务A开启),是1000,然而B持有A的副卡,在A查看前就花掉了1000,但没提交,在A第一次查看完后,迅速提交(事务B提交)。当A刷新了一下,发现余额为0,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。
- 不过因为A一直到B提交后才发现余额为0,就不存在脏读问题。
*不可重复读:事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了(UPDATE),然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。
(2)对于锁,读提交也是锁行的(其他事务不能对那一行进行删改)
3、可重复读 repeatable read
(1)就是在开始读取数据(事务开启)时,不再允许修改操作
- 事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作,这个不允许只是针对程序员当前操作的行),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。
- 分析:重复读可以解决不可重复读问题。网上说:不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。
- 事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。通俗来说,幻读就是当前事务第一次读取后,另一事务进行了insert操作,当前事务必须先提交,然后当前事务再次读取的结果与第一次读取到的数据条目不一致。
- 那怎么解决幻读问题?—>串行化 serializable 注:InnoDB和Falcon存储引擎通过多版本并发控制MVCC机制解决了该问题。
(2)对于锁,可重复读也是锁行的(其他事务不能对那一行进行删改)