写在正文前面,以下仅MySQL小白进阶
用于记录对MySQL事务并发执行可能导致的4个问题的理解。
读https://www.cnblogs.com/CodeBear/p/12710670.html后总结,博文来自于掘金小册:MySQL 是怎样运行的:从根儿上理解 MySQL。
MySQL事务浅述
MySQL是客户端/服务器架构的软件
客户端(client)/服务端(server),C/S架构,也称主(主动:指客户端发起)从(被动:指服务端被动接收)式架构。
每个客户端与服务器连接后,就会产生一个session(会话),客户端和服务器的交互就是在session中进行的。
事务的特性(ACID)
- 原子性(Atomicity):一事务的操作要么全部执行,要么全部不执行。当事务非正常终止时,其中间结果将被取消。
- 一致性(Consistency):事务执行后,数据库状态与其他业务规则保持一致。
- 隔离性(Isolation):在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
- 持久性(Durability):一旦事务提交成功,事务中的所有数据更新必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重新启动时,也必不会丢失提交的数据。
并发导致的问题可能
建表如下
CREATE TABLE t (
id INT PRIMARY KEY,
name VARCHAR(80)
) Engine=InnoDB CHARSET=utf8mb4;
插入SQL
INSERT INTO t VALUES(1, '鸣人');
脏写
时间节点 | sessionA | sessionB |
---|---|---|
1 | begin | |
2 | begin | |
3 | UPDATE t SET name=‘佐助’ WHERE id=1 | |
4 | UPDATE t SET name=‘小樱’ WHERE id=1 | |
5 | rollback | |
6 | commit |
如果sessionB在回滚事务的时候把sessionA的修改也给回滚了,导致sessionA的提交丢失了,这种现象就被称为“脏写”。
脏读
时间节点 | sessionA | sessionB |
---|---|---|
1 | begin | |
2 | begin | |
3 | UPDATE t SET name=‘佐助’ WHERE id=1 | |
4 | SELECT * FROM t WHERE id=1 | |
5 | ||
6 | … | … |
如果sessionA在节点4查询了id=1的数据name是“佐助”,也就是读到了sessionB还没有提交的数据,就被称为“脏读”。
不可重复读
时间节点 | sessionA | sessionB |
---|---|---|
1 | begin | |
2 | begin | |
3 | SELECT * FROM t WHERE id=1(这里查询结果必然是鸣人) | |
4 | UPDATE t SET name=‘佐助’ WHERE id=1 | |
5 | commit | |
6 | SELECT * FROM t WHERE id=1 | |
7 | … |
如果sessonA在节点6查询id=1的数据name是佐助,也就是在同一次事务中,针对同一条SQL前后查询结果不一致,就被称为不可重复读。
幻读
时间节点 | sessionA | sessionB |
---|---|---|
1 | begin | |
2 | begin | |
3 | SELECT * FROM t WHERE name=‘鸣人’(这里查询结果必然是一条数据) | |
4 | INSERT INTO t VALUES(2, ‘鸣人’); | |
5 | commit | |
6 | SELECT * FROM t WHERE name=‘鸣人’ | |
7 | … |
如果sessonA在节点6查询name='鸣人’的数据是两条,也就是在同一次事务中,针对同一条SQL,后一次SQK读到了前面SQL未查询出来的数据,就被称为“幻读”。
(完)MySQL事务隔离级别及MVCC后续整理。