提到索引,首先想到的是效率提高,查询速度提升,不知不觉都会有一种心理趋向,管它三七二十一,先上个索引提高一下效率..但是索引其实也是暗藏杀机的...

今天压测带优化项目,开着Jmeter高并发访问项目,后台连着mysql通过show processlist命令查看查询情况,发现些sql语句需要优化,就在关键字段上上了索引.效果很明显项目的吞吐量瞬间提高到原来3倍,但是问题也出现了,日志中报出大量的死锁错误.本来以为程序逻辑有问题,定位了一下程序块,大体逻辑如下:

userDao.updateByUserId(userId);
userDao.save(user);

简单说就是,一个按照表中的userId字段进行更新,一个按照表中的主键进行保存.逻辑上看不出来什么问题,前前后后也尝试了各种方法,并添加了各种日志进行排查都无果.一筹莫展之际想到这个问题是在我添加索引之后出现的,也许和索引有关,之前记得读到过有关索引引起问题的帖子,但是具体内容已经忘记了,然后去掉了表中的索引(userId字段)后,果然再也不报错了,死锁消失了.进而探究了一下原因:

找到一篇博客进行了比较详细的介绍: http://blog.csdn.net/aesop_wubo/article/details/8286215

简要的说就是Mysql的innodb引擎支持事务,更新时采用的是行级锁,会在使用中的索引上加锁,如果使用的主键索引,直接锁主键索引,如果使用的非主键索引,则先锁索引,再锁对应的主键索引.故而在根据非主键索引进行更新时,实际上需要3步:

1)先获取索引锁

2)获取对应记录的主键锁

3)按照主键完成更新操作

在高并发的情况下实际上这里就存在问题了, 由于上面说的1)和2)是按照先锁索引,再锁主键的顺序,那么只要存在先锁主键,再锁索引这种反顺序操作那么就能达成死锁.也就是说一个获取了索引锁,等待主键锁,另一个获取了主键锁,等待获取索引锁.造成互相等待的死锁情况.

这里补充说明一下我上面例子中为何导致死锁:
userDao.updateByUserId(userId)这句是按照非主键索引更新,故先锁非主键索引,再锁主键索引.
userDao.save(user)这句按照主键保存对象,由于更新的字段中包含索引字段,故在获取主键索引后,需要获取索引字段的锁,以便完成字段更新.

这就满足了获取锁的顺序与上一句完全相反,达成死锁条件~

解法:

说了这么多,解决方案也就明晰了,只要让更新操作中带有主键即可.也就是让获取锁的顺序一致即可.我这里的例子userDao.updateByUserId(userId)更新时加入主键,要么就是拆分成2次操作,先查询到对应的记录,再根据主键来更新.

Mysql索引引起的死锁的更多相关文章

  1. [经验分享] MySQL Innodb表导致死锁日志情况分析与归纳【转,纯学习】

    在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志. 两个sql语句如下: (1)insert into backup_ta ...

  2. MySQL Innodb表导致死锁日志情况分析与归纳

    发现当备份表格的sql语句与删除该表部分数据的sql语句同时运行时,mysql会检测出死锁,并打印出日志   案例描述在定时脚本运行过程中,发现当备份表格的sql语句与删除该表部分数据的sql语句同时 ...

  3. Mysql 原理以及常见mysql 索引等

    ## 主键 超键 候选键 外键 (mysql数据库常见面试题) 数据库之互联网常用架构方案 数据库之互联网常用分库分表方案 分布式事务一致性解决方案 MySQL Explain详解 ## 数据库事务的 ...

  4. 27.MySQL 索引、事务与存储引擎

    MySQL 索引.事务与存储引擎 目录 MySQL 索引.事务与存储引擎 MySQL 索引 索引的概念 索引的作用及副作用 索引的作用 索引的副作用 创建索引的原则依据 索引的分类和创建 普通索引 唯 ...

  5. 一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1 .mysql索引结构,各自的优劣 2 .索引的设计原则 3 .mysql锁的类型有哪些 4 .mysql执行计划怎么看 ...

  6. 深入MySQL索引

    MySQL索引作为数据库优化的常用手段之一在项目优化中经常会被用到, 但是如何建立高效索引,有效的使用索引以及索引优化的背后到底是什么原理?这次我们深入数据库索引,从索引的数据结构开始说起. 索引原理 ...

  7. MySQL 索引

    MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是 ...

  8. MYSQL索引结构原理、性能分析与优化

    [转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...

  9. MySQL索引原理及慢查询优化

    原文:http://tech.meituan.com/mysql-index.html 一个慢查询引发的思考 select count(*) from task where status=2 and ...

随机推荐

  1. [osg]节点遍历nodevisitor浅析

    参考:https://www.cnblogs.com/hzhg/archive/2010/12/17/1908764.html OSG中节点的访问使用的是一种访问器模式.一个典型的访问器涉及抽象访问者 ...

  2. 认识flask框架-2

    1.json:基于键值对的字符串,轻量级的数据交互格式,用来传输数据 2.json模块 dumps:把字典转化成json字符串. loads:把json字符串转成字典. dump.load操作的是文件 ...

  3. 【LeetCode】28. Implement strStr() (2 solutions)

    Implement strStr() Implement strStr(). Returns a pointer to the first occurrence of needle in haysta ...

  4. 大数据新手之路二:安装Flume

    Ubuntu16.04+Flume1.8.0 1.下载apache-flume-1.8.0-bin.tar.gz http://flume.apache.org/download.html 2.解压到 ...

  5. eslint简单的规范

    module.exports = { root: true, parser: 'babel-eslint', parserOptions: { sourceType: 'module' }, // h ...

  6. C#中统计一个过程消耗的时间

    使用Unity进行的测试,代码如下: using System.Collections; using System.Collections.Generic; using UnityEngine; us ...

  7. 合并k个排序的列表 Merge k Sorted Lists

    2018-11-25 22:58:52 问题描述: 问题求解: 本题可以使用优先队列高效的进行求解,整体的时间复杂度为O(nlogk). public ListNode mergeKLists(Lis ...

  8. 确认OHS版本的方法

    还是 opatch lsinventory 好用 C:\Oracle\Middleware\ohs\OPatch>opatch lsinventory Oracle Interim Patch ...

  9. Getting Started with Processing 第五章的easing问题

    分析 使用 easing easing 的感官目的是为了 draw 的时候,画的图形不是即时 mouseX 的值,而是稍有落后一点.从算法分析,就是让所画图形的 x 坐标 落后于 mouseX 的值, ...

  10. dynamic遇上ADO.NET

    传说中的dynamic dynamic是个不合群.不按规则办事的家伙,可以说是个异形,但更恐怖的是它又是无所不知的,任何事情都难不了它(咳咳,它似乎与Lambda表达式是死对头).这令人想起<死 ...