事务的原子性、一致性、隔离性、持久性

  事务的4个属性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。简称ACID。

原子性Atomicity

一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。原子性,顾名思义就是不可分割的意思。可以理解为事务是数据库交换中最小的逻辑单位,它是不能再拆分的操作。

一致性Consistency

事务必须使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。举个例子,就比如银行转账,两个人转账前后,在银行看来,这两个客户的总存款数应该是不变的。

隔离性Isolation

隔离性是指一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。数据库是通过锁机制来控制隔离性的。锁机制后续会介绍。

持久性Durability

持久性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对其有任何影响。事务只要提交了,就要保证该事务更改的数据能够永久记入数据库,即便提交完成后,服务器突然停电,内存数据丢失,也要保证数据库下次启动后,断电前已经提交的事务对数据库个更改不能丢失。这种保证工作是由数据库管理系统通过日志机制完成的。

并发引起的问题:

SQL并发引起的错误主要由以下三种:脏读,不可重复读,幻读。

脏读:

脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚的。假如发工资的时候,财务人员不小心把一个人的工资打到了小黄的账号中,这时,小黄刚好查询账号余额,正开心呢,结果财务人员发现问题,进行了回滚,那么小黄同学下次查的时候,发现账户余额突然又少了,这种现象是不能允许的。由于数据库管理系统通过锁机制,很好的避免了脏读的出现。

不可重复读

不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回不同了的数据,这是由于在查询的同时,系统中其他事务提交修改而引起的。

虽然不可重复读是并发的一个问题,但是无论是Oracle数据库还是MySQL数据库,默认隔离级别都支持不可重复读。因为如果避免不可重复读要么牺牲效率,要么增大设计难度。所以读者在程序设计的时候,一定将不可重复读考虑在内。

有的程序员在处理扣款的时候,先查询账户余额,再减掉消费金额,然后将计算结果更新到账户余额。在并发的情况下 ,这种操作很容易引发账户余额错误。因为在最后执行更新余额操作的时候,账号余额很有可能已经被别的事务更新过了,这就是不可重复读造成的。一定要记住!!!

幻读

幻读是并发情况下,出现的一种常见现象。事务处理完数据后,再次检查,发现竟然存在未处理成功的数据,就像产生了幻觉一样。例如,第一个事务对一个表中的数据进行了修改,这种修改涉及表中的全部数据行,同时第二个事务也修改了这个表中的数据,这种修改是向表中插入一行新数据,那么,以后就会发生操作第一个事务的用户发现表中存在没有修改成功的数据行的现象,就好像发生了幻觉一样。

既然存在并发,幻读就是正常现象,目前为止,没有任何隔离级别能够避免幻读的出现。

事务隔离级别

大部分实际项目都存在高并发的情况,为了避免高并发出现的这些问题,数据库管理系统增加了事务隔离级别的设置,常见的事务隔离级别有4种

  1. 读未提交
  2. 读已提交
  3. 重复读
  4. 序列化

读未提交

一个会话可以读取其他事务未提交的更新结果,如果这个事务最后以回滚结束,这时读取的数据结果可能就是错误的。这种情况下会出现脏读、不可重复读、幻读,所以多数的数据库应用都不会使用这种隔离级别。MySQL数据库支持这种隔离级别,Oracle数据库不支持这种隔离级别。

读未提交

这是MySQL数据库和Oracle数据库的默认隔离级别。设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则会发生等待。但是其他会话可以修改这个事务中被读取的记录,而不必等待事务结束。在这种隔离级别下,一个事务中的两个相同的读取操作,其结果可能不同。这种隔离级别可以避免脏读的出现,但是无法避免不可重复读和幻读。

重复读

在一个事务中,如果两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数增多,则两次读取结果相同。换句话说,就是在一个事务中第一次读取得记录保证不会在这个事务期间发生改变。MySQL数据库是通过在整个事务期间给读取的记录加锁实现这个隔离级别的。这样,在这个事务结束前,其他会话不能修改事务的中读取的记录,而只能等待事务结束。但是MySql数据库不会阻碍其他会话向表中添加记录,也不会阻碍其他会话修改其他记录。MySql数据库支持这种隔离级别。Oracle数据库不支持这种隔离级别。此种隔离级别可以避免脏读和不可重复读,但是不可避免幻读。

序列化

在一个事务中 ,读取操作的结果是在这事务开始之前其他事务就已经提交的记录,MySQL数据库通过在整个事务期间给表加锁实现这种隔离级别。在这种隔离级别下,对这个表的所有DML操作都是不允许的,必须等待事务结束.这样就保证了在一个事务中的两次读取操作的结果肯定是相同的。MySQL数据库和Oracle数据库都支持这种隔离级别。但是此种隔离级别在并发的情况下,会造成严重的阻塞,所以这种隔离级别一般不会使用。此种隔离级别能够避免脏读和不可重复读,不能避免幻读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值