摘要:有天,一朋友在线上执行一条 update 语句修改数据库数据的时候,where 条件没有带上索引,导致业务直接崩了,被老板教训了一波。

本文分享自华为云社区《update 没有索引,会锁全表!》,作者: 小林coding 。

有天,一朋友在线上执行一条 update 语句修改数据库数据的时候,where 条件没有带上索引,导致业务直接崩了,被老板教训了一波。

这次我们就来看看:

  • 为什么会发生这种的事故?
  • 又该如何避免这种事故的发生?

说个前提,接下来说的案例都是基于 InnoDB 存储引擎,且事务的隔离级别是可重复读。

为什么会发生这种的事故?

InnoDB 存储引擎的默认事务隔离级别是「可重复读」,但是在这个隔离级别下,在多个事务并发的时候,会出现幻读的问题,所谓的幻读是指在同一事务下,连续执行两次同样的查询语句,第二次的查询语句可能会返回之前不存在的行。

因此 InnoDB 存储引擎自己实现了行锁,通过 next-key 锁(记录锁和间隙锁的组合)来锁住记录本身和记录之间的“间隙”,防止其他事务在这个记录之间插入新的记录,从而避免了幻读现象。

当我们执行 update 语句时,实际上是会对记录加独占锁(X 锁)的,如果其他事务对持有独占锁的记录进行修改时是会被阻塞的。另外,这个锁并不是执行完 update 语句就会释放的,而是会等事务结束时才会释放。

在 InnoDB 事务中,对记录加锁带基本单位是 next-key 锁,但是会因为一些条件会退化成间隙锁,或者记录锁。加锁的位置准确的说,锁是加在索引上的而非行上。

比如,在 update 语句的 where 条件使用了唯一索引,那么 next-key 锁会退化成记录锁,也就是只会给一行记录加锁。

这里举个例子,这里有一张数据库表,其中 id 为主键索引。

假设有两个事务的执行顺序如下:

可以看到,事务 A 的 update 语句中 where 是等值查询,并且 id 是唯一索引,所以只会对 id = 1 这条记录加锁,因此,事务 B 的更新操作并不会阻塞。

但是,在 update 语句的 where 条件没有使用索引,就会全表扫描,于是就会对所有记录加上 next-key 锁(记录锁 + 间隙锁),相当于把整个表锁住了

假设有两个事务的执行顺序如下:

可以看到,这次事务 B 的 update 语句被阻塞了。

这是因为事务 A的 update 语句中 where 条件没有索引列,所有记录都会被加锁,也就是这条 update 语句产生了 4 个记录锁和 5 个间隙锁,相当于锁住了全表。

因此,当在数据量非常大的数据库表执行 update 语句时,如果没有使用索引,就会给全表的加上 next-key 锁, 那么锁就会持续很长一段时间,直到事务结束,而这期间除了 select ... from语句,其他语句都会被锁住不能执行,业务会因此停滞,接下来等着你的,就是老板的挨骂。

那 update 语句的 where 带上索引就能避免全表记录加锁了吗?

并不是。

关键还得看这条语句在执行过程种,优化器最终选择的是索引扫描,还是全表扫描,如果走了全表扫描,就会对全表的记录加锁了

又该如何避免这种事故的发生?

我们可以将 MySQL 里的 sql_safe_updates 参数设置为 1,开启安全更新模式。

官方的解释:
If set to 1, MySQL aborts UPDATE or DELETE statements that do not use a key in the WHERE clause or a LIMIT clause. (Specifically, UPDATE statements must have a WHERE clause that uses a key or a LIMIT clause, or both. DELETE statements must have both.) This makes it possible to catch UPDATE or DELETE statements where keys are not used properly and that would probably change or delete a large number of rows. The default value is 0.

大致的意思是,当 sql_safe_updates 设置为 1 时。

update 语句必须满足如下条件之一才能执行成功:

  • 使用 where,并且 where 条件中必须有索引列;
  • 使用 limit;
  • 同时使用 where 和 limit,此时 where 条件中可以没有索引列;

delete 语句必须满足如下条件之一才能执行成功:

  • 使用 where,并且 where 条件中必须有索引列;
  • 同时使用 where 和 limit,此时 where 条件中可以没有索引列;

如果 where 条件带上了索引列,但是优化器最终扫描选择的是全表,而不是索引的话,我们可以使用 force index([index_name]) 可以告诉优化器使用哪个索引,以此避免有几率锁全表带来的隐患。

总结

不要小看一条 update 语句,在生产机上使用不当可能会导致业务停滞,甚至崩溃。

当我们要执行 update 语句的时候,确保 where 条件中带上了索引列,并且在测试机确认该语句是否走的是索引扫描,防止因为扫描全表,而对表中的所有记录加上锁。

我们可以打开 MySQL sql_safe_updates 参数,这样可以预防 update 操作时 where 条件没有带上索引列。

如果发现即使在 where 条件中带上了列索引列,优化器走的还是全标扫描,这时我们就要使用 force index([index_name]) 可以告诉优化器使用哪个索引。

这次就说到这啦,下次要小心点,别再被老板挨骂啦。

