Knowledge note
06-事务
事务简介
-- 数据准备
create table account(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
money int comment '余额'
)comment '账户表';
insert into account (id, name, money)
values (null,'张三',2000),(null,'李四',2000);
alter table account change momey money int;
-- 恢复数据
update account set money =2000 where name='张三' or name='李四';
-- 转账操作:张三给李四转账1000
-- 查询张三余额
select account.money from account where name='张三';
-- jiangzhangsandezhanghuyuejian1000
update account set money =account.money-1000 where name='张三';
-- 讲历史的账户余额+1000
update account set money =money+1000 where name ='李四';




-- 查看事务提交方式是自动提交还是手动提交
select @@autocommit;
-- 设置提交方式为手动提交
set autocommit =0;
alter table account change money money int;
-- 恢复数据
update account set money =2000 where name='张三' or name='李四';
-- 转账操作:张三给李四转账1000
-- 查询张三余额
select account.money from account where name='张三';
-- jiangzhangsandezhanghuyuejian1000
update account set money =account.money-1000 where name='张三';
-- 程序出现异常,则会中断下面的执行
-- 讲历史的账户余额+1000
update account set money =money+1000 where name ='李四';
-- 手动提交
commit ;
-- 回滚事务,假如中间出现异常执行这一步退回开始的数据
rollback ;
事务的四大特性

并发事务问题




#幻读
在数据库并发事务中,幻读(Phantom Read) 是指一个事务在多次执行相同查询时,由于另一个并发事务的插入/删除操作,导致前后查询结果集的行数发生意外变化(出现“新记录”或“消失的记录”),如同产生了“幻觉”。
#核心特点:
- 发生在同一事务内多次执行相同范围查询的场景;
- 差异体现在结果集的行数变化(新增或减少符合条件的记录);
- 与“不可重复读”的区别:不可重复读是同一条记录的内容被修改,而幻读是符合条件的记录数量变化。
#示例说明:
假设数据库中有一张 employee 表,包含字段 id、name、age,初始数据如下:
id
name
age
1
张三
25
2
李四
28
#并发场景:
- 事务A 开始,执行查询:
SELECT * FROM employee WHERE age > 20;结果:2条记录(张三、李四)。 - 事务B 开始,插入一条新记录:
INSERT INTO employee VALUES (3, '王五', 22);,并提交事务。 - 事务A 再次执行相同查询:
SELECT * FROM employee WHERE age > 20;结果:3条记录(多了王五)。
此时,事务A前后两次查询结果行数不同,这就是幻读——事务A“看到”了事务B新增的记录,且该记录符合查询条件。
#产生原因:
幻读的本质是事务隔离级别不足,导致一个事务无法阻止另一个事务对“查询范围”内的记录进行插入/删除操作。 在较低的隔离级别(如 Read Committed,读已提交)下,数据库默认允许这种现象,因为它只保证“读取到已提交的数据”,但不保证“查询范围的稳定性”。
#如何解决幻读?
- 提高事务隔离级别: 使用 Serializable(可串行化) 隔离级别(最高级别),数据库会通过强制事务串行执行(避免并发),从根本上防止幻读。但缺点是性能大幅下降,适用于对一致性要求极高的场景。
- 使用间隙锁(Gap Lock): 部分数据库(如MySQL InnoDB)在 Repeatable Read(可重复读) 级别下,通过“间隙锁”机制防止幻读。间隙锁会锁定查询条件范围内的“间隙”(即使该间隙暂无记录),阻止其他事务在该范围内插入新记录,从而保证查询范围的稳定性。
- 手动加锁:
在查询时显式使用表级锁(如
LOCK TABLES employee WRITE;),阻止其他事务对表进行插入/删除操作,但会严重影响并发性能,不推荐常规使用。
#总结:
幻读是并发事务中因“记录行数意外变化”导致的一致性问题,核心是查询范围被其他事务修改。解决方式需在“一致性”和“性能”之间权衡,实际开发中常用数据库的默认隔离级别(如InnoDB的Repeatable Read,通过间隙锁天然防幻读)或根据业务需求调整隔离级别。
事务隔离级别

查看事务隔离级别

设置事务隔离级别
总结:
