第六讲:全局锁和表锁

根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行锁三类。

一、全局锁

全局锁就是对整个数据库实例加锁。MySQL提供了一个加全局读锁的方法,命令是
Flush tables with read lock (FTWRL)

全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表都select出来存成文本。

以前有一种做法,是通过FTWRL确保不会有其他线程对数据库做更新,然后对整个库做备份。
注意,在备份过程中整个库完全处于只读状态。但是让整库都只读,听上去就很危险:
1. 如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;
2. 如果你在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟。
看来加全局锁不太好。

最优方案:官方自带的逻辑备份工具是mysqldump。当mysqldump使用参数–single-transaction的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于MVCC的支持,这个过程中数据是可以正常更新的。

有了这个功能,为什么还需要FTWRL呢?一致性读是好,但前提是引擎要支持这个隔离级别。
比如,对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL命令了。

single-transaction方法只适用于所有的表使用事务引擎的库。如果有的表使用了不支持事务的引擎,那么备份就只能通过FTWRL方法。这往往是DBA要求业务开发人员使用InnoDB替代MyISAM的原因之一。

二、表级锁

表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)。

表锁的语法是 lock tables …read/write。与FTWRL类似,可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。一般是在数据库引擎不支持行锁的时候才会被用到的。

另一类表级的锁是MDL(metadata lock)。MDL不需要显式使用,在访问一个表的时候会被自动加上。MDL的作用是,保证读写的正确性。在MySQL 5.5版本中引入了MDL,当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁

事务中的MDL锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。基于上面的分析,我们来讨论一个问题,如何安全地给小表加字段?

比较理想的机制是,在alter table语句里面设定等待时间,如果在这个指定的等待时间里面能够拿到MDL写锁最好,拿不到也不要阻塞后面的业务语句,先放弃。之后开发人员或者DBA再通过重试命令重复这个过程。

第七讲: 行锁

三、行锁

不支持行锁意味着并发控制只能使用表锁,对于这种引擎的表,同一张表上任何时刻只能有一个更新在执行,这就会影响到业务并发度。InnoDB是支持行锁的,这也是MyISAM被InnoDB替代的重要原因之一。 

行锁就是针对数据表中行记录的锁。这很好理解,比如事务A更新了一行,而这时候事务B也要更新同一行,则必须等事务A的操作完成后才能进行更新。

1. 从两阶段锁说起

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

问题:如果这个影院做活动,可以低价预售一年内所有的电影票,而且这个活动只做一天。于是在活动时间开始的时候,你的MySQL就挂了。你登上服务器一看,CPU消耗接近100%,但整个数据库每秒就执行不到100个事务。这是什么原因呢?这里,我就要说到死锁和死锁检测了。

2. 死锁和死锁检测

当出现死锁以后,有两种策略:

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

正常情况下我们还是要采用第二种策略,即:主动死锁检测,而且innodb_deadlock_detect的默认值本身就是on。主动死锁检测在发生死锁的时候,是能够快速发现并进行处理的,但是它也是有额外负担的。

3. 怎么解决由这种热点行更新导致的性能问题呢?

   问题的症结在于,死锁检测要耗费大量的CPU资源。

  • 1. 考虑通过将一行改成逻辑上的多行来减少锁冲突。
  • 2.并发控制要做在数据库服务端。基本思路就是,对于相同行的更新,在进入引擎之前排队。这样在InnoDB内部就不会有大量的死锁检测工作
  • 3. 控制并发度。

4. 怎么删除表的前10000行。

  • 最优方式: 在一个连接中循环执行20次 delete fromTlimit 500。
  • 直接执行delete fromTlimit 10000,单个语句占用时间长,锁的时间也比较长;而且大事务还会导致主从延迟。
  • 在20个连接中同时执行delete fromTlimit 500,会人为造成锁冲突

第八讲:事务到底是隔离的还是不隔离的?

可重复读隔离级别下执行的事务,事务看到的仍然跟在启动时看到的一样。

5. 事务的启动时机:

begin/start transaction 命令不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句,事务才真正启动。如果你想要马上启动一个事务可以使用start transaction withconsistent snapshot 这个命令。

