semi-consistent简介

http://hedengcheng.com/?p=220

semi-consistent简介    1

semi-consistent实现    2

MySQL Server层    2

InnoDB Engine层    2

是否采用semi-consistent read    2

Fetch Next特殊处理逻辑    3

优化:Unlock unmatched row    4

semi-consistent优缺点分析    4

优点    4

缺点    5

测试用例    5

构造semi-consistent read    5

构造unlock unmatched row    5

semi-consistent简介

对于熟悉MySQL,或者是看过InnoDB源码的朋友们来说,可能会听说过一个新鲜的名词:semi-consistent read 。 何谓semi-consistent read?以下一段文字,摘于semi-consistent read一文:

A type of read operation used for UPDATE statements, that is a combination of read committed and consistent read. When an UPDATE statement examines a row that is already locked, InnoDB returns the latest committed version to MySQL so that MySQL can determine whether the row matches the WHERE condition of the UPDATE. If the row matches (must be updated), MySQL reads the row again, and this time InnoDB either locks it or waits for a lock on it. This type of read operation can only happen when the transaction has the read committed isolation level, or when the innodb_locks_unsafe_for_binlog option is enabled.

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

semi-consistent read只会发生在read committed隔离级别下,或者是参数innodb_locks_unsafe_for_binlog被设置为true。

MySQL server与InnoDB引擎是如何进行交互?InnoDB引擎如何实现semi-consistent read?请见下面的详细分析。

semi-consistent实现

MySQL Server层

从上面的描述中可以看出,semi-consistent read仅仅针对于update操作,因此在sql_update.cc的mysql_update方法中,有如下调用:

sql_update.cc::mysql_update()

// 通知底层引擎,尝试进行semi consistent read

// 是否真正进行semi consistent read,由底层引擎决定

table->file->try_semi_consistent_read(1);

// InnoDB引擎决定当前update是否可以进行semi-consistent read

// 具体的处理方法,在下节中分析

ha_innodb.cc::try_semi_consistent_read(bool yes);

// 进行update的读与更新操作

// update操作完成之后,关闭semi-consistent read

table->file->try_semi_consistent_read(0);

MySQL Server层处理semi-consistent较为简单,接下来看看InnoDB Engine的处理方式。

InnoDB Engine层

InnoDB Engine层面,对于semi-consistent read的处理,包括两方面的逻辑:

  • 判断当前语句是否可以支持semi-consistent read
  • fetch next时,对于semi-consistent read的特殊处理

是否采用semi-consistent read

前面提到,MySQL Server在update时,会调用引擎的try_semi_consistent_read方法,来尝试进行semi-consistent read,而是否进行semi-consistent read,则交由底层处理。

ha_innodb.cc::try_semi_consistent_read()

if (yes &&

(srv_locks_unsafe_for_binlog

|| prebuilt->trx->isolation_level <= TRX_ISO_READ_COMMITTED))

prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;

简单分析下,当用户设置系统参数innodb_locks_unsafe_for_binlog为true,或者是采用的事务隔离级别为read committed(或以下)时,设置prebuilt->row_read_type参数,标识当前update语句使用semi-consistent read,fetch next时需要有针对性的做特殊处理。

Fetch Next特殊处理逻辑

InnoDB fetch next的主函数入口是row_search_for_mysql,此函数如何针对性的处理semi-consistent read呢?

row0sel.c::row_search_for_mysql()

// 尝试对于定位到的记录加锁

err = sel_set_rec_lock();

case DB_LOCK_WAIT:

// 如果加锁需要等待,则判断是否可以进行semi-consistent read

// 判断条件为:

// 1. prebuilt->row_read_type必须设置为ROW_READ_TRY_SEMI_CONSISTEN

// 2. 当前scan必须是range scan或者是全表扫描,而非unique scan

// 3. 当前索引必须是聚簇索引

// 4. 不满足以上三个条件,就不能进行semi-consistent read,进行加锁等待

// 注意:若不需要加锁等待,那么也不需要进行semi-consistent read,直接

// 读取记录的最新版本即可,没有加锁等待的开销。

if ((prebuilt->row_read_type != ROW_READ_TRY_SEMI_CONSISTENT)

|| unique_search

|| index != clust_index)

goto lock_wait_or_error;

// 可以进行semi-consistent read,根据记录的当前版本,构造最新的commit版本

// 若没有commit版本,当前版本为最新版本,则直接读取下一条记录

// 若存在commit版本,则设置did_semi_consistent_read为TRUE

row_sel_build_committed_vers_for_mysql();

if (old_vers == NULL)

goto next_rec;

did_semi_consistent_read = TRUE;

