算是一篇老生常谈的文章,我想写下自己此时的一些认知,方便自己理解,也希望能方便别人理解吧。
什么是事务?
事务是访问或更新(即读写)数据库各个数据项的一个程序执行单元,可以由一条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)序列化就不再多说了,事务顺序执行。
一点粗浅的理解吧,有不对之处请指出。