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

今天压测带优化项目,开着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. 鼠标经过事件(onmouseover)

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  2. MySQL数据库自动备份

    1.vi /home/wangcn/auto_log.sh#!/bin/bash #Shell Command For Backup MySQL Database Everyday Automatic ...

  3. c++ cmakelist 详解

    基本元素 首先cmaklist必须包括以下几个部分: #工程名 project(study_case) #cmake最低版本需求 cmake_minimum_required(VERSION 2.8. ...

  4. typeScript入门基础 (2): 数据 类型, 函数定义

    1.   number , boolean, string, null, undefind  枚举, any, array数组, 元祖, 2...枚举,需要的注意点,  下一个图,就是为什么yello ...

  5. Vuex结合 async/await 优雅的管理接口请求

    先看看 async/await 的语法 async 函数返回一个 Promise 对象 async 函数内部 return 返回的值.会成为 then 方法回调函数的参数. 1 2 3 4 async ...

  6. HTML 标记 1

    1. 文件结构 <html>                   ----------------------开始 <head>          -------------- ...

  7. @Scope注解设置创建bean的方式和生命周期

    1.1.1            Scope注解创建bean的方式和生命周期 作用 Scope设置对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式. 取 ...

  8. postMan用法

    增加: 删除: 更改: 查询:

  9. spring cloud: zuul(五): prefix访问前缀, ignoredServices粗粒度访问, yml不起作用

    路由的前缀 - 问题 zuul.prefix: 我们可以指定一个全局的前缀 strip-prefix: 是否将这个代理前缀去掉 zuul: prefix: /ecom 我的eureka:http:// ...

  10. 初步了解hg19注释文件的内容 | gtf

    hg19有哪些染色体? chr1 chr2 chr3 chr4 chr5 chr6 chr7 chr8 chr9 chr10 chr11 chr12 chr13 chr14 chr15 chr16 c ...