6. 在MySQL里,有两个“视图”的概念:

  • 一个是view。它是一个用查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。
  • 创建视图的语法是create view…,而它的查询方法与表一样。
  • 一个是InnoDB在实现MVCC时用到的一致性读视图,即consistent read view,用于支持RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别的实现

nnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。它是在事务开始的时候向
InnoDB的事务系统申请的,是按申请顺序严格递增的。

每次事务更新数据的时候,都会生成一个新的数据版本,并且把transaction id赋值给这个数据版本的事务ID,记为rowtrx_id。

InnoDB的行数据有多个版本每个数据版本有自己的rowtrx_id每个事务或者语句有自己的一
致性视图
。普通查询语句是一致性读,一致性读会根据rowtrx_id可见性。

  • 对于可重复读,查询只承认在事务启动前就已经提交完成的数据;
  • 对于读提交,查询只承认在语句启动前就已经提交完成的数据;

InnoDB为每个事务构造了一个数组,用来保存这个事务启动瞬间 "启动了但还没提交" 的所有事务ID。

7. 对于当前事务的启动瞬间来说,一个数据版本的rowtrx_id,有以下几种可能:

  1. 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是可见的;
  2. 如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的;
  3. 如果落在黄色部分,那就包括两种情况:

a. 若 rowtrx_id启动瞬间捕获的数组中,表示这个版本是由还没提交的事务生成的,不可见

b. 若 rowtrx_id不在启动瞬间捕获的数组数组中,表示这个版本是已经提交了的事务生成的,可见。

8. InnoDB利用了“所有数据都有多个版本”的这个特性,实现了“秒级创建快照”的能力。

一个数据版本,对于一个事务视图来说,除了自己的更新总是可见以外,有三种情况:
1. 版本未提交,不可见;
2. 版本已提交,但是是在视图创建后提交的,不可见;
3. 版本已提交,而且是在视图创建前提交的,可见。

更新数据都是先读后写的,而这个读,只能读当前的值,称为“当前读”(current read)。
当前读,总是读取已经提交完成的最新版本。为什么表结构不支持“可重复读”?这是因为表结构没有对应的行数据,也没有rowtrx_id,因此只能遵循当前读的逻辑。

除了update语句外,select语句如果加锁,也是当前读。

9. 事务的可重复读的能力是怎么实现的?

可重复读的核心就是一致性读(consistent read);而事务更新数据的时候,只能用当前读。如
当前的记录的行锁被其他事务占用的话,就需要进入锁等待

10. 读提交的逻辑和可重复读的逻辑类似,它们最主要的区别是:

  • 在可重复读隔离级别下,只需要在事务开始的时候创建一致性视图,之后事务里的其他查询都共用这个一致性视图;
  • 在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图
  • “start transaction with consistent snapshot; ”的意思是从这个语句开始,创建一个持续整个事务的一致性快照
  • 读提交隔离级别下,​​​​​​​事务A的查询语句的视图数组是在执行这个语句的时候创建的。所以,在读提交隔离级别下,这个用法就没意义了,等效于普通的start transaction。

​​​​​​​

