最近为了提高日志入库的速度,把入库的代码改成并发的。发现部分日志入库的时候mysql报错:
Error 1213: Deadlock found when trying to get lock; try restarting transaction.
字面意思可见是有死锁了。
出现死锁,首先查询状态日志,mysql执行:
SHOW ENGINE INNODB STATUS
查询LATEST DETECTED DEADLOCK标签下的日志,可见最近一次发生死锁的语句。再加上对比正常执行的sql语句,问题定位在使用replace into上。
innodb是行级锁,而我是并发且批量去使用replace into去更新表,很容易造成同时两条语句去更新一行数据。replace的时候会给要更新的行加上排他锁(X锁),这就是造成死锁的原因。(有唯一索引的表在insert的时候,如果发生了唯一索引冲突,会加上读锁(S锁),理论上在并发处理的时候不会死锁?待证实)。