记一次线上程序出现mysql死锁
线上程序出现死锁
过年期间的某一天,线上程序突然宕机一次,查看core文件发现是出现了数据库死锁,项目上线这么久还是第一次碰到死锁宕机的情况,我们的项目本身并没有使用事务,为什么会出现死锁我也很懵。通过命令在数据库上查看出现死锁的日志:
mysql -h 127.0.0.1 -P 4306 -u root -p --execute="show engine innodb status \G" > ./mysql.log
查看mysql.log的内容发现有死锁内容:
SQL ERROR:Deadlock found when trying to get lock; try restarting transaction
SQL:UPDATE tbl_fleet_science SET fld_level='8', fld_level_exp='1052182' WHERE fld_science_id='1' AND fld_fleet_id='0006-00-20160828-001006-0000008';
一共有两个地方对两行这个表中的数据进行了操作,互相等待锁释放导致死锁,仔细查了一下代码中操作这个表的语句,使用的条件顺序是WHERE fld_science_id='1' AND fld_fleet_id='0006-00-20160828-001006-0000008'
,先匹配fld_science_id
后匹配fld_fleet_id
,但是tbl_fleet_science
表结构中有一个索引,索引的顺序是(tbl_fleet_science,fld_fleet_id)
,这个顺序和代码中的条件顺序是相反的。 查询了一些资料并没有找到权威的解释,没有明确证据表明这种相反的顺序会导致死锁,但是能找到的唯一有疑点的地方只有这里了,所以把这个表的索引做了修改,改为(fld_fleet_id,tbl_fleet_science)
,与代码中的使用顺序一致。
更新之后确实也没有出现过类似的问题,但是这次死锁具体是不是因为这个顺序导致的,也不能完全确定,也许是某些不可知的问题,后面的工作中如果再遇到同类问题再来解决这个问题吧。