欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL 事务

程序员文章站 2022-06-01 22:34:06
...

MySQL 事务

特性

ACID

如何实现?

1. 原子性

场景:1.事务提交但没有持久;2.事务没有提交

解决:redo处理事务提交但没有flush磁盘,undo处理执行部分操作

2. 隔离性

场景:事务之间修改相同数据

【隔离级别】

读取未提交

事务A:开启事务,—,---,读取a

事务B:开启事务,更新a

说明:事务A读取的数据a,是事务B修改过的,但是事务B没有commit

读取已提交

事务A:开启事务,—,---,—,---,读取a

事务B:开启事务,更新a,commit

说明:事务A读取的数据a,是事务B修改过的,且事务B已经commit

可重复读:insert可见,update不可见

事务A:开启事务,—,---,—,---,读取a

事务B:开启事务,更新a,commit

说明:事务B更新、commit,事务A仍然读取不到数据a的变更


事务A:开启事务,—,---,—,---,查询

事务B:开启事务,insert b,commit

说明:事务B insert、commit,事务A查询可以获取记录b

串行化

【并发问题】

脏读:读取未提交例子中,事务A读取到事务B更新的数据a,如果事务B回滚,则事务A读到的数据a的更新,属于脏数据。

不可重复读:读取已提交例子中,事务A读取到事务B更新并commit的数据a,如果在事务B提交前读取,值为a1,在事务B提交后读取到的值只能为a2,则称为不可重复读

幻读:可重读读例子中,事务A在事务B insert b前查询,有n条数据,在事务B insert b后查询,则有n+1条数据(包含记录b),属于幻读

丢失更新

第一类,场景:

事务A:开启事务,更新数据a,commit

事务B:开启事务,更新数据a,rollback

由于事务B rollback,撤销事务B的更新,同时撤销了事务A的更新(是否存在:由于X锁,不存在。即事务B的撤销与事务A的无关)

第二类,场景:

事务A:开启事务,更新数据a,commit

事务B:开启事务,更新数据a,commit

最终取值:A还是B?或者A和B的叠加?

如何解决?串行化生产中不存在,悲观锁或者乐观锁

悲观锁:

-- 读锁定
select * from tbl where user = 'A' for update;
-- 更新
update tbl set col = 'a1' where user = 'A';

乐观锁:

-- 读取version
select * from tbl where user = 'B';
-- 更新并判断version
update tbl set col = 'a2' and version = version +1 
where user = 'B' and version = ${version};

或者CAS:

update tbl set col = 'a3' where user = 'C' and col = 'a1';

3. 持久性

场景:1.事务提交没flush;2.事务没有提交

解决:提交的事务,会redo;没有提交的事务,会undo

4. 一致性

事务日志

特点:顺序IO,减少磁盘寻道,效率高

redo log和undo log

参考

事务,https://zhuanlan.zhihu.com/p/43493165

https://www.zhihu.com/question/30272728

https://hit-alibaba.github.io/interview/Server/db/Transaction.html

https://blog.csdn.net/sun8112133/article/details/89853755

丢失更新,https://segmentfault.com/a/1190000012626590

https://www.cnblogs.com/-mrl/p/13093469.html