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

今天压测带优化项目,开着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. C++.sprintf

    ZC:sprintf,sprintf_s 1.经测试 sprintf,是会在字符串的最后 加上'\0'的,∴ 不用担心 字符串的结尾的问题 2. 3. 4. 5.

  2. .NET扩展方法 封装公用方法

    定义方法的时候  第一个参数前面加上this   表示这个方法可以被IQueryable类型的对象.出来  调用的时候 只用传第二个参数  第一个参数不用传 第一个参数就是.出当前方法的参数 定义扩展 ...

  3. JDK7+EclipseIDE+Tomcat7.0.55++mybatis3+Maven3.2.2 构建webapp 的java 的maven项目

    构建Maven项目 工具 JDK7+EclipseIDE+Tomcat7.0.55++mybatis3+Maven3.2.2 JDK 下载地址 http://www.oracle.com/techne ...

  4. [JS]给String对象添加方法,使传入的字符串字符之间以空格分开输出

    看到一个这样子的面试题: 给String对象添加一个方法,传入一个string类型的参数,然后将string的每一个字符间加空格返回,例如:addSpace("hello world&quo ...

  5. yum的配置文件介绍

    yum 的配置文件分为两部分:main 和repository   main 部分定义了全局配置选项,整个yum 配置文件应该只有一个main.常位于/etc/yum.conf 中. reposito ...

  6. word空白页怎么删除

    最简单的,直接按键盘上的BackSpace或者Delete键,来进行删除.  分页符过到.打开“编辑”-->替换-->高级-->特殊字符-->手工分页符-->“全部替换” ...

  7. (转)c# 扩展方法

    扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型.扩展方法必须是静态方法,可以像实例方法一样进行调用.且调用同名中实际定义的方法优先级要高于扩展方法. 先来 ...

  8. java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration

    java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration 最近在做项目的时候遇到了这个问题,很是困扰,多次尝试后发现是jar包的问 ...

  9. 02linux 基本命令

    系统环境变量的设置 以nginx为例: 方式一: ~/.bash_profile  这是个人的 /etc/profile 为系统的环境变量 vim /etc/profile.d/nginx.sh #在 ...

  10. javascript 两张图片切换 三目运算符

    <body> <script> function changeImage(){ var s = document.getElementById('myimage'); s.sr ...