rc mysql common_RR与RC隔离级别下MySQL不同的加锁解锁方式

作者   韩杰·沃趣科技MySQL数据库工程师

出品   沃趣科技

|  RC与RR隔离级别下MySQL不同的加锁解锁方式

MySQL5.7.21

数据准备

root@localhost : pxs 05:26:27> show create table dots\G

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

Table: dots

Create Table: CREATE TABLE `dots` (

`id` int(11) NOT NULL,

`color` varchar(20) COLLATE utf8_bin NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

1 row in set (0.00 sec)

root@localhost : pxs 05:27:34> select * from dots;

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

| id | color |

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

|  1 | black |

|  2 | white |

|  3 | black |

|  4 | white |

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

4 rows in set (0.00 sec)

root@localhost : pxs 01:57:02> show variables like 'innodb_locks_unsafe_for_binlog';

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

| Variable_name                  | Value |

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

| innodb_locks_unsafe_for_binlog | OFF  |

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

1 row in set (0.00 sec)

1.RC隔离级别

确认隔离级别

root@localhost : pxs 05:27:35> show variables like '%iso%';

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

| Variable_name        | Value          |

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

| transaction_isolation | READ-COMMITTED |

| tx_isolation          | READ-COMMITTED |

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

2 rows in set (0.01 sec)

同时开启两个会话,按下图的流程开始操作。

2ff2d79104b42591788ec0f75fcc5b8b.png

2.RR隔离级别

确认隔离级别

root@localhost : pxs 05:24:41> show variables like '%iso%';

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

| Variable_name        | Value          |

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

| transaction_isolation | REPEATABLE-READ |

| tx_isolation          | REPEATABLE-READ |

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

2 rows in set (0.01 sec)

同时开启两个会话,按下图的流程开始操作。

ff64ecd3ad1c9d6b8cb7dddb1a0fa805.png

3.半一致读semi-consistent read

3.1 半一致读发生条件

RC隔离级别

RR隔离级别,且innodb_locks_unsafe_for_binlog=true

3.2 innodb_locks_unsafe_for_binlog

innodb_locks_unsafe_for_binlog默认为off。

如果设置为1,会禁用gap锁,但对于外键冲突检测(foreign-key constraint checking)或者重复键检测(duplicate-key checking)还是会用到gap锁。

启用innodb_locks_unsafe_for_binlog产生的影响等同于将隔离级别设置为RC,不同之处是:

1)innodb_locks_unsafe_for_binlog是全局参数,影响所有session;但隔离级别可以是全局也可以是会话级别。

2)innodb_locks_unsafe_for_binlog只能在数据库启动的时候设置;但隔离级别可以随时更改。

基于上述原因,RC相比于innodb_locks_unsafe_for_binlog会更好更灵活。

启用innodb_locks_unsafe_for_binlog还有以下作用:

对于update或者delete语句,InnoDB只会持有匹配条件的记录的锁。在MySQL Server过滤where条件,发现不满足后,会把不满足条件的记录释放锁。这可以大幅降低死锁发生的概率。

简单来说,semi-consistent read是read committed与consistent read两者的结合。一个update语句,如果读到一行已经加锁的记录,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。若满足(需要更新),则MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)。

来看下面这个例子:

CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;

INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);

COMMIT;

这个例子中,表上没有索引,所以对于记录锁会用到隐藏主键。

假设某个client开启了一个update:

SET autocommit = 0;

UPDATE t SET b = 5 WHERE b = 3;

假设另一个client紧接着也开启一个update:

SET autocommit = 0;

UPDATE t SET b = 4 WHERE b = 2;

每当InnoDB发起update,会先对每一行记录加上排它锁,然后再决定记录是否满足条件。如果不匹配,则innodb_locks_unsafe_for_binlog开启,InnoDB就会把记录上的锁释放掉。否则,InnoDB会一直持有锁直到事务结束。具体如下:

如果innodb_locks_unsafe_for_binlog没有开启,第一个update会一直持有x锁

