关于Mysql数据库InnoDB存储引擎事务的一点理解

  • Post author:
  • Post category:mysql


算是一篇老生常谈的文章,我想写下自己此时的一些认知,方便自己理解,也希望能方便别人理解吧。


什么是事务?

事务是访问或更新(即读写)数据库各个数据项的一个程序执行单元,可以由一条SQL构成,也可以由一组复杂的SQL语句构成。


事务有哪些特性?

ACID,已经说的耳朵都起茧了。but,我还是决定从课本上抄一遍,加深一下概念和认知。

1)原子性(Atomicity):整个事务是不可分割的单元,要么执行成功,要么执行失败回滚。

2)一致性(consistency):指事务完成后,数据库的完整性约束(实体完整性、域完整性、参照完整性)没有被破坏。例如唯一性约束(域完整性)还是成立的。

3)隔离性(isolation):每个事务提交前对其他事务不可见。

4)持久性(durability):事务一旦提交,其结果就是永久性的。即使发生宕机,数据库也能将数据恢复。当然,恢复数据需要一些系统共同的配合。


事务的隔离级别都有哪些?

ISO和ANIS SQL标准制定了四种隔离级别,但是大部分数据库厂家并没有遵守这些标准,例如Oracle就不支持 READ UNCOMMITTED和REPELATABLE READ的隔离级别。

SQL标准定义的四个隔离级别分别为:

1) READ UNCOMMITTED:未提交读;

2) READ COMMITTED:提交读;

3) REPELATABLE READ:可重复读;

4)SERIALIZABLE :序列化;

Oracle默认的隔离级别为

提交读

,Mysql InnoDB存储引擎默认的隔离级别为

可重复读

定义各个隔离级别可能出现的问题:

首先呢,我们来创建一张用户的账户余额表,并插入几条数据;

然后我们开启两个对话窗口,并将自动提交关闭。


1)将两个会话都设置为未提交读;

set session transaction isolation level read uncommitted;


可见,会话2读取到了会话1未提交的事务,这种现象称为

脏读

2)将两个会话都设置提交读;

set session transaction isolation level read committed;


ok,脏读的问题解决了,但是我们看下面的问题。


在会话1中的事务中,两次查询同一行的值出现了不一样的结果,这就是通常所说的,

不可重复读

3)将两个会话都设置为;

set session transaction isolation level read committed;


事务的隔离级别修改为可重复读之后,不可重复读的现象便不会再发生了。

ok,但是还有一个词,叫做

幻读

,大家肯定也听说过。幻读是什么呢?我个人的理解是,“幻读的重点在于新增或者删除 (数据条数变化)。同样的条件, 第1次和第2次读出来的记录数不一样;不可重复读的重点是修改: 同样的条件, 你读取过的数据, 再次读取出来发现值不一样了”。下面展示一下幻读的过程:

目前东北F4的账户余额如下:

此时我们同样是开启两个会话(左边的两个图都是为事务1的图,右面的图为事务2),每个会话中开启一个事务。


幻读的理解是这样的:本来说在9的时候,整体查询应该有5条数据,money为300的有两条。与最初查询结果不一致,就产生了幻读。但是好像InnoDB做了一些实现调整吧。对于上述现象,我参考了一些文章,理解是这样的:InnoDB在可重复读的隔离级别下,事务中的查询操作,采用的是之前的快照;但是一旦有更新操作,那么数据锁就都变成了最新版本,所获得的数据也就都是最新数据了。这种方式算是在一定程度上解决了幻读的问题吧。

4)序列化就不再多说了,事务顺序执行。

一点粗浅的理解吧,有不对之处请指出。



版权声明:本文为xiao1xuan2原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。