今天咱们说说事务,相信大家都知道事务的 ACID (Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)。

原子性:表示一个事务不可在分割,而且事务中的操作要么一起成功,要么一起失败;

一致性:表示事务前后数据的完整性必须保持一致;

持久性:表示事务一旦进行提交,那么数据的就改便会永久保存,即使数据库出现宕机也不会任何影响。

前面三个很好理解,那咱们再说说事务的隔离性,事务的隔离就是表示事务与事务之间不会相互干扰。但是多事务的情况下,还是很容易出现脏读、不可重复读以及幻读的问题。我们简单的解释一下这几个词,

脏读:当数据库中一个事务A正在修改一个数据但是还未提交或者回滚,另一个事务B 来读取了修改后的内容并且使用了,之后事务A提交了,此时就引起了脏读。
此情况仅会发生在: 读未提交的的隔离级别.

不可重复读:在一个事务A中多次操作数据,在事务操作过程中(未最终提交),事务B也才做了处理,并且该值发生了改变,这时候就会导致A在事务操作的时候,发现数据与第一次不一样了。 就是不可重复读。
此情况仅会发生在:读未提交、读提交的隔离级别.

幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样.一般解决幻读的方法是增加范围锁RangeS,锁定检索范围为只读,这样就避免了幻读。
此情况会回发生在:读未提交、读提交、可重复读的隔离级别。

说完上面的问题,咱们再说说事务具体的隔离级别,事务隔离级别越高效率就越低。事务隔离的级别大致分为以下几种,

读未提交(read uncommited)、读提交((read commited)、可重复读(repeatable read)以及串行化(serializable)。那么我来解释一下这几种隔离级别,

读未提交:表示一个事务没有提交,其他事务便能读取到它所修改的内容;

读提交:表示一个事务必须提交了,其他事务才能读取到它所修改的内容;

可重复读:表示一个事务从开始到执行结束看到的数据与此事务开启时看到的数据是一致的;

串行化:表示一个事务中不管是读写操作都会加锁,读会加读锁,写会加写锁,如果多个事务出现读写冲突的时候,那么必须等前一个事务执行完成,才能执行下一个事务。

可以下面代码查询你当前数据库的事务隔离级别

mysql> show variables like 'transaction_isolation';
Empty set, 1 warning (0.13 sec)

mysql 默认是为空的。你可以将启动参数 transaction-isolation 的值设置成 READ-COMMITTED ,这里我也建议大家把事务隔离设置成 “读提交”。当然具体设置成什么级别还得根据业务来。

事务隔离性的实现原理

在数据库中会创建一个视图,访问的时候以试图的逻辑结果为准。

在 “可重复读” 隔离级别下,这个视图是在这个事务启动时创建的,并且从始至终都是在用这个视图,原因就是 “事务从开始到执行结束看到的数据与此事务开启时看到的数据是一致的 ”;

在 “读提交” 隔离级别下,这个视图是在每个sql语句开始执行的时候创建的;

这里需要注意的是 在“读未提交” 隔离级别下,是没有视图概念的,因它直接取得就是最新得值;

“串行化” 隔离级别更没有视图得概念了,因为它直接加锁了,这样避免其他事务得并行访问。

事务隔启动方式

Mysql的事务启动方式有以下几种,

1、显式的启动事务,使用 begin 或者 start transation ,然后还有 begin 或者 start commit 事务提交,begin 或者 start rollback 事务回滚;

2、也可以设置自动提交,set autocommit=0表示设置为事务关闭自动提交,如果为 1 则表示启动自动提交,当然自动提交事务的前提必须是要开启事务,所以这里就多了一步操作,使用 begin 开启事务。如果你认为这样很麻烦的话,你也可以执行 commit work and chain ,表示自动提交,并自动启动下一个事务。

好啦,今天就说到这里,如果有什么问题,欢迎大家一起研究讨论。