点击关注,第一时间了解华为云新鲜技术~

update 没有索引导致业务崩了,老板骂了一个小时相关推荐

  1. oracle回退的办法,【案例】Oracle for update回退导致业务阻塞的解决办法

    [案例]Oracle for update回退导致业务阻塞的解决办法 时间:2016-11-02 20:53   来源:Oracle研究中心   作者:HTZ   点击: 次 天萃荷净 Oracle研 ...

  2. navicat下对mysql创建索引导致死锁,数据库崩溃,完美解决方案

    文章目录 写在前面 一.短事务场景下,执行DDL语句场景分析 1.短事务场景下,执行表字段添加操作 2.短事务场景下,执行表字段修改操作 3.短事务场景下,执行表字段删除操作 (1)往里添加一条数据试 ...

  3. 算法工程师如何应对业务方和老板的灵魂拷问?

    文章作者:姚凯飞 编辑整理:Hoh 内容来源:作者授权 出品平台:DataFunTalk 导读:你是否有过来自用户.业务和老板们的 badcase "灵魂拷问": 我运营的首页频道 ...

  4. MySQL选错索引导致的线上慢查询事故复盘

    前言 又和大家见面了!又两周过去了,我的云笔记里又多了几篇写了一半的文章草稿.有的是因为质量没有达到预期还准备再加点内容,有的则完全是一个灵感而已,内容完全木有.羡慕很多大佬们,一周能产出五六篇文章, ...

  5. 滴滴服务器不稳定,“滴滴崩了”登上热搜!是什么原因导致滴滴崩了呢?

    原标题:"滴滴崩了"登上热搜!是什么原因导致滴滴崩了呢? 前几天,不少网友反馈滴滴崩了,出现打不了车.发布的行程也看不见.司机接到人后开启不了订单.司机无法结束订单等多种异常情况. ...

  6. mysql deadlock 展示_MySQL DeadLock -- 二级索引导致的死锁

    MySQL Deadlock 复现步骤 建表SQL CREATE TABLE `t_wms_order_item` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, ...

  7. Linux 基金会年度报告——没有人能离开 Linux 支持环境;树莓派翻新版将创建“新的”分支系统;AWS 发生中断,导致业务交付出现问题 | 开源日报

    整理 | 宋彤彤 责编 | 屠敏 开源吞噬世界的趋势下,借助开源软件,基于开源协议,任何人都可以得到项目的源代码,加以学习.修改,甚至是重新分发.关注「开源日报」,一文速览国内外今日的开源大事件吧! ...

  8. 【自动化】国内自动化与信息化产业仍有十年以上的产业繁荣;非标自动化业务你离BOSS只差一个认知

    自2016年底开始的国内自动化"小阳春",持续性不断超市场预期:其实,从长期来看,国内自动化和信息化有巨大的需求纵深,并且其经济性.必要性还会越来越强,产业的长期潜力应该是被低估的 ...

  9. 微软惹的祸!CVPR提交网站最后1小时被挤崩,官方紧急延长36小时

    视学算法报道   编辑:小咸鱼 好困 [新智元导读]CVPR提交网站宕机了,而且还是在截止时间前的最后1个小时!于是DDL被紧急延长了1天半. 什么? CVPR 2022的论文提交网站居然在deadl ...

最新文章

  1. leetcode 82. 删除排序链表中的重复元素 II
  2. Linux信号 四 异步等待信号与同步等待信号接口
  3. iperf3 测速跑不满的解决办法
  4. 安卓9.0马达框架分析
  5. android https通过载入pfx证书获取数据
  6. 运行 sudo 时会发生什么?
  7. PAT 甲级 1003
  8. 如何开发Web3D游戏
  9. 数字逻辑_半加器_全加器_全减器_乘法器
  10. Vue 扫描二维码、条形码
  11. JQuery(1)——JQuery如何读
  12. ABR算法研究综述 | A Survey on Bitrate Adaptation Schemes for Streaming Media Over HTTP(IEEE COMST‘18)阅读笔记
  13. 微信小程序开发多少钱?微信小程序开发费用
  14. autojs实用文档
  15. 创意电子学小知识:电位器
  16. 动画程序时长缩放是什么意思_1分钟做出高逼格动画!PPT中自带的小功能帮你一键搞定!...
  17. ae教程 (六)人物滤镜 (五)lomo色调
  18. 刘韧:此时使用文字 只因为文字简练
  19. cordova编译crosswalk-webview插件报错的处理办法
  20. 不良资产评估 难点与问题分析

热门文章

  1. Linux中sudo免密码
  2. 五.激光SLAM框架学习之A-LOAM框架---项目工程代码介绍---3.laserOdometry.cpp--前端雷达里程计和位姿粗估计
  3. php 502状态码,Nginx502状态码处理
  4. java8 groupingby_Java8 教程第五章之Streams Collectors groupingBy
  5. python os.walk遍历目录_Python 用 os.walk 遍历目录
  6. 微信小程序|个人简历
  7. memcache 获取key的方法,查询session存储
  8. Verilog HDL 学习笔记3-Latch
  9. dfs.datanode.max.xcievers参数导致hbase集群报错
  10. leetcode 42 python