最近的项目,为了保障绝对的一致性,使用SERIALIZABLE作为隔离级别。
然后就爆出了很诡异的死锁。
报错log如下:
org.springframework.dao.DeadlockLoserDataAccessException: PreparedStatementCallback; SQL [xxxxx]; Deadlock found when trying to get lock;
try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
1461 2017-04-17 21:58:26.550 ERROR pool-7-thread-2
我们的sql大概是这样的:
begin;
select * from table_a where id = 6;
INSERT INTO xxx (xxxxx) ON DUPLICATE KEY UPDATE xxxxx;
UPDATE table_a SET column_a = GREATEST(column_a, 0) WHERE id = 6;
commit;
报错的概率并不高,在我们的系统中,大概只有2%的概率左右出现。
单独执行这段sql并不会有任何问题,因此定位了许久。后来灵光一下,同时开启两个事务来模拟这个操作。
方式如下:
//准备工作
1 set session transaction isolat