2026-10-24 20:51:38
MySQL事务的核心是确保ACID特性(原子性、一致性、隔离性、持久性),基础用法如下:
START TRANSACTION; -- 开启事务-- 执行SQL操作,例如:UPDATE accounts SET balance = balance - 100 WHERE user_id = 123;INSERT INTO transaction_logs (user_id, amount, type) VALUES (123, -100, 'withdraw');-- 提交或回滚COMMIT; -- 成功时提交-- ROLLBACK; -- 出错时回滚关键点:
MySQL定义了四种标准隔离级别,直接影响并发事务间的数据可见性:
1. READ UNCOMMITTED(读未提交)解决脏读问题,只能读取已提交的数据。
仍可能出现不可重复读(同一事务内两次读取同一行数据结果可能不同)。
多数Web应用的平衡选择,如电商网站查询商品库存时,只需看到最新提交的库存数据。
PostgreSQL、SQL Server等数据库的默认隔离级别。
解决脏读和不可重复读问题,同一事务内多次读取同一行数据结果一致。
可能出现幻读(同一事务内两次范围查询结果可能不同),但InnoDB通过MVCC和间隙锁降低风险。
InnoDB的默认隔离级别,适用于需要事务内保持数据一致性视图的场景,如报表生成、复杂数据分析。
修改全局设置后,建议重启MySQL服务以确保所有新连接生效。
READ UNCOMMITTED:脏读风险过高,数据可靠性是底线。
SERIALIZABLE:除非业务对数据一致性有极端要求且可接受极低并发,否则不建议使用。
保持事务短小精悍:减少事务持有锁的时间,降低死锁可能性。
统一访问顺序:所有事务以相同顺序访问和锁定资源,减少循环等待几率。例如,约定所有事务先锁accounts表再锁orders表。
避免用户交互在事务中:用户操作的不可预测性会延长事务时间,增加死锁风险。
显式加锁:使用SELECT ... FOR UPDATE或SELECT ... FOR SHARE提前获取锁,降低死锁风险。START TRANSACTION;SELECT balance FROM accounts WHERE user_id = 123 FOR UPDATE; -- 先获取排他锁UPDATE accounts SET balance = balance - 100 WHERE user_id = 123;COMMIT;
减少锁粒度:优先使用行级锁(InnoDB默认)而非表级锁。
错误处理与重试:应用程序捕获死锁错误(1213),回滚当前事务并短暂延迟后重试。
分析死锁日志:通过SHOW ENGINE INNODB STATUS查看最近死锁信息,优化事务逻辑或SQL查询。
正确使用MySQL事务需在数据安全和系统性能间找到平衡点:


