衡水哪个公司做网站好,学校网站建设问卷调查表,安徽省建设厅网站人员管理,门户网站 开发注意记录一次死锁问题的分析排查
现象
底层往kafka推送设备上线数据应用层拉取设备上线消息,应用层有多个消费者并发执行将设备上线数据同步数据库表pa_terminal_channel日志报#xff1a;#xff08;Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: …记录一次死锁问题的分析排查
现象
底层往kafka推送设备上线数据应用层拉取设备上线消息,应用层有多个消费者并发执行将设备上线数据同步数据库表pa_terminal_channel日志报Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction死锁sql语句为update pa_terminal_channel SET status ‘Y’ WHERE channel_id ‘通道id’ and device_id ‘设备id’
排查思路
由于应用层有多个消费者对消息进行处理导致并发更新的情况发生手动开启事务的方式复现现象第一个窗口执行更新但不提交 第二个窗口执行更新发现进入等待随后报1025错误 经过框架查找数据库报1025错经过jdbc框架错误码转换后报Deadlock found when trying to get lock即日志中所出现的错误查看执行计划发现该条数据的type为index_merge,即数据库查询优化器介入处理此时在更新操作中使用了两个条件并且这些条件涉及到两个索引channelid和deviceid对应的索引MySQL 可能会使用多个索引来查找符合条件的行从而可能会锁定更多的行。也就意味着在同一批设备id相同但通道id不同的数据也会被锁住。因此本次死锁原因出现。
解决办法
增加channelid和deviceid的复合索引让数据库走正常的复合索引避免数据库查询优化器介入处理此时缩小更新时锁的数据行数避免触发死锁问题。 ALTER TABLE pa_terminal_channel ADD INDEX terminal_channelid_deviceid (channelID, deviceId); 增加复合索引后再观察执行计划发现已正常走复合索引。
该问题分析过程中产生的错误猜想
猜想一、业务发生事务问题导致经典死锁问题但排查业务后发现并无事务介入排除猜想二、代码中有一段获取channelid的操作有可能发生线程安全问题导致获取到相同channelid导致不同线程更新同一条数据触发死锁。排除因为在业务日志中可以看到处理后的channelid打印结果并无异常并且通过多线程模拟调用该方法并无异常 猜想三、数据库没加索引排除数据库已有channelid单值索引如果数据库执行优化器没有介入光走单值索引也不会触发死锁猜想四、数据库索引文件发生损坏排除、创建新的索引不会直接改变现有索引的结构。。验证将原有表增加复合索引后又删除复合索引后锁表问题得到解决。此过程不会导致原有channelid的索引文件发生变化但是会扰动数据库优化执行器