// 若本次update scan,由于加锁等待,使用了semi-consistent,则设置相应的参数

// 该参数,在下一小节提到的MySQL针对semi-consistent优化中有用

if (did_semi_consistent_read)

prebuilt->row_read_type = ROW_READ_DID_SEMI_CONSISTENT;

else

prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;

// 至此,InnoDB的fetch next针对semi-consistent read的处理完毕

优化:Unlock unmatched row

上面提到的是semi-consistent read的功能实现,除此之外,MySQL针对semi-consistent read,还做了优化措施:对于update scan返回的不满足条件的记录,提前放锁。

MySQL Server层流程

sql_update.cc::mysql_update()

// 判断当前scan返回的记录,是否满足update的where条件

// 若满足,则进行update操作

if (!(select && select->skip_record())

// 若不满足update的where条件,则选择将当前记录上的行锁提前释放

else

table->file->unlock_row();

InnoDB Engine层流程

ha_innobd.cc::unlock_row();

switch (prebuilt->row_read_type)

// 若系统未设置参数innodb_locks_unsafe_for_binlog,同时隔离级别大于

// TRX_ISO_READ_COMMITTED,则不可提前释放不满足条件的行锁

// 否则可以提前释放不满足条件的行锁

case ROW_READ_WITH_LOCKS:

if (!srv_locks_unsafe_for_binlog &&

prebuilt->trx->isolation_level > TRX_ISO_READ_COMMITTED)

break;

// 若当前系统已采用SEMI_CONSISTENT read,但是没有锁等待,加锁直接成功

// 那么此时直接释放不满足条件的行锁

case ROW_READ_TRY_SEMI_CONSISTENT:

row_unlock_for_mysql();

// 若当前系统已采用SEMI_CONSISTENT read,并且有锁等待,构造了commit版本

// 没有在commit版本上加锁,因此也无锁可放,直接返回即可

case ROW_READ_DID_SEMI_CONSISTENT:

prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;

break;

semi-consistent优缺点分析

优点

  • 减少了更新同一行记录时的冲突,减少锁等待。

    无并发冲突,读记录最新版本并加锁;有并发冲突,读事务最新的commit版本,不加锁,无需锁等待。

  • 可以提前放锁,进一步减少并发冲突概率。

    对于不满足update更新条件的记录,可以提前放锁,减少并发冲突的概率。

  • 在理解了semi-consistent read原理及实现方案的基础上,可以酌情考虑使用semi-consistent read,提高系统的并发性能。

缺点

  • 非冲突串行化策略,因此对于binlog来说,是不安全的

    两条语句,根据执行顺序与提交顺序的不同,通过binlog复制到备库后的结果也会不同。不是完全的冲突串行化结果。

    因此只能在事务的隔离级别为read committed(或以下),或者设置了innodb_locks_unsafe_for_binlog参数的情况下才能够使用。

测试用例

构造semi-consistent read

set binlog_format=mixed;

set session transaction isolation level repeatable read;

create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;

insert into t1 values (1),(2),(3),(4),(5),(6),(7);

session 1:                                                session 2:

set autocommit=0;

update t1 set a = a + 10;

set binlog_format=mixed;

set session transaction isolation level read committed;

update t1 set a = a + 100 where a > 10;

此时,session 2不需要等待session 1,虽然session 1的更新后项满足session 2的条件,但是由于session 2进行了semi-consistent read,读取到的记录的前项为(1-7),不满足session 2的更新where条件,因此session 2直接返回。

session 2直接返回,0 rows affected。

构造unlock unmatched row

set binlog_format=mixed;

set session transaction isolation level repeatable read;

create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;

insert into t1 values (1),(2),(3),(4),(5),(6),(7);

session 1:                                                session 2:

set autocommit=0;

update t1 set a = a + 10;

commit;

set binlog_format=mixed;

set session transaction isolation level repeatable read;

set autocommit = 0;

update t1 set a = a + 100 where a < 10;

select * from t1 lock in share mode;

session 1在session 2开始前已经提交,session 2可以进行semi-consistent read。并且读到的都是session 1的更新后项,完成加锁。但是由于更新后项均不满足session 2的where条件,session 2会释放所有行上的锁(由MySQL Server层判断并调用unlock_row方法释放行锁)。

此时,session 1再次执行select * from t1 lock in share mode语句,直接成功。因为session 2已经将所有的行锁提前释放。

朋友们可以试试将session 2的隔离级别改为repeatable read,那么此时session 1就会等待session 2提交。

转载于:https://www.cnblogs.com/MYSQLZOUQI/p/3863558.html

semi-consistent简介相关推荐

  1. python视频人脸检测_OpenCV + python 实现人脸检测(基于照片和视频进行检测)

    OpenCV + python 实现人脸检测(基于照片和视频进行检测) Haar-like 通俗的来讲,就是作为人脸特征即可. Haar特征值反映了图像的灰度变化情况.例如:脸部的一些特征能由矩形特征 ...

  2. python和scre_python中变量命名的基本规则,标识符和关键字

    [iCore3 双核心板_FPGA]实验二十八:基于SDRAM 的VGA 驱动器的设计 本实验设计的VGA显示驱动完全基于FPGA实现,用SDRAM做缓存设备,通过ARM控制VGA显示的内容.ARM ...

  3. html中点击文字变色,html选中文字 背景/字 变色

    iconfont使用,亲测 iconfont对于前端应用来说有很多便捷: 1.自由变化大小 2.自由修改颜色 3.可以添加一些视觉效果如:阴影.旋转.透明度. 4.兼容IE6 在线引用和下载到本地两种 ...

  4. RR RC 隔离级别

    1. Export with CONSISTENT = Y sets the transaction to read-only. read committed和serializable的区别和联系: ...

  5. MySQL之CAID-隔离级别讲解

    1. 数据库事务ACID特性 数据库事务的4个特性: 原子性(Atomic): 事务中的多个操作,不可分割,要么都成功,要么都失败: All or Nothing. 一致性(Consistency): ...

  6. 行业分析-全球与中国医疗CMOS图像传感器市场现状及未来发展趋势

    根据QYR(恒州博智)的统计及预测,2021年全球医疗CMOS图像传感器市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(2022-2028).地区层面来看,中国 ...

  7. 安防CMOS图像传感器市场现状及未来发展趋势

    根据QYR(恒州博智)的统计及预测,2021年全球安防CMOS图像传感器市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(2022-2028).地区层面来看,中国 ...

  8. html table边框细线,HTML小技巧将table边框改为细线

    HTML制作新手在用TABLE表格时,会碰到如何改变边线粗线,因为默认的TABLE边线设置即使是1px 是很粗的.因此会使用其他一些方法来制作出细线边框,这里介绍一种利用CSS来实现细线的方法,很有效 ...

  9. sparkcore分区_Spark学习:Spark源码和调优简介 Spark Core (二)

    本文基于 Spark 2.4.4 版本的源码,试图分析其 Core 模块的部分实现原理,其中如有错误,请指正.为了简化论述,将部分细节放到了源码中作为注释,因此正文中是主要内容. 第一部分内容见: S ...

最新文章

  1. Python常用函数--文档字符串DocStrings
  2. (转)使用Spring配置文件实现事务管理
  3. 初学Python——RabbitMQ的安装
  4. 黑客攻击发现:多个银行类APP存漏洞
  5. 基于知识图谱的问答系统入门—NLPCC2016KBQA数据集
  6. 人工智能自拍之后,会怎样给自己P图?
  7. 总结之:CentOS 6.5 LAMP分主机平台的搭建及测试
  8. Cesium:鼠标监听事件绑定
  9. 在安全防火墙内通过 WebHook 触发构建
  10. 流媒体网络性能指标——抖动
  11. 一篇网络流的好blog
  12. 电子产品“使用”和“放置”哪个寿命更长??
  13. 一个百万富翁碰到一个陌生人,陌生人找他谈了一个换钱的计划.该计划如下:我每天给你10万,而你第一天给我一分钱,第二天我仍给你十万,你给我二分钱,第三天我仍给你十万,你给我四分钱......你每天给我的
  14. $happy-new(year[2006])
  15. 苹果电脑python快捷键_我常用用的MAC快捷键和手势
  16. ubuntu18 配置静态IP地址(详细版)
  17. 机器人产业化给导电环行业带来的机遇
  18. 【数量称谓】祖宗十八代
  19. windows无法启动windows defender service服务(位于本地计算机上) 错误577
  20. 华硕笔记本台式机专用系统 GHOSTXPSP3 v2012.12

热门文章

  1. 关于Toad的Cannot load OCI DLL问题
  2. 【leetcode】Max Points on a Line(hard)☆
  3. 使用一些宏跟踪调试__LINE__ __FILE__ __DATE__ __TIME__ __STDC__
  4. pattern recognition and machine learning基本思想1:最大似然估计
  5. es html标签,ES 6 Number
  6. linuxpython23同时_Linux-centos同时存在Python2-Python3
  7. (50)Xilinx Multiplier IP核配置(十一)(第10天)
  8. (35)FPGA打两拍、打三拍设计(第7天)
  9. (06)System Verilog 静态变量与动态变量区别
  10. matlab 多速率,多速率信号处理系统设计与实现.PDF