事务对于程序员来说,是一个非常重要的概念,也是必须掌握的概念,如果不理解事务的原理,将很难写出令人满意的代码。以下记录关于事务的要点,其中参考了不少其他人的文章,若遇到错误的地方请指正,大家一起进步。
什么是事务
事务可以看成一个逻辑工作单元。这个逻辑工作单元的特点,是要么可以全部执行成功,要么全部不执行成功,不允许存在部分成功或者部分失败的情形。
事务的特性
由以上事务的定义也可看出事务特殊的地方,具有一下4个非常著名的特性(ACID):
原子性(atomicity):事务是最小单位,不可再分
一致性(consistency):事务要求所有DML语句操作时,必须保证同时成功或者同时失败
隔离性(isolation):不同事务(事务A与事务B)之间具有隔离性
持久性(durability):是事务的保证,事务终结的标志,所做的修改保存到数据库中(内存-硬盘)
这几个特性中,需要着重理解的是事务的隔离性,尤其对于数据库的操作来说,事务的隔离性,在一定程度上解决了部分并发问题。
事务的隔离级别
1.读未提交(read uncommitted)
该级别中,一个事务会读取到另一个事务中未提交的数据,这里的读取也叫做“脏读”
2.读已提交(read committed)
该级别中,一个事务只能读取到另一个事务已提交的事务。这种隔离界别可以解决“脏读”的问题,但是却解决不了“不可重复读的问题”。
不可重复读是指:同一个事务中,多次读取同一条数据,出现不一致的情况,这种情况通常是由于,其他多个事务多次修改该条数据导致的。
3.可重复读(repeatable read)
该级别中,可以解决“不可重复读的问题”,采用的手段是对可能改变的数据间隙加锁,后面后细说。
但是无法解决另一个问题“幻读”。幻读主要针对insert操作,而不可重复读主要针对update操作。
幻读是指同一个事务中2次范围读取,由于另一个事务进行了insert操作,导致2次读取的结果集出现不一样的情况。
4.串行化(serializable)
该级别中,所有的事务操作均是串行执行的,可以解决上述幻读问题,但效率较低。
其中mysq默认的隔离级别是可重复读,但值得注意的是mysql数据库在该默认级别,并不会出现幻读的现象
本节主要阐述了事务的定义,事务的特性以及着重阐述了事务的隔离性,隔离级别,以及各个隔离级别所能解决的问题。
如果细心阅读可以发现,上面所能解决的问题---脏读、不可重复读、幻读三个问题基本上都是由一个事务在读,而另一个事务在修改或者增加导致的(事务A对数据进行修改、增加,事务B总是在做读操作)。那如果多个事务并发对事务进行修改的话,即丢失更新问题,上面的隔离级别可以解决的吗?答案是不能的。那怎么解决呢,可以先提前透露下,利用锁机制,包括乐观锁,悲观锁,具体的请看下节!