当前位置: 代码迷 >> 综合 >> 事务的隔离性
  详细解决方案

事务的隔离性

热度:24   发布时间:2023-10-25 05:08:29.0

文章摘自微信公众号架构师之路+自己的总结,作为学习笔记记录下来,如有侵权,联系必删

 

事务有四个特性(ACID):

(1)原子性(Atomic):事务中包含操作被看作一个逻辑单元,这个逻辑单元要么一次性执行成功,要么全部失败。原子性体现在对数据的读取上,例如一个事务对统一数据项对多次读取的结果是相同的

(2)一致性(consistency):事务对数据完整性约束的遵循。这些约束可能包括主键约束、外键约束或是一些用户自定义约束。事务执行的前后都是合法的数据状态,不会违背任何的数据完整性。如A和B账户中各有500元,之后A向B转100元,此时A有400,B有600,需要满足A+B=1000,同时还需要保证双方的钱不为负数,这些都是保证数据一致性的约束。

(3)隔离性(Isolation):多个用户并发事务访问同一个数据库时,一个用户的事务不应该呗其他用户的事务干扰。

(4)持久性(Durability):指事务运行成功后,对系统的更新是永久的,不会无缘无故回滚。

假设有InnoDB表:假设有InnoDB表:t(id PK, name);
表中有三条记录:
1, shenjian
2, zhangsan
3, lisi并发导致的问题有:读脏、不可重复读、幻读case 1 读脏(读了未提交事务操作的记录)
事务A,先执行,处于未提交的状态:
insert into t values(4, wangwu);事务B,后执行,也未提交:
select * from t;如果事务B能够读取到(4, wangwu)这条记录,事务A就对事务B产生了影响,这个影响叫做“读脏”,读到了未提交事务操作的记录。case 2 不可重复读(一个事务执行出不同结果)
事务A,先执行:
select * from t where id=1;结果集为:
1, shenjian事务B,后执行,并且提交:
update t set name=xxoo where id=1;
commit;事务A,再次执行相同的查询:
select * from t where id=1;结果集为:
1, xxoo这次是已提交事务B对事务A产生的影响,这个影响叫做“不可重复读”,一个事务内相同的查询,得到了不同的结果。case 3 幻读(A有先读后写,写依赖于读的条件,B为写并改变A读的结果,导致B读出的数据不一致)
事务A,先执行:
select * from t where id>3;结果集为:
NULL事务B,后执行,并且提交:
insert into t values(4, wangwu);
commit;事务A,首次查询了id>3的结果为NULL,于是想插入一条为4的记录:
insert into t values(4, xxoo);结果集为:
Error : duplicate key!

InnoDB实现了四种不同事务的隔离级别:读为提交、读提交、可重复读、串行化

InnoDB使用不同的锁策略实现不同的隔离级别

(1)读未提交

这种事务隔离级别下,select语句不加锁。会读到不一致的数据。

即“读脏”,是并发高、一致性最差的隔离级别。

(2)串行化

该事务隔离级别下,所有select语句都会被隐式转化为select ... in share mode.

这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。一致性最好,并发行差

大数据场景不选择以上两种隔离级别

(3)可重复读

普通的select使用快照读(snapshot read),这是一种不加锁的一致性读(Consistent Nonlocking Read),底层使用MVCC来实现

加锁的select:唯一记录的查询使用记录锁,范围查询的使用间隙锁和临键锁。

(ps. 锁单条记录的锁为记录锁,锁范围内的记录的锁未间隙锁,间隙锁+记录锁=临键锁)

(4)读提交

这是最常用的隔离级别

普通读诗快照读

加锁的select, update, delete等语句,除了在外键约束检查以及重复键检查时会封锁区间,其他时刻都只使用记录锁

可能出现不可重复读

 

  相关解决方案