说到事务,作IT的确定都不陌生,会想到Transcation(开启、提交、回滚)。做为资深的IT工做者,对事务全面理解是一项基本功,固然对于正在迈向资深的我来讲,也必须了解。下面就来谈一下事务mysql
1、事务的概念sql
数据库事务(Database Transaction) ,是指做为单个逻辑工做单元执行的一系列操做,要么彻底地执行,要么彻底地不执行。 数据库
2、事务的特性session
事务必须具有ACID四个特性并发
原子性(Atomicity): 一个事务的执行被视为一个不可分割的单元,事务中的操做,要么所有成功,要么所有失败回滚,不能只执行其中的一部分。性能
一致性(Consistency):一致性是指事务必须使数据库从一个一致的状态变到另外一个一致的状态,也就是执行事务的先后状态都必须处于一致的状态。好比说A向B转帐500,那么A帐户要减500,而B帐户须要加500,这两个事件最终的帐户总额仍然没有改变。测试
隔离性(Isolation):是指事务之间的行为互不影响,在实际操做中,会受事务的隔离级别的影响。spa
持久性(Durability):事务提交以后,将数据持久到数据库,即便系统出现问题,数据依然还在。命令行
3、事务的隔离级别事件
在说到事务的隔离特性时,提到事务的隔离性会受到隔离级别的影响。事务的隔离级别定义了事务之间的可见性,有人称它为事务的“自私”程度。主要分为四种隔离级别
一、READ UNCOMMITTED(未提交读)。
在此隔离级别下,若是事务A对数据进行修改,在没有提交的状况下,事务B也能够看到该修改,这种问题称为脏读。未提交读的隔离级别较低,容易引发不少问题,通常不经常使用。
测试以下:(使用navicat链接mysql进行测试)
①首先要将隔离级别设置为未提交读状态(如下实例都在global级别设置,也能够设置session级别)
打开第一个命令行界面,用来专门设置隔离级别:
mysql> set @@global.tx_transaction='READ-UNCOMMITTED';
由于设置的是global级别的,因此在接下来的操做中,为了能更好的演示效果,须要另开一个命令行窗口,在接下来的描述中,提到建立事务就表示新打开一个窗口。
②建立A事务:
首先要查看当前的隔离级别,确保是未提交读状态:
开启事务,并执行查询,能够看到只有三条数据。结果以下:
③建立B事务:
也是先查看当前的隔离级别(如下测试都会在新打开命令行界面时查看隔离级别,后面就再也不叙述)
开启事务,并插入一条数据,可是不提交。此时,在当前事务中能够查询到新增的数据:
④而后再回到A事务,执行查询,此时在B事务还未提交时,就能够查到新增的数据:
在A事务中读到了B事务未提交的数据,称此现象为脏读。
二、READ COMMITTED(提交读)
在该隔离级别下,不会出现脏读。当事务A对数据修改以后,只要在提交之后,事务B才能看到修改的数据。可是会出现不可重复读问题,何谓不可重复读?就是一个事务对同一行数据重复读取两次,可是却获得了不一样的结果。
测试以下:
①设置隔离级别
mysql> set @@global.tx_isolation='READ-COMMITTED';
②建立事务A:
开启事务,而后查询数据
③建立事务B
开启事务,接下来查看数据,跟事务A查到的数据一致。而后更新第二条数据。此时,不提交事务。
④在事务A中执行查询命令,发现B事务更新的数据查不到:
⑤让事务B提交,而后事务A再次执行查询,此时就能够查看到更新以后的数据:
在该隔离级别下,事务A读到的内容是事务B提交后的数据,即事务A只能读到事务B两端的数据,至于事务B中间的其余修改就读不到了。如事务A能读到刚开始的状态,若是事务B在修改过程当中,刚开始把id=10的数据修改成‘cc’,没有提交;而后又把id=11的数据改成‘dd’,依旧不提交;最后发现更新错了,又把id=10的数据改成‘c’,id=11的数据改成‘d’,把id=9的数据改成‘bb’,提交。此时事务A只能读到id=9的值变了,至于id=10和11的变化过程一无所知。这个就是与未提交读的区别之处,未提交读能看到这个变化过程,随变化而变化。
三、REPEATABLE READ(可重复读)
在该隔离级别下,不会出现不可重复读的问题。事务B对数据作的修改,提交以后,对于先于B事务开启的事务A来讲,此修改仍然看不到。
测试以下:
①设置隔离级别
mysql> set@@global.tx_isolation='REPEATABLE-READ';
②建立事务A
开启事务,而后执行查询
③建立事务B
开启事务B,先查询数据,而后将第三条数据更新。此时不提交事务
④在事务A中进行查询,没法查看事务B修改的数据
⑤提交事务B,再在事务A中执行查询,依然没法看到更新的数据,查询到的数据始终没有改变
⑥将事务A提交,而后开启新的事务,此时便可查看到更新后的数据
可重复读解决了不可重复读的问题,某个事务在执行期间,不管后续的其余事务如何操做数据,都保持查询结果不变,可是从新打开事务后,会读到不同的数据。这就引出了幻读的问题,所问幻读就是事务在操做过程当中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺乏了第一次查询中出现的数据。
四、SERIALIZABLE(可串行化)
这是隔离的最高级别,强制要求全部的事务串行执行,会对每行数据加锁,这就形成大量锁征用问题,性能最差。
测试以下:
①设置隔离级别
mysql> set @@global.tx_isolation='SERIALIZABLE';
②建立事务A
开启事务并执行查询
③建立事务B
开启事务并执行查询,此时能够查询。可是若是更新数据时,事务处于等待状态,由于事务A已经上锁。当必定时间还没法执行时,提示当前更新数据处于锁状态,没法更新。
④当事务A提交后,处于等待状态的事务B也会执行完。
可串行化解决了幻读的问题,可是又引起了新的问题,死锁。例如上述两个事务,若是都不提交,那么此时都将没法进行后续操做。
综合上述内容,四种隔离级别所解决的问题以下:
其性能以下:
即隔离级别越高,其并发性越低,性能越差。
4、小结
事务是开发中没法避免的一个问题,因此熟悉事务的基本概念以及使用是很是重要的。固然本文也只是解析了事务的一角,还须要在从此的工做中继续深刻剖析事务的应用。