MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?
笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》
7) --行锁功能:怎么减少行锁对性能的影响?
MySQL的行锁是在引擎层由各个引擎自己实现的。因此,并不是所有的引擎都支持行锁,如MyISAM引擎就不支持行锁。对于不支持行锁的引擎,只能使用表锁来进行并发控制。对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的,这也是MyISAM被它替代的一个重要原因。
顾名思义,行锁就是针对数据表中行记录的锁。比如事务A要更新某一行,同时事务B也要更新这一行,则B必须等待A的操作完成后才能进行更新。
两阶段锁协议:
在InnoDB事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。因此,如果你的事务中需要锁多个行,要把最可能造成锁冲突,最可能影响并发度的锁尽量往后放。
举一个具体的例子:
客户A要在电影院B购买电影票,这可能涉及三个操作:
- 在A的账户余额中扣除电影票的票价
- 在影院B的余额中增加这张电影票的票价
- 记录一条交易记录。
当然为了保证交易的原子性,我们要把这三个操作放在同一个事务中。那么你应该怎样安排上面的语句呢?(两条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到达后如果开始执行则很快就能执行完成。
参考答案如下:
- 如果在Q4语句执行之前主库的DDL到达,现象:没有影响,备份拿到的是DDL后的表结构。
- 如果在‘时刻2’到达,则表结构被改过,Q5执行的时候,报Table defination has changed,please retry transaction,现象mysqldump终止。
- 如果在“时刻2”和“时刻3”之间到达,mysqldump占着t1的MDL读锁,binlog被阻塞,现象:主从延迟,直到Q6执行完成。
- 从“时刻4”开始,mysqldump释放了MDL读锁,现象:没有影响,备份拿到的是DDL之前的表结构。
问题:
如果你要删除一个表里面的10000行数据,有以下三种方式:
- 直接执行 delete from T limit 10000;
- 在一个连接中循环执行20次delete from T limit 500;
- 在20个连接中同时执行delete from T limilt 500;
你会选择哪种方式,为什么呢?
MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?的更多相关文章
- 最全mysql笔记整理
mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...
- MySQL 笔记整理(6) --全局锁和表锁:给表加个字段怎么有这么多阻碍
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 6) --全局锁和表锁:给表加个字段怎么有这么多阻碍 数据库锁设计的初衷是处理并发问题.作为多用户共享的资源,当出现并发访问的时候, ...
- MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...
- MySQL 笔记整理(20) --幻读是什么,幻读有什么问题?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 20) --幻读是什么,幻读有什么问题? 我们先来看看表结构和初始化数据 ...
- MySQL 笔记整理(9) --普通索引和唯一索引,应该怎么选择?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 9) --普通索引和唯一索引,应该怎么选择? 假如你在维护一个市民系统, ...
- MySQL 笔记整理(16) --“order by”是怎么工作的?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 16) --“order by”是怎么工作的? 在林老师的课程中,第15 ...
- MySQL 笔记整理(19) --为什么我只查一行的语句,也执行这么慢?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 19) --为什么我只查一行的语句,也执行这么慢? 需要说明一下,如果M ...
- MySQL 笔记整理(18) --为什么这些SQL语句逻辑相同,性能却差异巨大?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 18) --为什么这些SQL语句逻辑相同,性能却差异巨大? 本篇我们以三 ...
- MySQL 笔记整理(13) --为什么数据表删掉一半,表文件大小不变?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 13) --为什么数据表删掉一半,表文件大小不变? 我们还是以MySQL ...
随机推荐
- 我用linux系统的采坑记
我的新Ubuntu18,也没安装什么,但是在使用过程中总是莫名其妙的卡死,真的很烦.有时候cpu使用率接近100%,有时候貌似是内存不够了,但是我明明是8GB,这些小问题搞得我很恼火.这样的机器真的不 ...
- Centos7 编译安装 Nginx Mariadb Asp.net Core2 (实测 笔记 Centos 7.3 + Openssl 1.1.0h + Mariadb 10.3.7 + Nginx 1.14.0 + Asp.net. Core 2 )
环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G,双网卡) 系统版本:CentOS-7-x86_64-Minimal-1611.iso 安装步骤: 1.准备 1.0 查看硬 ...
- Java解析json字符串和json数组
Java解析json字符串和json数组 public static Map<String, String> getUploadTransactions(String json){ Map ...
- Servlet 监听器Listner
定义: 专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动. Servlet 规范为每种事件监听器都定义了相应的接口,它用于监听 ...
- scala 下 sigmoid 与breeze.numeric.sigmoid差异对比
scala> val beforeInit = System.nanoTime;val handsgn = rd.map(x => 1.0 / (1.0 + Math.exp(-x))); ...
- HTML图片标签路径解析
img标签中src属性表示的是引用的图片路径,有两种路径类型: 1. 绝对路径 2. 相对路径. 绝对路径:使用图片在硬盘上的绝对位置来访问图片,通常是从根目录开始,向下一个目录一个目录的寻找. ...
- For each...in / For...in / For...of 的解释与例子
1.For each...in for each...in 语句在对象属性的所有值上迭代指定的变量.对于每个不同的属性,执行一个指定的语句. 语法: for each (variable in obj ...
- C语言面试题分类->字符串处理
1.strlen:计算字符串长度(不包含'\0') 实现想法:遍历字符串,直到'\0'结束 #include<stdio.h> #include<stdlib.h> #incl ...
- Ubuntu部署python3.7的开发和运行环境
Ubuntu部署python3.7的开发和运行环境 1 概述 由于最近项目全部由python2.x转向 python3.x(使用 python3.7.1) ,之前的云主机的的默认python版本都面临 ...
- [Swift]LeetCode143. 重排链表 | Reorder List
Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You may not mod ...