一、什么是事务? 事务是数据库执行过程中的一个逻辑单元,保证一组操作要么全部成功,要么全部失败。
1.1 事务的ACID特性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ┌─────────────────────────────────────────────────────────────────┐ │ ACID特性 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ A → Atomic(原子性) │ │ 要么全做,要么不做 │ │ │ │ C → Consistency(一致性) │ │ 事务前后,数据状态一致 │ │ │ │ I → Isolation (隔离性) │ │ 并发事务互不干扰 │ │ │ │ D → Durability(持久性) │ │ 事务提交后,修改永久保存 │ │ │ └─────────────────────────────────────────────────────────────────┘
1.2 事务示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 START TRANSACTION;UPDATE accounts SET balance = balance - 1000 WHERE user_id = 1 ;UPDATE accounts SET balance = balance + 1000 WHERE user_id = 2 ;COMMIT ;
二、事务操作 2.1 基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 START TRANSACTION;BEGIN ;COMMIT ;ROLLBACK ;ROLLBACK TO SAVEPOINT point1;SAVEPOINT point1;RELEASE SAVEPOINT point1;
2.2 自动提交 1 2 3 4 5 6 7 8 9 SHOW VARIABLES LIKE 'autocommit' ;SET autocommit = 0 ;START TRANSACTION;
2.3 事务支持情况
三、隔离级别 3.1 隔离级别概述
隔离级别
脏读
不可重复读
幻读
READ UNCOMMITTED
✅ 可能
✅ 可能
✅ 可能
READ COMMITTED
❌ 不可能
✅ 可能
✅ 可能
REPEATABLE READ
❌ 不可能
❌ 不可能
✅ 可能(MySQL可避免)
SERIALIZABLE
❌ 不可能
❌ 不可能
❌ 不可能
1 2 3 4 5 6 7 8 9 10 11 12 ┌─────────────────────────────────────────────────────────────────┐ │ 隔离级别对比 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 隔离程度从低到高: │ │ READ UNCOMMITTED → READ COMMITTED → REPEATABLE READ │ │ → SERIALIZABLE │ │ │ │ 隔离程度越高,数据越安全,但性能越差 │ │ MySQL默认:REPEATABLE READ │ │ │ └─────────────────────────────────────────────────────────────────┘
3.2 设置隔离级别 1 2 3 4 5 6 7 8 9 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT @@transaction_isolation ;
3.3 各种问题详解
四、InnoDB锁机制 4.1 锁类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ┌─────────────────────────────────────────────────────────────────┐ │ 锁类型分类 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 按粒度分: │ │ ├─ 表级锁 → 开销小,加锁快 │ │ │ 表锁、全局锁 │ │ └─ 行级锁 → 开销大,加锁慢,支持并发 │ │ 行锁、间隙锁 │ │ │ │ 按类型分: │ │ ├─ 共享锁(S锁)→ 读锁,可共存 │ │ └─ 排他锁(X 锁)→ 写锁,互斥 │ │ │ │ 按方式分: │ │ ├─ 乐观锁 → 版本号 │ │ └─ 悲观锁 → 排他锁 │ │ │ └─────────────────────────────────────────────────────────────────┘
4.2 行锁 1 2 3 4 5 6 7 8 9 10 SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;SELECT * FROM users WHERE id = 1 FOR UPDATE ;SELECT * FROM users WHERE id = 1 FOR UPDATE ;
4.3 表锁 1 2 3 4 5 6 7 8 9 10 11 12 LOCK TABLES users READ; LOCK TABLES users WRITE; UNLOCK TABLES;
4.4 意向锁
五、间隙锁与临键锁 5.1 间隙锁 1 2 3 4 5 SELECT * FROM users WHERE age BETWEEN 15 AND 25 FOR UPDATE ;
5.2 临键锁 1 2 3 4 5 SELECT * FROM users WHERE age = 20 FOR UPDATE ;
5.3 锁分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SHOW ENGINE INNODB STATUS;SHOW FULL PROCESSLIST;SELECT * FROM information_schema.INNODB_TRX;SELECT * FROM information_schema.INNODB_LOCK_WAITS;SELECT * FROM information_schema.INNODB_LOCKS;
六、乐观锁与悲观锁 6.1 悲观锁 1 2 3 4 5 6 7 8 9 10 11 12 13 START TRANSACTION;SELECT * FROM products WHERE id = 1 FOR UPDATE ;UPDATE products SET stock = stock - 1 WHERE id = 1 ;COMMIT ;
6.2 乐观锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 UPDATE products SET stock = stock - 1 , version = version + 1 WHERE id = 1 AND version = 1 ;UPDATE products SET stock = stock - 1 , updated_at = NOW() WHERE id = 1 AND updated_at = '2026-01-01 12:00:00' ;
6.3 两种锁对比
特性
乐观锁
悲观锁
实现方式
版本号、时间戳
数据库锁
适用场景
并发少
并发多
性能
好
差
安全性
可能冲突失败
保证安全
编程复杂度
需要重试机制
简单
七、死锁 7.1 死锁产生 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ┌─────────────────────────────────────────────────────────────────┐ │ 死锁示例 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 事务A: │ │ SELECT * FROM users WHERE id = 1 FOR UPDATE ; │ UPDATE users SET age = 30 WHERE id = 2 ; │ │ │ 事务B: │ │ SELECT * FROM users WHERE id = 2 FOR UPDATE ; │ UPDATE users SET age = 30 WHERE id = 1 ; │ │ │ 死锁!互相等待对方释放锁 │ │ │ └─────────────────────────────────────────────────────────────────┘
7.2 避免死锁 1 2 3 4 5 6 7 8 9 10 11 12 13 14 SET TRANSACTION ISOLATION LEVEL READ COMMITTED;SHOW ENGINE INNODB STATUS;
7.3 处理死锁 1 2 3 4 5 6 7 8 9 10 11 SHOW ENGINE INNODB STATUS;SET innodb_lock_wait_timeout = 50 ;SELECT * FROM information_schema.INNODB_TRX;
八、分布式事务 8.1 方案对比
方案
原理
优点
缺点
2PC
两阶段提交
强一致性
性能差,有协调者单点
3PC
三阶段提交
减少阻塞
依然有协调者问题
TCC
Try-Confirm-Cancel
性能好
业务侵入性强
本地消息表
消息队列
简单可靠
复杂度高
Seata
AT模式
封装完善
需要引入中间件
8.2 XA事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 XA START 'transaction_id' ;UPDATE accounts SET balance = balance - 100 WHERE user_id = 1 ; XA END 'transaction_id' ; XA PREPARE 'transaction_id' ; XA COMMIT 'transaction_id' ; XA ROLLBACK 'transaction_id' ;
九、实战案例 9.1 订单创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 START TRANSACTION;UPDATE products SET stock = stock - 1 WHERE id = 1 AND stock > 0 ;INSERT INTO orders (user_id, product_id, status) VALUES (1 , 1 , 'pending' );INSERT INTO order_logs (order_id, action) VALUES (LAST_INSERT_ID(), 'created' );COMMIT ;
9.2 库存扣减 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 START TRANSACTION;SELECT stock FROM products WHERE id = 1 FOR UPDATE ;UPDATE products SET stock = stock - 1 WHERE id = 1 ;COMMIT ;UPDATE products SET stock = stock - 1 WHERE id = 1 AND stock > 0 ;
十、常见问题 10.1 事务占用太多 1 2 3 4 5 6 7 8 9 10 11 12 SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING' ;SELECT * FROM information_schema.INNODB_TRX WHERE trx_state = 'LOCK WAIT' ;
10.2 锁表了怎么办 1 2 3 4 5 6 7 8 9 10 11 12 13 SHOW OPEN TABLES WHERE In_use > 0 ;SHOW PROCESSLIST; KILL thread_id;
参考资料
持续更新中…欢迎收藏!
#MySQL #事务 #锁 #ACID #隔离级别 #教程