MySQL实战45讲笔记(三)相关推荐

  1. MySQL 实战45讲--笔记

    文章目录 MySQL 实战45讲-->笔记 开篇词 基础篇(8讲) 01 | 基础架构:一条SQL查询语句是如何执行的? 1.1 SQL 语句在 MySQL 的各个功能模块中的执行过程. 依次看 ...

  2. MySQL实战45讲学习笔记

    文章目录 MySQL实战45讲-学习笔记 01 基础架构:一条SQL查询语句是如何执行的? mysql逻辑架构 连接器 查询缓存 分析器 优化器 执行器 02 日志系统:一条SQL更新语句如何执行 r ...

  3. 《MySQL实战45讲》——学习笔记04-05 “深入浅出索引、最左前缀原则、索引下推优化“

    04 | 深入浅出索引(上) 1. 什么是索引? 索引的出现其实就是为了提高数据查询的效率,就像书的目录一样,书有500页,每页存的都是书的内容,目录可能只有5页,只存了页码:通过目录能快速找到某个主 ...

  4. 《MySQL实战45讲》——学习笔记12 “InnoDB刷脏页的控制策略“

    本篇介绍MYSQL InnoDB的WAL机制带来的小问题--利用WAL技术,数据库将随机写转换成了顺序写,大大提升了数据库的性能,但也带来了内存脏页的问题: 脏页会被后台线程自动flush,也会由于数 ...

  5. 《Mysql实战45讲》学习笔记 1-22

    Mysql <Mysql实战45讲> 1.一条sql查询语句是如何执行的 Server层: 连接器,查询缓存,分析器,优化器,执行器 存储引擎层: 负责数据的存储和提取 (Innodb, ...

  6. 丁奇的MySQL实战45讲 学习笔记[链接]

    收录一下, 方便自己查阅 <MySQL实战45讲>1~15讲 -丁奇,学习笔记 <MySQL实战45讲>16~30讲 -丁奇,学习笔记 <MySQL实战45讲>31 ...

  7. mysql 实战 45讲 学习笔记 基础知识 原理剖析

    MySQL 实战45讲 持续更新中~ 00讲 开篇 我们知道如何写出逻辑正确的SQL语句来实现业务目标,却不确定这个语句是不是最优的 我们听说了一些使用数据库的最佳实践,但是更想了解为什么这么做 我们 ...

  8. 《MySQL实战45讲》——学习笔记01-03 “MySQL基本架构、日志系统、事务隔离“

    最近有新闻说"丁奇"炒股失败欠债,赶紧去极客时间买了他的<MySQL 实战 45 讲>以防下架,顺带重新系统的复习下MYSQL相关知识,记录下学习笔记: 本篇介绍: M ...

  9. MySQL实战45讲学习笔记----查询结果返回过程分析

    全表扫描时,客户端查询服务端数据库中大量数据,查询结果是如何返回给客户端的. 全表扫描对server层的影响 mysql -h$host -P$port -u$user -p$pwd -e " ...

最新文章

  1. 力扣(LeetCode)刷题,简单题(第7期)
  2. LeetCode 23. Merge k Sorted Lists--Python解法--优先队列,分治法
  3. QT的QAxBase类的使用
  4. 用C#写的一个注册表操作类
  5. android 反色 java_Android小米,魅族6.0状态栏不能反色解决方法
  6. “CSDN 2021年度IT技术影响力之星评选”正式开启报名!
  7. 发展之道:简单与专注
  8. 多线程的那点儿事(之优先级反转)
  9. ajax的嵌套需要注意的问题
  10. 未能加载文件或程序集“Newtonsoft.Json”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)
  11. Keil5手动添加Device
  12. crc循环冗余校验码c语言,crc循环冗余校验码算法
  13. spring cloud学习-什么是Spring Cloud Eureka?
  14. 算法刷题记录(Day 73)
  15. c语言基础题(笔记一)
  16. LINUX漏洞复现篇之ShellShock漏洞
  17. 关于猜数字游戏以及关机指令
  18. 【批量行驶证识别】如何批量行驶证OCR识别行驶本行车本图片或复印件并导出至excel表格或文本格式,下面教你方法
  19. 佳能c3020维修模式 白电平调整_传真机维修清零 白电平大全
  20. 收藏:WBS任务分解法

热门文章

  1. win10挂载linux iscsi存储,我的NAS使用经验 篇六:挂载iSCSI服务为物理磁盘给电脑扩容,支持Windows和MAC...
  2. C++ 用逗号分割字符串
  3. 云台设备指令通讯-串口通讯、UDP、TCP通讯应用
  4. 大一python基础编程题倒等腰梯形_高校邦【慧学杯】Python程序设计基础【实境编程】(2020秋)免费答案...
  5. 分层双向链表+ 哈希表 实现LFU
  6. Python源码剖析[19] —— 执行引擎之一般表达式(2)
  7. 制作一个简单的canvas动画
  8. 诸葛亮出山之真相全版
  9. 实现macOS热门功能,我只用了60行代码
  10. Android excel表打印