前言
作为后端开发人员,几乎每天都与数据库打交道。对着变化莫测的需求,紧张的工期,很多程序员日复一日写着CRUD代码,无暇理会数据库实际执行原理,这是技术提高的门槛。
秉着工作处处皆学问,知其然知其所以然的信念,日常生活中我都会把遇到的问题摘录下来,总结分析背后的技术原理。
一、遇见死锁
组长让我实现一个提交申请单的功能。因为用户可以重复提交申请,而申请只能保留一份,因此我在插入新申请insert操作前,先按照用户id删除delete他之前所有申请记录。确保两个操作的一致性,我加了事务@Transactional。
简单的功能,简洁的实现。事与愿违,表中出现重复用户id记录的。查看数据发现,新的记录插入成功,是旧的数据没有删除成功。既然是事务,为什么一个执行成功,一个失败呢?
+-----------------+-----------+---------------+-----------+
| id | member_id | nick_name | is_delete |
+-----------------+-----------+---------------+-----------+
| 181025163317920 | 3288 | 蕉仔伟🍌 | |
| 181026142458439 | 3288 | 赛亚人 | |
| 181030104733141 | 3288 | 百变小樱 | |
| 181030105733272 | 3288 | 柴犬慕斯 | |
+-----------------+-----------+---------------+-----------+
4 rows in set (0.01 sec)
带着问题找原因,看看数据库的状态报告:
mysql> show engine innodb status;
| InnoDB | |
=====================================
LATEST DETECTED DEADLOCK
------------------------
2018-11-28 20:07:24 0x7f286deb7700
*** (1) TRANSACTION:
TRANSACTION 41443739, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 11