在数据库(以 MySQL/PostgreSQL 等关系型数据库为主)中,SERIALIZABLE(可串行化) 是最高的隔离级别,旨在通过严格加锁或冲突检测保证事务“像串行执行一样正确”。但代价是容易引发锁等待、死锁、性能急剧下降,甚至业务逻辑“看起来没问题却跑不通”。
下面从问题表现 → 排查思路 → 具体手段 → 常见根因 → 解决建议系统说明。
事务长时间等待(锁等待)
死锁(Deadlock)
Deadlock found吞吐量骤降
业务逻辑“不符合预期”
先确认“是不是 SERIALIZABLE 引起的”,再确认“为什么需要 SERIALIZABLE”
MySQL
SELECT @@transaction_isolation;
-- 或
SHOW VARIABLES LIKE 'transaction_isolation';
会话级
SELECT @@session.transaction_isolation;
PostgreSQL
SHOW transaction_isolation;
常见误区:
REPEATABLE READSET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
或框架(Spring)显式指定
✅ 检查:
@Transactional(isolation=...))SELECT * FROM performance_schema.data_lock_waits;
SELECT * FROM performance_schema.data_locks;
SELECT
r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx;
SELECT * FROM information_schema.innodb_trx;
SHOW ENGINE INNODB STATUS;
重点关注:
LATEST DETECTED DEADLOCK
你会看到:
SERIALIZABLE 下,事务越长越危险
SELECT *
FROM information_schema.innodb_trx
ORDER BY trx_started ASC;
看:
trx_startedtrx_statetrx_query重点看:
常见问题:
✅ 实际上:
READ COMMITTED 足够REPEATABLE READ + 显式锁@Transactional
public void bigMethod() {
query();
rpcCall(); // ❌
update();
}
SERIALIZABLE 下:
事务 A:
UPDATE a
SELECT b
事务 B:
SELECT b
UPDATE a
✅ SERIALIZABLE 下极易死锁
SELECT * FROM order WHERE user_id = 1 FOR UPDATE;
在 SERIALIZABLE:
| 场景 | 推荐 |
|---|---|
| 普通业务 | READ COMMITTED |
| 一致性要求高 | REPEATABLE READ |
| 真·强一致 | SERIALIZABLE(极少) |
原则:
事务里只留“必须原子的 SQL”
所有事务:
先 A 后 B
UPDATE account
SET balance = balance - 10
WHERE id = 1 AND version = 3;
SERIALIZABLE 的问题,90% 不是数据库问题,而是“事务设计问题”。
如果你愿意,可以:
我可以直接帮你定位是哪一行导致的。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。