Mysql InnoDB行锁实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。下面通过一些实际例子来加以说明。

(1)在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。

在如表20-9所示的例子中,开始tab_no_index表没有索引:

mysql> create table tab_no_index(id int,name varchar(10)) engine=innodb;

Query OK, 0 rows affected (0.15 sec)

mysql> insert into tab_no_index values(1,'1'),(2,'2'),(3,'3'),(4,'4');

Query OK, 4 rows affected (0.00 sec)

Records: 4  Duplicates: 0  Warnings: 0

表20-9         InnoDB存储引擎的表在不使用索引时使用表锁例子

  www.2cto.com

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_no_index where id = 1 ;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_no_index where id = 2 ;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

mysql> select * from tab_no_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

   www.2cto.com

mysql> select * from tab_no_index where id = 2 for update;

等待

在如表20-9所示的例子中,看起来session_1只给一行加了排他锁,但session_2在请求其他行的排他锁时,却出现了锁等待!原因就是在没有索引的情况下,InnoDB只能使用表锁。当我们给其增加一个索引后,InnoDB就只锁定了符合条件的行,如表20-10所示。

创建tab_with_index表,id字段有普通索引:

mysql> create table tab_with_index(id int,name varchar(10)) engine=innodb;

Query OK, 0 rows affected (0.15 sec)

mysql> alter table tab_with_index add index id(id);

Query OK, 4 rows affected (0.24 sec)

Records: 4  Duplicates: 0  Warnings: 0

表20-10    InnoDB存储引擎的表在使用索引时使用行锁例子

  www.2cto.com

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 ;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 2 ;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

mysql> select * from tab_with_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

mysql> select * from tab_with_index where id = 2 for update;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

(2)由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。

在如表20-11所示的例子中,表tab_with_index的id字段有索引,name字段没有索引:

mysql> alter table tab_with_index drop index name;

Query OK, 4 rows affected (0.22 sec)

Records: 4  Duplicates: 0  Warnings: 0

mysql> insert into tab_with_index  values(1,'4');

Query OK, 1 row affected (0.00 sec)

mysql> select * from tab_with_index where id = 1;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

| 1    | 4    |

+------+------+

2 rows in set (0.00 sec)

表20-11    InnoDB存储引擎使用相同索引键的阻塞例子

  www.2cto.com

session_1

session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 and name = '1' for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

+------+------+

1 row in set (0.00 sec)

虽然session_2访问的是和session_1不同的记录,但是因为使用了相同的索引,所以需要等待锁:

mysql> select * from tab_with_index where id = 1 and name = '4' for update;

等待

(3)当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁。

  www.2cto.com

在如表20-12所示的例子中,表tab_with_index的id字段有主键索引,name字段有普通索引:

mysql> alter table tab_with_index add index name(name);

Query OK, 5 rows affected (0.23 sec)

Records: 5  Duplicates: 0  Warnings: 0

表20-12    InnoDB存储引擎的表使用不同索引的阻塞例子

·          session_1

·          session_2

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> select * from tab_with_index where id = 1 for update;

+------+------+

| id   | name |

+------+------+

| 1    | 1    |

| 1    | 4    |

+------+------+

2 rows in set (0.00 sec)

   www.2cto.com

Session_2使用name的索引访问记录,因为记录没有被索引,所以可以获得锁:

mysql> select * from tab_with_index where name = '2' for update;

+------+------+

| id   | name |

+------+------+

| 2    | 2    |

+------+------+

1 row in set (0.00 sec)

由于访问的记录已经被session_1锁定,所以等待获得锁。:

mysql> select * from tab_with_index where name = '4' for update;

(4)即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnoDB将使用表锁,而不是行锁。因此,在分析锁冲突时,别忘了检查SQL的执行计划,以确认是否真正使用了索引。关于MySQL在什么情况下不使用索引的详细讨论,参见本章“索引问题”一节的介绍。

  www.2cto.com

在下面的例子中,检索值的数据类型与索引字段不同,虽然MySQL能够进行数据类型转换,但却不会使用索引,从而导致InnoDB使用表锁。通过用explain检查两条SQL的执行计划,我们可以清楚地看到了这一点。

例子中tab_with_index表的name字段有索引,但是name字段是varchar类型的,如果where条件中不是和varchar类型进行比较,则会对name进行类型转换,而执行的全表扫描。

mysql> alter table tab_no_index add index name(name);

Query OK, 4 rows affected (8.06 sec)

Records: 4  Duplicates: 0  Warnings: 0

mysql> explain select * from tab_with_index where name = 1 \G

*************************** 1. row ***************************

id: 1

select_type: SIMPLE

table: tab_with_index

type: ALL

possible_keys: name

key: NULL

key_len: NULL