x-lock(1,2); retain x-lock

x-lock(2,3); update(2,3) to (2,5); retain x-lock

x-lock(3,2); retain x-lock

x-lock(4,3); update(4,3) to (4,5); retain x-lock

x-lock(5,2); retain x-lock

第二个update会阻塞住直到第一个update提交或者回滚

x-lock(1,2); block and wait for first UPDATE to commit or roll back

如果innodb_locks_unsafe_for_binlog开启,第一个update先持有x锁,然后会释放不匹配的记录上面的x锁

x-lock(1,2); unlock(1,2)

x-lock(2,3); update(2,3) to (2,5); retain x-lock

x-lock(3,2); unlock(3,2)

x-lock(4,3); update(4,3) to (4,5); retain x-lock

x-lock(5,2); unlock(5,2)

对于第二个update,InnoDB会开启半一致读,此时InnoDB返回记录最近提交的版本,由MySQL上层判断此版本是否满足update的where条件。

x-lock(1,2); update(1,2) to (1,4); retain x-lock

x-lock(2,3); unlock(2,3)

x-lock(3,2); update(3,2) to (3,4); retain x-lock

x-lock(4,3); unlock(4,3)

x-lock(5,2); update(5,2) to (5,4); retain x-lock

4.一开始的例子

4.1 RC隔离级别

session 1

session 1执行:

update dots set color = 'black' where color = 'white';

由于color列无索引,因此只能走聚簇索引,进行全部扫描。加锁如下:

fd6b4d62f1e0a7f44e9017b96ff5891f.png

注:如果一个条件无法通过索引快速过滤,那么存储引擎层面就会将所有记录加锁后返回,然后由MySQL Server层进行过滤。因此也就把所有的记录,都锁上了。

但在实际中,MySQL做了优化,如同前面作用1所提到的。在MySQL Server过滤条件,发现不满足后,会调用unlock_row方法,把不满足条件的记录放锁 (违背了2PL的约束)。这样做,保证了最后只会持有满足条件记录上的锁,但是每条记录的加锁操作还是不能省略的。

实际加锁如下:

860d71528edb593e9805754b24e02418.png

session 2

session 2执行:

update dots set color = 'white' where color = 'black';

session 2尝试加锁的时候,发现行上已经存在锁,InnoDB会开启semi-consistent read,返回最新的committed版本(1,black),(2,white),(3,black),(4,white)。MySQL会重新发起一次读操作,此时会读取行的最新版本(并加锁)。如同前面作用2所提到的。

加锁如下:

fd6b4d62f1e0a7f44e9017b96ff5891f.png

MySQL优化后实际加锁如下:

3dd5e3ccda81d39ccdf62433b26f03d8.png

4.2 RR隔离级别

session 1

session 1执行:

update dots set color = 'black' where color = 'white';

由于color列无索引,因此只能走聚簇索引,进行全部扫描。加锁如下:

7552d8953fe751436f18988c76f4a530.png

session 2

session 2执行:

update dots set color = 'white' where color = 'black';

更新被阻塞。 等session 1提交commit之后,session 2update才会成功。

引申:RR隔离级别,且开启innodb_locks_unsafe_for_binlog=ON

环境准备

root@localhost : (none) 04:57:46> show  variables like '%iso%';

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

| Variable_name        | Value          |

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

| transaction_isolation | REPEATABLE-READ |

| tx_isolation          | REPEATABLE-READ |

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

2 rows in set (0.01 sec)

root@localhost : (none) 04:55:25> show variables like 'innodb_locks_unsafe_for_binlog';

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

| Variable_name                  | Value |

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

| innodb_locks_unsafe_for_binlog | ON    |

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

1 row in set (0.00 sec)

root@localhost : pxs 05:00:54> select * from dots;

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

| id | color |

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

|  1 | black |

|  2 | white |

|  3 | black |

|  4 | white |

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

4 rows in set (0.00 sec)

开始操作

