MySQL InnoDB存储引擎中的锁机制
1.隔离级别
Read Uncommited(RU):这种隔离级别下,事务间完全不隔离,会产生脏读,可以读取未提交的记录,实际情况下不会使用。
Read Committed (RC):仅能读取到已提交的记录。针对当前读,RC隔离级别保证对读取到的记录加锁 (记录锁),存在幻读现象。所谓幻读是指在同一个事务中,多次执行同一个查询,返回的记录不完全相同的现象。幻读产生的根本原因是,在RC隔离级别下,每条语句都会读取已提交事务的更新,若两次查询之间有其他事务提交,则会导致两次查询结果不一致。虽然如此,读提交隔离级别在生产环境中使用很广泛。
Repeatable Read (RR):针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。mysql的innodb比较特殊,RR即解决了幻读问题,主要通过间隙锁实现。
Serializable:从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。
查看隔离级别:
show variables like 'tx_isolation';
SELECT @@tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@global.tx_isolation;
修改隔离级别:
用户可以用SET TRANSACTION语句改变单个会话或者所有新进连接的隔离级别。它的语法如下:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
2. 一致性非锁定读和一致性锁定读
一致性非锁定读:
指InnoDB存储引擎通过行多版本控制的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行delete或update操作,这时读取操作不会因此去等待行上锁的释放。InnoDB存储引擎会去读取行的一个快照数据。快照数据是指该行的之前版本的数据,该实现是通过undo段来完成的。读取快照数据是不需要上锁的,因为没有事务需要对历史数据进行修改操作。在InnoDB存储引擎的默认设置下,这是默认的读取方式,即读取不会占用和等待表上的锁。
一致性锁定读:
在某些情况下,用户需要显式的对数据库读取操作进行加锁,以保证数据逻辑的一致性。InnoDB存储引擎对于select支持两种一致性的锁定读操作。
select...for update 对读取的行记录加一个X锁
select...lock in share mode 对读取的行记录加一个S锁
3. 行锁的三种算法
record lock:记录锁,单个记录上的锁;record lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,则会使用隐式的主键来进行锁定。
gap lock:间隙锁,锁定一个范围,但是不包含记录本身;
next-key lock:gap lock+record lock,锁定一个范围,并锁定记录本身。设计的目的是解决幻读问题。
当查询的索引含有唯一属性时,InnoDB存储引擎会对next-key lock进行优化,将其降级为record lock,即仅锁住索引本身,而不是范围。若是辅助索引,则加的是next-key lock,特别需要注意的是,InnoDB存储引擎还会对辅助索引下一个键值加上gap lock。
可以通过下面两种方式来显式的关闭gap lock:
(1)将事务的隔离级别设置为Read Committed;
(2)将参数innodb_locks_unsafe_for_binlog设置为1.
4. 查看锁请求的信息
(1)show engine innodb status\G;
(2)show full processlist;
(3)查看information_schema下的表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS;
5. 锁相关的状态变量
mysql> show status like 'innodb_row_lock%';
+-------------------------------+--------+
| Variable_name | Value |
+-------------------------------+--------+
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 490578 |
| Innodb_row_lock_time_avg | 37736 |
| Innodb_row_lock_time_max | 121411 |
| Innodb_row_lock_waits | 13 |
+-------------------------------+--------+
Innodb 的行级锁定状态变量不仅记录了锁定等待次数,还记录了锁定总时长,每次平均时长,以及最大时长,此外还有一个非累积状态量显示了当前正在等待锁定的等待数量。对各个状态量的说明如下:
- Innodb_row_lock_current_waits:当前正在等待锁定的数量;
- Innodb_row_lock_time:从系统启动到现在锁定总时间长度;
- Innodb_row_lock_time_avg:每次等待所花平均时间;
- Innodb_row_lock_time_max:从系统启动到现在等待最常的一次所花的时间;
- Innodb_row_lock_waits:系统启动后到现在总共等待的次数;
对于这5 个状态变量, 比较重要的主要是Innodb_row_lock_time_avg(等待平均时长) ,Innodb_row_lock_waits(等待总次数)以及Innodb_row_lock_time(等待总时长)这三项。尤其是当等待次数很高,而且每次等待时长也不小的时候,就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手指定优化计划。
6. 合理使用InnoDB
(1)尽可能让所有的数据检索都通过索引来完成;
(2)合理设计索引,让Innodb 在索引键上面加锁的时候尽可能准确,尽可能的缩小锁定范围,避免造成不必要的锁定而影响其他Query 的执行;
(3)尽可能减少基于范围的数据检索过滤条件,避免因为间隙锁带来的负面影响而锁定了不该锁定的记录;
(4)尽量控制事务的大小,减少锁定的资源量和锁定时间长度;
(5)在业务环境允许的情况下,尽量使用较低级别的事务隔离,以减少MySQL 因为实现事务隔离级别所带来的附加成本;
几篇非常好的博客:
一个最不可思议的MySQL死锁分析:http://hedengcheng.com/?p=844
MySQL加锁处理分析:http://hedengcheng.com/?p=771
Innodb锁系统(1)之如何阅读死锁日志:http://mysqllover.com/?p=411
MySQL InnoDB存储引擎中的锁机制的更多相关文章
- MySQL数据库InnoDB存储引擎中的锁机制
MySQL数据库InnoDB存储引擎中的锁机制 http://www.uml.org.cn/sjjm/201205302.asp 00 – 基本概念 当并发事务同时访问一个资源的时候,有可能 ...
- MySQL数据库InnoDB存储引擎中的锁机制(转载)
http://www.uml.org.cn/sjjm/201205302.asp 00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化. 锁就是 ...
- MySQL 温故而知新--Innodb存储引擎中的锁
近期碰到非常多锁问题.所以攻克了后,细致再去阅读了关于锁的书籍,整理例如以下:1,锁的种类 Innodb存储引擎实现了例如以下2种标准的行级锁: ? 共享锁(S lock),同意事务读取一行数据. ? ...
- MySQL InnoDB存储引擎undo redo解析
本文介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 为了实现事务原子,在MySQL数据库InnoDB存储引擎,还使用Undo Log(简称:MVCC ...
- 三分钟入门 InnoDB 存储引擎中的表锁和行锁
各位对 "锁" 这个概念应该都不是很陌生吧,Java 语言中就提供了两种锁:内置的 synchronized 锁和 Lock 接口,使用锁的目的就是管理对共享资源的并发访问,保证数 ...
- 在MySQL的InnoDB存储引擎中count(*)函数的优化
写这篇文章之前已经看过了很多数据库方面的优化内容,大部分都是加索引.使用事务.要什么select什么等等.然而,只是停留在阅读的层面上,很少有实践,因为没有遇到真实的项目,一切都是纸上谈兵.实践是检验 ...
- MySQL InnoDB存储引擎
200 ? "200px" : this.width)!important;} --> 介绍 本篇文章是对Innodb存储引擎的概念进行一个整体的概括,innodb存储引擎的 ...
- MySQL InnoDB 存储引擎探秘
在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库中.从MySQL5.5.8开始,InnoDB成为其默认的存储引擎.InnoDB存储引擎支持事务.其设计目标主要是面向OLTP的应用, ...
- MySQL InnoDB存储引擎体系架构 —— 索引高级
转载地址:https://mp.weixin.qq.com/s/HNnzAgUtBoDhhJpsA0fjKQ 世界上只两件东西能震撼人们的心灵:一件是我们心中崇高的道德标准:另一件是我们头顶上灿烂的星 ...
随机推荐
- Mapped Statements collection does not contain value for ResearcherMapper.方法名
搞了半天, 原来是映射文件没加, 新手常遇到的问题. Mapped Statements collection does not contain value for后面是什么类什么方法之类的: 错误原 ...
- Linux必学的60个命令
inux必学的60个命令Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁盘操作.文件存取.目录操作.进程管理.文件权限设定等.所以,在Linux系统上工作离不开使用系统提供的命令.要想 ...
- 高动态范围光照(High Dynamic Range Imaging,简称HDRI或HDR)
1 HDR基本概念 高动态范围光照(High Dynamic Range Imaging,简称HDRI或HDR),是一种表达超过了显示器所能表现的亮度范围的图像映射技术,已成为目前游戏应用不可或缺的 ...
- springMVC+MyBatis+Spring 整合(4) ---解决Spring MVC 对AOP不起作用的问题
解决Spring MVC 对AOP不起作用的问题 分类: SpringMVC3x+Spring3x+MyBatis3x myibaits spring J2EE2013-11-21 11:22 640 ...
- 破解之寻找OEP[手动脱壳](1)
OEP:(Original Entry Point),程序的入口点,软件加壳就是隐藏了OEP(或者用了假的OEP), 只要我们找到程序真正的OEP,就可以立刻脱壳. PUSHAD (压栈) 代表程序的 ...
- ural 1108
大数乘法 不会java 比赛的时候各种细节RE WA ........ #include <cstdio> #include <cstring> #include ...
- ural 1069
题意:删除一棵树上的叶子 每删除一片叶子就写下连着该片叶子的节点 让你还原一棵树 记录每个节点连着的叶子数 0表示此时这个节点就是叶子 -1表示这个节点已经删除 删除的只能是0 就是说是叶子 暴 ...
- C++函数中那些不可以被声明为虚函数的函数
转自C++函数中那些不可以被声明为虚函数的函数 常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函 ...
- 【C++基础】 各种“虚”总结(ing...)
虚基类,虚函数,虚析构函数,纯虚函数,虚函数表(待补充) 一.虚基类——在继承方式(public / private)之前加 virtual class B1: virtual public B0{} ...
- 解决 IntelliJ 乱码问题
原文:解决 IntelliJ 乱码问题 汉字符在IntelliJ的控制台输出乱码.编译器在编译的时候,把汉字符编译成非UTF-8而引起乱码.我是在做Jsoup解析的时候出现的错误,其实归根结底确实编译 ...