1 什么是事务
事务就是保障一系列的操作统一执行,要嘛全部成功,要嘛全部失败。
2 mysql存储引擎

3 事务的属性ACID
1)原子性(Atomicity)
一连串的操作看做一个操作,要嘛全部成功,要嘛全部失败
2)一致性(Consistency)
事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,这是数据库就处于一种不正确的状态,也就是不一致的状态。
3)隔离性(isolation)
事务之间的操作互不影响,一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
4)持久性(durabolity)
数据一旦提交永久保存
4 隔离级别
4.1 隔离级别相关问题
在一个事务中对数据进行多次查询,在这个过程中,如果其它事务对数据进行更新、新增、删除操作,那么多次查询的结果就会不同
1)脏读
4.2 隔离级别

SELECT @@tx_isolation;

set SESSION transaction isolation level read committed;
set global transaction isolation level read committed;
重启才会有效,对所有用户有效
5 示例
1)提交
set autocommit = 0;
start TRANSACTION;
DELETE FROM jcustomer WHERE CustomerNo = 10000002;
DELETE FROM jcustomer WHERE CustomerNo = 10000003;
COMMIT;
set autocommit标识关闭自动提交。因为mysql默认自动提交,执行一条操作语句就会自动提交,为了保证事务内多条语句全部执行成功后再一起提交,需要先关闭
start TRANSACTION;开启事务
COMMIT;提交事务

成功删除两条记录
2)回滚
set autocommit = 0;
start TRANSACTION;
DELETE FROM jcustomer WHERE CustomerNo = 10000005;
DELETE FROM jcustomer WHERE CustomerNo = 10000006;
ROLLBACK
ROLLBACK回滚
没有删除,受影响行0
3)回滚到节点
set autocommit = 0;
start TRANSACTION;
DELETE FROM jcustomer WHERE CustomerNo = 10000010;
DELETE FROM jcustomer WHERE CustomerNo = 10000011;
SAVEPOINT a;
DELETE FROM jcustomer WHERE CustomerNo = 10000012;
ROLLBACK TO a;
SAVEPOINT a;设置回滚节点
ROLLBACK TO a;回滚到节点a处
上面语句执行后,回滚到节点a处,10000010,10000011被删除,10000012没有被删除
6 MYSQL展示ACID特性示例

三个窗口的执行语句分别是
1号窗口
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; UPDATE jcustomer set `Name` = CONCAT(`Name`,'aaa') WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; COMMIT; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
2号窗口
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; UPDATE jcustomer set `Name` = CONCAT(`Name`,'bbb') WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; COMMIT; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
3号窗口
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
6.1 示例1
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
执行结果
2)执行1号窗口前三条语句
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
3)执行2号窗口前三条语句
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
4)执行1号窗口第四条语句
UPDATE jcustomer set `Name` = CONCAT(`Name`,'aaa') WHERE CustomerNo = 10000010;
5)执行2号窗口第四条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的还是:小明
没有脏读
6)执行1号窗口第五条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的:小明aaa
7)执行3号窗口的语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的是小明:没有脏读
8)执行1号窗口的第六条语句
COMMIT;
9)执行1后窗口的第七条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
10)执行3号窗口的语句
读取到小明aaa,1号窗口的事务成功提交了
11)执行2号窗口的第五条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的还是:小明
没有不可重复度
12)执行2号窗口的第六条语句
UPDATE jcustomer set `Name` = CONCAT(`Name`,'bbb') WHERE CustomerNo = 10000010;
13)执行3号窗口的语句
还是小明aaa
14)执行2号窗口的第七条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
15)执行2号窗口的第八条语句
COMMIT;
16)执行2号窗口的第九条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
6.2 示例2
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
执行结果
2)执行1号窗口前三条语句
set autocommit = 0;
start TRANSACTION;
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
3)执行2号窗口前五条语句
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
4)执行1号窗口第四条语句
UPDATE jcustomer set `Name` = CONCAT(`Name`,'aaa') WHERE CustomerNo = 10000010;
5)执行2号窗口的第六条语句
UPDATE jcustomer set `Name` = CONCAT(`Name`,'bbb') WHERE CustomerNo = 10000010;
修改操作阻塞了,这是数据库锁的作用
6)执行1号窗口第五条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的:小明aaa
7)执行3号窗口的语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
读取到的是小明:没有脏读
8)执行1号窗口的第六条语句
COMMIT;
同时窗口2,阻塞的修改语句执行了
9)执行1后窗口的第七条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
10)执行3号窗口的语句
读取到小明aaa,1号窗口的事务成功提交了
11)执行2号窗口的第七条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
12)执行2号窗口的第八条语句
COMMIT;
13)执行2号窗口的第九条语句
SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
6.3 示例3
把窗口1的修改语句修改成下面的
UPDATE jcustomer set `Name` = 'aaa' WHERE CustomerNo = 10000010;
把窗口2的修改语句修改成下面的
UPDATE jcustomer set `Name` = 'bbb' WHERE CustomerNo = 10000010;
1)窗口1执行前五条语句
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; UPDATE jcustomer set `Name` = 'aaa' WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
2)窗口2执行前六条语句
set autocommit = 0; start TRANSACTION; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010; UPDATE jcustomer set `Name` = 'bbb' WHERE CustomerNo = 10000010; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
同样阻塞了
3)执行窗口1第六、七条语句
COMMIT; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
同时窗口2 阻塞的修改语句执行了
4)执行窗口2第八、九条语句
COMMIT; SELECT * FROM jcustomer WHERE CustomerNo = 10000010;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?