注:过程现象满足RR隔离级别,也符合设置innodb_locks_unsafe_for_binlog=ON的情况。因为前面所讲的启用innodb_locks_unsafe_for_binlog会产生作用1与作用2,所以整个加锁与解锁情况与RC隔离级别类似。

参考:

《数据库事务处理的艺术:事务管理与并发控制》https://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_locks_unsafe_for_binloghttp://hedengcheng.com/?p=771http://hedengcheng.com/?p=220

|  作者简介

韩杰  沃趣科技MySQL数据库工程师

熟悉mysql体系架构、主从复制,熟悉问题定位与解决。

相关链接

更多干货,欢迎来撩~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/399248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈web应用的负载均衡、集群、高可用(HA)解决方案

浅谈web应用的负载均衡、集群、高可用(HA)解决方案转载于:https://www.cnblogs.com/hfultrastrong/p/7887420.html

今天开通了博客园帐号

打算开博客很久了,最近一直在纠结于应该在哪里开博客,也选了一些博客网站做了粗略的对比,同时还看了网友们的比较,将要在博客园和CSND之间选择,最后选择了博客园。原因在于博客园更专注,希望在这里能够和大…

hdu 确定比赛名次

算法&#xff1a;拓扑排序 题意&#xff1a;有一个比赛&#xff0c;现在知道很多队之间的关系&#xff1b;让你去让确定比赛排名&#xff1b; Problem Description 有N个比赛队&#xff08;1<N<500&#xff09;&#xff0c;编号依次为1&#xff0c;2&#xff0c;3&#x…

Tomcat中server.xml文件内各节点详解

由于 Tomcat 基于 Java&#xff0c;实际上在各种 Linux 发行版里的配置方法都大同小异&#xff0c;只是我看见在 Arch Linux 环境里搭建 Tomcat 的文章比较少&#xff0c;所以在 Arch Linux 实践一遍然后得出此文。此文假设你对 Tomcat 并不十分了解&#xff0c;主要笔墨将会在…

thinkphp mysql cache_thinkPHP5框架数据库连贯操作之cache()用法分析

本文实例讲述了thinkPHP5框架数据库连贯操作之cache()用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;介绍TP5中自带的缓存系统&#xff0c;是File型缓存。也就是文件型缓存。存储地址是&#xff1a;根目录..untimecache(根目录指public)。这个缓存系统相较于redi…

[Javascript_库编写]创建自己的“JavaScript库”

一.编写JavaScript库要注意的问题 为了让自己的JS库构建的更加优雅、合理&#xff0c;我们编写JS库时要注意两方面的内容&#xff1a; 1.不要使用版本检测&#xff0c;而要使用能力检测 由于浏览器的类型和版本太多&#xff0c;以及不断的新的浏览器出现&#xff0c;我们不可能…

文件的分割与合并

/*文件的分割*/ #include<stdio.h> #include<stdlib.h> #include<string.h> #define NUM 1024 * 1024 * 100 int main() {//所需分割的文件路径FILE *fr fopen("F:\\PL.exe", "rb");if (fr NULL){exit(-1);}char *buff (char*)malloc…

mysql5.6.24怎么打开_mysql 5.6.24 安装配置方法图文教程

由于工作需要&#xff0c;开始使用mysql数据库&#xff0c;已经好久没有使用了。基本已经忘了差不多。今天重新安装配置了一下&#xff0c;写个随笔记录一下&#xff0c;以免自己以后需要的时候翻看&#xff0c;如有不正确或需要补充的&#xff0c;希望大家多多留言。首先下载m…

sublime text 3安装及使用

安装配置 安装&#xff1a; 安装环境:Ubuntu 16.04 官网下载sublime text 3 https://www.sublimetext.com/3 解压&#xff1a; tar xvf 文件名 进入 sublime_text_3文件夹&#xff0c;运行 ./sublime_text 注册码&#xff1a;我用的时候有用 —– BEGIN LICENSE —–TwitterInc…

