笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》

7) --行锁功能:怎么减少行锁对性能的影响?

  MySQL的行锁是在引擎层由各个引擎自己实现的。因此,并不是所有的引擎都支持行锁,如MyISAM引擎就不支持行锁。对于不支持行锁的引擎,只能使用表锁来进行并发控制。对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的,这也是MyISAM被它替代的一个重要原因。

  顾名思义,行锁就是针对数据表中行记录的锁。比如事务A要更新某一行,同时事务B也要更新这一行,则B必须等待A的操作完成后才能进行更新。

两阶段锁协议:

  在InnoDB事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。因此,如果你的事务中需要锁多个行,要把最可能造成锁冲突,最可能影响并发度的锁尽量往后放。

  举一个具体的例子:

  客户A要在电影院B购买电影票,这可能涉及三个操作:

  1. 在A的账户余额中扣除电影票的票价
  2. 在影院B的余额中增加这张电影票的票价
  3. 记录一条交易记录。

  当然为了保证交易的原子性,我们要把这三个操作放在同一个事务中。那么你应该怎样安排上面的语句呢?(两条Update,一条Insert)。根据两阶段锁协议,不管你怎样安排顺序,所有的锁都是在需要时加上,事务提交时释放。因此,如果你把更新影院B余额的操作放在最后,那么影院余额这一行的锁的时间就最少,最大程度地减少了事务直接的锁等待,提升了并发度。

死锁和死锁检测:

  当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致几个线程都在进入无限等待的状态,称为死锁。当出现死锁后我们有两种策略:

  • 直接进入等待,直到超时,这个超时时间可以通过参数innodb_lock_wait_timeout来设置。
  • 另一种策略是,发起死锁监测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect设置为on,表示开启这个逻辑。

  第一种策略的默认值是50s,显然在生产环境这个值是无法接受的。但如果你把这个值设置的很小,如1s,当出现死锁时确实可以很快解开,但也会出现很多误伤。因此我们常采用第二种策略:主动死锁检测。并且,innodb_deadlock_detect的默认值本身就是on。主动死锁检测在发生死锁的时候能够快速发现并进行处理,但是它也有额外负担。例如有1000个线程并发更新同一行,那么死锁检测会这样工作,这1000个线程每个的事务被锁的时候都要去看一下它所依赖的线程有没有被别人锁住,如此循环来判断是否出现了循环等待。那么此时死锁检测的就会消耗大量CPU资源,你就会看到CPU利用率很高,但是每秒执行不了几个事务。

  那么怎么解决这种热点行更新导致的性能问题呢?问题的根源在于,死锁检测要耗费大量的CPU资源。一种治标的方式是,如果你能确保事务一定不会出现死锁,可以临时把死锁检测关掉。当然这个操作伴随着一定的风险,另一个思路是控制并发度。根据上面的分析,你会发现如果并发能够控制住,比如同一行在同一时间最多只有10个线程在更新,那么死锁检测的成本就是可以接受的。当然你也可以从设计上来优化这里的逻辑。

上篇问题:

  备份一般都会在备库上执行,你在用-single-transaction方法做逻辑备份的过程中,如果主库上的一个小表做了一个DDL,比如给一个表上加了一列。这时候,从备库上会看到什么现象呢?

  (DML: Data manipulation language,数据操纵语言,增删改查等;DDL:Data definition language,数据库定义语言,修改表结构等;DCL:Data control language数据库控制语言,修改用户权限等)

  假设这个DDL是针对表t1的,这里把备份过程中几个关键的语句列出来:

Q1:SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Q2:START TRANSACTION WITH CONSISTENT SNAPSHOT;
/* other tables */
Q3:SAVEPOINT sp;
/* 时刻 1 */
Q4:show create table `t1`;
/* 时刻 2 */
Q5:SELECT * FROM `t1`;
/* 时刻 3 */
Q6:ROLLBACK TO SAVEPOINT sp;
/* 时刻 4 */
/* other tables */

  在备份开始的时候,为了确保可重复读隔离级别,再设置一次隔离级别(Q1时刻)。启动事务,使用with consistent snapshot确保这个语句执行完成后就可以得到一个一致性视图。(Q2时刻)设置一个保存点.(Q3时刻)。拿到t1的表结构(Q4时刻)。正式导数据(Q5时刻)。回滚到SAVEPOINT sp,在这里的作用是释放t1的MDL锁。

我们题目设定中t1是小表,假定DDL到达后如果开始执行则很快就能执行完成。