ref: NULL

rows: 4

Extra: Using where

1 row in set (0.00 sec)

mysql> explain select * from tab_with_index where name = '1' \G

*************************** 1. row ***************************

id: 1  www.2cto.com

select_type: SIMPLE

table: tab_with_index

type: ref

possible_keys: name

key: name

key_len: 23

ref: const

rows: 1

Extra: Using where

1 row in set (0.00 sec)

Mysql InnoDB行锁实现方式(转)的更多相关文章

  1. Mysql InnoDB行锁实现方式

    Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...

  2. mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

    一.概述 Innodb 行锁是通过给索引上的索引项加锁来实现的.这一点与(oracle,sql server)不同后者是通过在数据块中对相应的数据行加锁.这意味着只有通过索引条件检索数据,innodb ...

  3. Mysql InnoDB行锁不使用索引锁表的时候会锁整张表

    原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...

  4. Mysql研磨之InnoDB行锁模式

    事务并发带来的一些问题 (1)更新丢失(LostUpdate):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题最后的更新覆盖了由其 ...

  5. MySQL锁---InnoDB行锁需要注意的细节

    前言 换了工作之后,接近半年没有发博客了(一直加班),emmmm.....今天好不容易有时间,记录下工作中遇到的一些问题,接下来应该重拾知识点了.因为新公司工作中MySQL库经常出现查询慢,锁等待,节 ...

  6. MySQL锁:03.InnoDB行锁

    目录 InnoDB 行锁 锁排查可以用的视图和数据字典 InnoDB 行锁兼容性 InnoDB行锁之共享锁 共享锁: 查看InnoDB锁 InnoDB行锁实现机制 对普通索引上锁 InnoDB隐式.显 ...

  7. Innodb行锁源码学习(一)

    Innodb是mysql数据库中目前最流行的存储引擎,innodb相对其它存储引擎一个很大的特点是支持事务,并且支持行粒度的锁.今天我重点跟大家分享下innodb行锁实现的基础知识.由于篇幅比较大,文 ...

  8. MySQL InnoDB引擎锁的总结

    为什么要锁 我们开的的各式各样系统中,系统运行需要CPU.内存.I/O.磁盘等等资源.但除了硬资源外,还有最为重要的软资源:数据. 当人们访问操作我们的系统时,其实归根是对数据的查看与生产.那么对于同 ...

  9. 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

    该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...

随机推荐

  1. Win7下如何设置护眼的电脑豆沙绿界面?保护眼睛的颜色设置教程

    关爱心灵的窗户——眼睛! 随着科技发展,使用电脑的人越来越多,由于使用电脑时间过长,我们的眼睛也越发容易疲劳,干燥.如何才能使电脑对人眼的伤害减小到最 小. 小编建议大家可以把窗口背景色设置成护眼色. ...

  2. iOS 下ARC的内存管理机制

    本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...

  3. 【bzoj1082】 SCOI2005—栅栏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1082 (题目链接) 题意 给出m块木柴,以及n块木板,要求将m块木柴做木板,要求将木柴切割成与木板一 ...

  4. PowerShell控制台快捷键

    按键 功能 ← 光标向左移动一个字符 Ctrl + ← 光标向左移动一个单词 → 光标向右移动一个字符 Ctrl + → 光标向右移动一个单词 Home键 光标移动到行首 End键 光标移动到行尾 D ...

  5. Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)

    catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...

  6. Zabbix邮件报警-->Script

    Version:3.0.1 邮件报警有两种media 1.Email zabbix发送报警邮件到指定smtp服务器(使用系统自带的sendmail,发送邮箱是zabbix服务器的本地邮箱账号) 再由s ...

  7. 缺陷管理系统mantisbt环境搭建

    mantisbt 搭载在lamp环境下 <VirtualHost *:8000> DocumentRoot "/data/mantisbt" </VirtualH ...

  8. AngularJs form.FormController、ngModel.NgModelController

    form.FormController FormController跟踪所有他所控制的和嵌套表单以及他们的状态,就像有效/无效或者脏值/原始. 每个表单指令创建一个FormController实例. ...

  9. 系统配置 之:远程桌面连接(win7系统)

    本文包括两部分: 1.配置远程桌面连接 2.解决[远程桌面连接不上] 一.远程桌面连接设置 [远程桌面连接配置] Win7系统下的远程桌面连接设置,如果是其他系统或 Win8 及其以上系统,也可作为参 ...

  10. JS+JavaBean判断管理员增删改的操作权限

    目标:用户分管理员和普通用户2种,都可以登陆,但是管理员才可以执行增删改的权限,普通用户可以看,但是执行的时候提示权限不足 帖代码片段:我只会这一种,在JSP页面判断 省略得权限数值方法: <% ...