官方文档:https://dev.mysql.com/doc/refman/5.6/en/innodb-locks-set.html

线上出现一个死锁现象,信息显示的是两条对同一个表的不同记录的update操作,表上只有一个主键索引,更新的条件上无索引,时间地段显示两个update只相差1ms

业务场景是同时一个事务中先是insert 再update新插入的行,存在并发;数据库环境是5.6,事务隔离级别RC,auto_increment_increment=1

通过定时任务实现两个会话同时对一个表先进行insert,然后update

#表结构
mysql> show create table test.t3;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t3 | CREATE TABLE `t3` (
`id` int() NOT NULL AUTO_INCREMENT,
`name` varchar() DEFAULT NULL,
`col` varchar() DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8 |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
row in set (0.00 sec)
#定时任务
* * * for i in `seq `;do /usr/local/mysql/bin/mysql -uroot -S /tmp/mysql_3309.sock -e "begin;insert into test.t3 values(null,'aa','$i');update test.t3 set name='aa$i' where col='$i';commit;";done
* * * for i in `seq `;do /usr/local/mysql/bin/mysql -uroot -S /tmp/mysql_3309.sock -e "begin;insert into test.t3 values(null,'aa','$i');update test.t3 set name='aa$i' where col='$i';commit;";done

捕获到的死锁信息

------------------------
LATEST DETECTED DEADLOCK
------------------------
-- :: 0x7f5277ba6700
*** () TRANSACTION:
TRANSACTION , ACTIVE sec fetching rows
mysql tables in use , locked
LOCK WAIT lock struct(s), heap size , row lock(s), undo log entries
MySQL thread id , OS thread handle , query id localhost root updating
update test.t3 set name='aa26' where col=''
*** () WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id page no n bits index PRIMARY of table `test`.`t3` trx id lock_mode X locks rec but not gap waiting
Record lock, heap no PHYSICAL RECORD: n_fields ; compact format; info bits
: len ; hex 8000004c; asc L;;
: len ; hex 0000000aa0be; asc ;;
: len ; hex b6000001910110; asc ;;
: len ; hex ; asc aa;;
: len ; hex ; asc ;; *** () TRANSACTION:
TRANSACTION , ACTIVE sec fetching rows
mysql tables in use , locked
lock struct(s), heap size , row lock(s), undo log entries
MySQL thread id , OS thread handle , query id localhost root updating
update test.t3 set name='aa126' where col=''
*** () HOLDS THE LOCK(S):
RECORD LOCKS space id page no n bits index PRIMARY of table `test`.`t3` trx id lock_mode X locks rec but not gap
Record lock, heap no PHYSICAL RECORD: n_fields ; compact format; info bits
: len ; hex 8000004c; asc L;;
: len ; hex 0000000aa0be; asc ;;
: len ; hex b6000001910110; asc ;;
: len ; hex ; asc aa;;
: len ; hex ; asc ;; *** () WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id page no n bits index PRIMARY of table `test`.`t3` trx id lock_mode X locks rec but not gap waiting
Record lock, heap no PHYSICAL RECORD: n_fields ; compact format; info bits
: len ; hex 8000004b; asc K;;
: len ; hex 0000000aa0bd; asc ;;
: len ; hex 3500000142133d; asc B =;;
: len ; hex ; asc aa26;;
: len ; hex ; asc ;; *** WE ROLL BACK TRANSACTION ()
------------

解决

mysql> explain update test.t3 set name='aa126' where col=''
-> ;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | UPDATE | t3 | NULL | index | NULL | PRIMARY | 4 | NULL | 382 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.00 sec)

更新操作会对主键索引进行全索引扫描,我的理解为会一行行的处理先在innodb层在主键上加X锁,然后再server层通过where条件进行过滤,释放不符合条件的记录上的锁

在where条件字段上加索引,避免全索引扫描

测试发现通过在where条件上添加索引可以解决问题,但是还是无法解释这一现象,因为单独将事务拿出来重现是不会产生阻塞的,只有高并发下才会产生。。。。有知道的朋友请留言。

最新文章

  1. LeetCode #329. Longest Increasing Path in a Matrix
  2. 第一个C++例子
  3. mysql 查看当前登陆用户匹配原则及权限user()与current_user()
  4. css3中transform的用法
  5. 我的第一个Node web程序
  6. __ATTRIBUTE__ 你知多少?【转】
  7. S5PV210之添加缺少的-内核提供的'.h'文件 linux3.0.8驱动
  8. c++ assert
  9. [OFBiz]开发 三
  10. 关于Java IM的一点资料
  11. ckeditor上传图片的注意点
  12. CvvImage类
  13. js验证IP及子网掩码的合法性
  14. 201521123109《java程序设计》第一周学习总结
  15. U盘重装Win10系统视频教程
  16. python学习日记(OOP——静态方法和类方法)
  17. 字符集之在UTF-8中,一个汉字为什么需要三个字节?
  18. 关于弹性布局的 flex-grow的用法和flex-shrink的用法
  19. 利用反射创建User类的对象
  20. (转载)用C#实现MySQL建库及建表

热门文章

  1. T4310 祖玛游戏
  2. Java类的静态块の一
  3. Java、Node.js、PHP还是.Net? 无论你选谁,我都能教你一招!
  4. An internal error occurred during: "Map/Reduce location status updater". java.lang.NullPointerException
  5. synchronized关键字修饰非静态方法与静态方法的区别
  6. spark 省份次数统计实例
  7. 洛谷 P2668 斗地主
  8. shell脚本,100以内的质数有哪些?
  9. swift中使用sqlite3
  10. 【实用工具】Teleport Pro爬取整个网站镜像到本地