Mysql 系列文章主页

===============

Tips:在阅读本文前,最好先阅读 这篇(Mysql锁机制--行锁)文章~

在上篇文章中,我们看到InnoDB默认的行锁可以使得操作不同行时不会产生相互影响、不会阻塞,从而很好的解决了多事务和并发的问题。但是,那得基于一个前提,即 Where 条件中使用上了索引;反之,如果没有使用上索引,则是全表扫描、全部阻塞。本文就以实际例子来演示这种情景。

1 准备数据

1.1 建表

DROP TABLE IF EXISTS employee;
CREATE TABLE IF NOT EXISTS employee (
id INT PRIMARY KEY auto_increment,
name VARCHAR(40),
money INT
)ENGINE INNODB;

注意:ENGINE 是 INNODB(因为 InnoDB 才支持行锁)

1.2 插入数据

INSERT INTO employee(name, money) VALUES('', 10000);
INSERT INTO employee(name, money) VALUES('', 10000);

提示:'1001' & '1002' 既是字符串,也是数字(后面会用到)

2 没有建索引的情形

到现在为止,没有显示地为 Employee 表建立索引。

2.1 准备

还是老规矩,两个会话(终端),左边是白色背景的,右边是黑色背景的,并且均设置 autocommit = 0

2.2 测试

2.2.1 在左侧会话中执行更新

Sql 语句:

UPDATE employee SET money = money + 10000 WHERE name = '';

结果:

2.2.2 在右侧会话中执行更新

Sql 语句:

UPDATE employee SET money = money + 5000 WHERE name = '';

结果:如下图所示,更新操作被阻塞了!

2.2.3 在左侧执行 COMMIT 命令

提示:执行的时候注意查看右边Sql语句执行情况的变化

2.2.4 右侧的Sql语句正常执行了,耗时 18.19 秒

2.2.5 右侧也执行一下提交

2.2.6 左侧查看一下数据

2.2.7 右侧查看一下数据

两边结果相同,且正确。

但问题是,左侧操作的是 name = '1001' 记录而右侧操作的是 name = '1002' 记录,右侧还是被阻塞了,说明,左侧的更新操作锁住了全表!究其原因,是因为 name 字段上没有索引!

2.3 结论

当 Where 查询条件中的字段没有索引时,更新操作会锁住全表!

3 索引失效的情形

现在来演示索引失效的情形;要想索引失效,前提得要有索引啊;于是,先建立索引。

3.1 建立索引

CREATE INDEX idx_name ON employee(name);

3.2 有索引情况下的行锁演示

提示:还是老规矩,两个会话(终端),左边是白色背景的,右边是黑色背景的,并且均设置 autocommit = 0

3.2.1 在左侧会话中执行更新

Sql 语句:

UPDATE employee SET money = money + 10000 WHERE name = '';

结果:

3.2.2 在右侧会话中执行更新

Sql 语句:

UPDATE employee SET money = money + 5000 WHERE name = '';

结果:

立即执行,没有被阻塞!

3.2.3 左右两侧分别执行提交

3.2.4 左侧查看结果

3.2.5 右侧查看结果

两边的结果相同,且正确。

3.2.6 结论

可以看到,在有索引的情况下,更新不同的行,InnoDB 默认的行锁不会阻塞。

3.3 索引失效情况下的行锁演示

提示:还是老规矩,两个会话(终端),左边是白色背景的,右边是黑色背景的,并且均设置 autocommit = 0

3.3.1 在左侧会话中执行更新

Sql 语句:(注意:name = 1001 的 1001 两边没有加单引号)

UPDATE employee SET money = money + 10000 WHERE name = 1001;

结果:

3.3.2 在右侧会话中执行更新

Sql 语句:

UPDATE employee SET money = money + 5000 WHERE name = '';

结果:

被阻塞!说明左侧会话锁住了整张表!

3.3.3 左侧执行提交(注意查看右侧会话中Sql执行的情况变化)

3.3.4 查看右侧会话

右侧会话中的更新操作被执行,耗时 20.68 秒

3.3.5 右侧也提交

3.3.6 左侧查看结果

3.3.7 右侧查看结果

两边结果相同,且正确。

3.3.8 结论

Where 条件中的查询字段虽然有索引,但是索引失效时(本例子中是字符串没有加单引号),InnoDB 默认的行锁更新操作变为表锁。

4 结论

没有索引或者索引失效时,InnoDB 的行锁变表锁

原因:Mysql 的行锁是通过索引实现的!