微信公众号新功能-原创声明、赞赏功能、评论管理、页面模版

原文&#xff1a;http://www.shichangbu.com/portal.php?modview&aid25931 公众号如何申请这些功能&#xff1f; 在微信公众号后台和QQ经常都有人问我诸如此类的问题&#xff1a;”微信公众平台原创声明怎么开通?“、”微信赞赏等功能是怎么回事…

mysql时间聚合_11.MySQL数值、日期和时间、信息、聚合函数

mysql> ALTER TABLE 名单 ADD id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT FIRST;Query OK, 0 rows affected (0.27 sec)Records: 0 Duplicates: 0 Warnings: 0mysql> DESC 名单;-----------------------------------------------------------------| Field | Type…

Html工具类

1 import java.io.IOException;2 import java.io.PrintWriter;3 4 import javax.servlet.http.HttpServletResponse;5 6 import net.sf.json.JSONException;7 8 9 public class HtmlUtil { 10 11 /** 12 * 13 * <br> 14 * <b>功能&#x…

C#基础加强_泛型的基本原理

小弟初写博文&#xff0c;深感“易敲千行码&#xff0c;难下百余文”的道理。 内容粗略浅薄&#xff0c;望各位大神海涵&#xff01; 动态数组ArrayList可以实现不断的增长&#xff0c;让我们感受到了在某些地方较数组有优越感。但它包含的数组类型是object类&#xff0c;意味着…

python语法笔记(四)

1、对象的属性 python一切皆对象&#xff0c;每个对象都可能有多个属性。python的属性有一套统一的管理方案。 属性的__dict__系统 对象的属性可能来自于其类定义&#xff0c;叫做类属性&#xff1b;还可能是该对象实例自身定义的属性&#xff0c;叫做对象属性。类属性…

为什么闹钟设置了却不响_又被iPhone闹钟坑了?解决闹钟不响问题看这里!

原标题&#xff1a;又被iPhone闹钟坑了&#xff1f;解决闹钟不响问题看这里&#xff01;你有没有过这样的体验&#xff0c;早上醒来&#xff0c;闹钟还没响&#xff0c;内心想&#xff1a;真好&#xff0c;还可以再睡会。拿起手机想看看还能再睡多久&#xff0c;结果……我的天…

CSS3实现纸张边角卷起效果

html代码 1 <body>2 <div class"page">3 <div class"page-box">4 <h1>5 兔子先生6 </h1>7 <p>8 这几…

fzu 1894 单调队列

http://acm.fzu.edu.cn/problem.php?pid1894 Problem 1894 志愿者选拔Accept: 1328 Submit: 4200Time Limit: 1500 mSec Memory Limit : 32768 KB Problem Description 世博会马上就要开幕了&#xff0c;福州大学组织了一次志愿者选拔活动。参加志愿者选拔的同学们排队接…

均线带角度的指标_选股指标:均线角度并列向上,量能倍增飞扬趋势明显,短线操作可考虑...

今天要讲的是量能飞扬的选股指标&#xff0c;这个指标是按照20日、30日、60日、120日均线反正切角度原理为基础设计的公式&#xff0c;这4条均线角度排列向上&#xff0c;股价呈现向上的趋势&#xff0c;选出的股票有大概率上涨的空间&#xff0c;完整的公式如下&#xff1a;A2…

将链表中m-n范围内的数进行倒序

Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given 1->2->3->4->5->NULL, m 2 and n 4, return 1->4->3->2->5->NULL. Note:Given m, n satisfy the following condition:1 ≤ m ≤ n ≤ lengt…

python 核心编程第5章(习题)

1.标准类型运算符. 写一段脚本&#xff0c;输入一个测验成绩&#xff0c;根据下面的标准&#xff0c;输出他的评分成绩&#xff08;A-F&#xff09;。 #coding:utf8 a raw_input() a int(a) if (a > 100) or (a < 0):print "输入错误,请输入0&#xff5e;100的数字…