参考答案如下:

  1. 如果在Q4语句执行之前主库的DDL到达,现象:没有影响,备份拿到的是DDL后的表结构。
  2. 如果在‘时刻2’到达,则表结构被改过,Q5执行的时候,报Table defination has changed,please retry transaction,现象mysqldump终止。
  3. 如果在“时刻2”和“时刻3”之间到达,mysqldump占着t1的MDL读锁,binlog被阻塞,现象:主从延迟,直到Q6执行完成。
  4. 从“时刻4”开始,mysqldump释放了MDL读锁,现象:没有影响,备份拿到的是DDL之前的表结构。

问题:

  如果你要删除一个表里面的10000行数据,有以下三种方式:

  1. 直接执行 delete from T limit 10000;
  2. 在一个连接中循环执行20次delete from T limit 500;
  3. 在20个连接中同时执行delete from T limilt 500;

  你会选择哪种方式,为什么呢?

  

MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?的更多相关文章

  1. 最全mysql笔记整理

    mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...

  2. MySQL 笔记整理(6) --全局锁和表锁:给表加个字段怎么有这么多阻碍

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 6) --全局锁和表锁:给表加个字段怎么有这么多阻碍 数据库锁设计的初衷是处理并发问题.作为多用户共享的资源,当出现并发访问的时候, ...

  3. MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行

    最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...

  4. MySQL 笔记整理(20) --幻读是什么,幻读有什么问题?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 20) --幻读是什么,幻读有什么问题? 我们先来看看表结构和初始化数据 ...

  5. MySQL 笔记整理(9) --普通索引和唯一索引,应该怎么选择?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 9) --普通索引和唯一索引,应该怎么选择? 假如你在维护一个市民系统, ...

  6. MySQL 笔记整理(16) --“order by”是怎么工作的?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 16) --“order by”是怎么工作的? 在林老师的课程中,第15 ...

  7. MySQL 笔记整理(19) --为什么我只查一行的语句,也执行这么慢?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 19) --为什么我只查一行的语句,也执行这么慢? 需要说明一下,如果M ...

  8. MySQL 笔记整理(18) --为什么这些SQL语句逻辑相同,性能却差异巨大?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 18) --为什么这些SQL语句逻辑相同,性能却差异巨大? 本篇我们以三 ...

  9. MySQL 笔记整理(13) --为什么数据表删掉一半,表文件大小不变?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 13) --为什么数据表删掉一半,表文件大小不变? 我们还是以MySQL ...

随机推荐

  1. jieba库与好玩的词云的学习与应用实现

    经过了一些学习与一些十分有意义的锻(zhe)炼(mo),我决定尝试一手新接触的python第三方库 ——jieba库! 这是一个极其优秀且强大的第三方库,可以对一个文本文件的所有内容进行识别,分词,甚 ...

  2. unittest中的测试固件

    运行下面的两段代码,看看有什么不同? 第一段: import unittest from selenium import webdriver class F2(unittest.TestCase): ...

  3. Caused by: java.lang.ClassCastException: org.springframework.web.SpringServletContainerInitializer cannot be cast to javax.servlet.ServletContainerInitializer

    A child container failed during startjava.util.concurrent.ExecutionException: org.apache.catalina.Li ...

  4. 约瑟夫环问题 --链表 C语言

    总共有m个人在圆桌上,依次报名,数到第n个数的人退出圆桌,下一个由退出人下一个开始继续报名,循环直到最后一个停止将编号输出 #include <stdio.h>#include <s ...

  5. C#嵌套类

    { "children" : [{ "children" : [{ "children" : [], "name" : ...

  6. angular-ui-bootstrap typeahead 智能提示 自动补全 获取焦点不触发问题的解决

    项目中有一处使用了angular-ui-bootstrap中的typeahead来实现输入框智能提示语自动化补全的功能,存在一个bug, 即输入文字后,当再次点击文本框,其获取焦点后并不会触发智能提示 ...

  7. Java软件工程师面试常见问题集锦之一

    1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象 ...

  8. 阿里云对象存储 OSS 应用服务器搭建代码

    背景说明 最近做一个APP客户端图片直传阿里云OSS的服务,需要在后台开一个阿里云的OSSToken获取的接口. 阿里云官方文档地址:快速搭建移动应用直传服务. 略过移动端说明,直接看服务端的. 不是 ...

  9. JAVA设计模式—观察者模式和Reactor反应堆模式

    被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一 ...

  10. [Swift]LeetCode391. 完美矩形 | Perfect Rectangle

    Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover o ...