Mysql锁机制--索引失效导致行锁变表锁的更多相关文章

  1. Mysql在InnoDB引擎下索引失效行级锁变表锁案例

    先做好准备,创建InnoDB引擎数据表,并添加了相应的索引 DROP TABLE IF EXISTS `innodb_lock`; CREATE TABLE `innodb_lock` ( `a` ) ...

  2. MySQL优化篇系列文章(二)——MyISAM表锁与InnoDB锁问题

    我可以和面试官多聊几句吗?只是想... MySQL优化篇系列文章(基于MySQL8.0测试验证),上部分:优化SQL语句.数据库对象,MyISAM表锁和InnoDB锁问题. 面试官:咦,小伙子,又来啦 ...

  3. SQL优化 MySQL版 - 避免索引失效原则(一)

    避免索引失效原则(一) 精力有限,剩余的失效原则将会在 <避免索引失效原则(二)>中连载出来,请谅解 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 避免索引失效的一些原 ...

  4. SQL优化 MySQL版 - 避免索引失效原则(二)

    避免索引失效原则(二) 注:继上一篇文章继续讲解: 避免索引失效原则(一)https://www.cnblogs.com/StanleyBlogs/p/10482048.html#4195062 作者 ...

  5. MySQL 行锁 表锁机制

    MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整的很惨!不知坑在何方?没事,我来给你们标记几个坑.遇到了可别乱踩.通过本章内容,带你学习MySQL的行锁 ...

  6. [转]MySQL 表锁和行锁机制

    本文转自:http://www.cnblogs.com/itdragon/p/8194622.html MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整 ...

  7. MySQL高级第四章——MySQL的锁机制

    一.概述 1.定义 锁是计算机协调多个进程或线程并发访问某一资源的限制. 2.分类 操作类型来分: 读锁(共享锁)和写锁(排它锁) 数据粒度来分: 表锁和行锁 二.三锁 1.表锁——偏读 特点: 偏向 ...

  8. 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁

    转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...

  9. mysql优化二之锁机制

    mysql优化二之锁机制 mysql提供了锁机制和MVCC机制来保证并发操作的安全性,这里主要讨论锁机制, MVCC见下篇文章 mysql的锁按照锁粒度可分为行锁与表锁,按照操作类型划分可读锁和写锁 ...

随机推荐

  1. MySQL“Another MySQL daemon already running with the same unix socket” 报错信息处理

    Mysql "Another Mysql daemon already running with the same unix socket" 解决办法:rm var/lib/mys ...

  2. Java服务器端生成报告文档:使用SQL Server Report Service(SSRS)

    SQL Server Report Service(SSRS)提供了Asp.Net和WinForm两类客户端组件封装,因此使用C#实现SSRS报表的导出功能,仅需要使用相应的组件即可. Java操作S ...

  3. centos7.0下的 systemctl 用法

    参考链接: http://man.linuxde.net/systemctl

  4. 阿里云API网关(11)外网访问 阿里云API网关内定义的API步骤:

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  5. Python基础--函数的定义和调用

    一.函数的作用: 提高代码的可读性,减少代码的冗余,方便调用和修改,组织结构清晰 二.函数的定义:函数遵循先定义后调用的原则 1.无参函数 def funcname(): #def 是关键字,后跟函数 ...

  6. python——函数

    python--函数 1.介绍: 在过去的十年间,大家广为熟知的编程方法无非两种:面向对象和面向过程,其实,无论哪种,都是一种编程的规范或者是如何编程的方法论.而如今,一种更为古老的编程方式:函数式编 ...

  7. POJ-1287 Networking---裸的不能再裸的MST

    题目链接: https://vjudge.net/problem/POJ-1287 题目大意: 模板 #include<iostream> #include<cstdio> # ...

  8. Go-GRPC 初体验

    grpc 跟常见的client-server模型相似(doubbo)grpc 编码之前需要准备以下环境: 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消 ...

  9. 【转载】Ubuntu 12.04 LTS 中文输入法的安装

    原文地址 :  http://www.cnblogs.com/zhj5chengfeng/archive/2013/06/23/3150620.html 我装的是英文版的 Ubuntu12.04,如果 ...

  10. JavaScript 图

    TypeScript方式实现源码 // 图的遍历算法 // 算 法 数据结构 描 述 // 深度优先搜索 栈 通过将顶点存入栈中,顶点是沿着路径被探索的,存在新的相 // 邻顶点就去访问 // 广度优 ...