根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行锁三类,本文先讨论前两种。

全局锁

全局锁是对整个数据库实例加锁,MySQL提供的加全局读锁的命令是Flush tables with read lock(下面简称FTWRL)。当需要让整个库处于只读状态时,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据的增删改、数据定义语句(表的建立与修改等)、更新类事务的提交语句。

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

让整个库都处于只读,有些弊端:

  • 若在主库上备份,那么在备份期间都不能执行更新,业务会停滞;

  • 若在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,导致主从延迟。

那么既然备份加锁有这么多弊端,是否可以不加锁呢?

答案是不行的,考虑有用户余额表和订单表两张表,当用户发起一次购买,需要在用户余额表扣减余额,在订单表里增加一笔订单。若顺序是先备份用户余额表,然后用户购买,再备份订单表,不难发现会出现问题,顺序反之亦然。

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

那既然官方有这个工具,为什么需要FTWRL呢?答案是有些引擎并不支持可重复读的隔离级别,这时候必须使用FTWRL命令。因此,只有所有表都使用事务引擎的库才能使用single-transaction

还有一种想法是,为了让全库只读,使用set global readonly=true的方式。但还是建议使用FTWRL,原因如下:

  • 在有些系统中,readonly的值会被用作其他逻辑,比如判断库是主库还是从库。

  • 在异常处理机制上,如果执行FTWRL命令之后由于客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为readonly之后,如果客户端发生异常,则数据库会一直保持该状态,导致整个库长时间处于不可写状态,风险较高。

表级锁

这里介绍两种表级别的锁,一种是表锁,一种是元数据锁。

表锁的语法是lock tables … read/write,可以用unlock tables主动释放锁,也可以在客户端断开时自动释放锁。表锁除了限制其他线程的读写,也限制本线程接下来的操作

在没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式。对于InnoDB这种支持行锁的引擎,一般不使用lock tables来控制并发。

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

  • 读锁不互斥,因此可以有多个线程同时对一张表增删改查。

  • 读写锁、写锁之间互斥,用来保证变更表结构操作的正确性。

要注意的是,事务中的MDL锁,在语句执行开始时申请,但语句结束后并不会马上释放,而会等到整个事务提交后释放。考虑下面这样一个例子:

首先事务启动,然后session A会对表t加一个MDL读锁,由于session B需要的也是读锁,第二条查询语句也能正常执行。但之后session C会被阻塞,因为前面的读锁还没释放,而session C需要写锁。当session C阻塞,之后只需要读锁的请求也都会被阻塞,等同于这张表此时完全不可读写。

如果某张表上查询语句频繁,而客户端有重试机制,即超时后再起session请求,那么在上述情况下库的线程很快就会爆满。

基于以上分析,考虑一个场景,假设要对一张小表加字段,这张表数据量不大,但是请求很频繁,该怎么做?

此时因为请求频繁,不能简单kill事务。比较好的方法是,在alter table语句里设置等待时间,如果在等待时间里能拿到MDL写锁就进行修改,拿不到也不阻塞后面的业务语句,先放弃修改,之后开发人员人工介入。

目前已有相应的语句:

ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...

参考资料:极客时间专栏《MySQL实战45讲》https://time.geekbang.org/column/intro/100020801?tab=catalog

MySQL 06 全局锁和表锁:给表加个字段怎么有这么多阻碍?的更多相关文章

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

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

  2. Mysql实战45讲 06讲全局锁和表锁:给表加个字段怎么有这么多阻碍 极客时间 读书笔记

    Mysql实战45讲 极客时间 读书笔记 Mysql实战45讲 极客时间 读书笔记 笔记体会: 根据加锁范围:MySQL里面的锁可以分为:全局锁.表级锁.行级锁 一.全局锁:对整个数据库实例加锁.My ...

  3. MySQL锁(二)表锁:为什么给小表加字段会导致整个库挂掉?

    概述 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持.最常使用的MYISAM与INNODB都支持表级锁定.表级锁定分为表共享 ...

  4. 观锁和乐观锁——《POJOs in Action》

    1        事务隔离 事务隔离是数据库提供的功能. SQL Server通过SET TRANSACTION ISOLATION LEVEL语句设置事务隔离级别: SET TRANSACTION ...

  5. EF基础知识小记七(拆分实体到多个表以及拆分表到多个实体)

    一.拆分实体到多个表 1.在日常开发中,会经常碰到一些老系统,当客户提出一些新的需求,这些需求需要在原来的表的基础上加一些字段,大多数人会选择通过给原表添加字段的方式来完成这些需求,方法,虽然可行,但 ...

  6. 【MySQL 读书笔记】全局锁 | 表锁 | 行锁

    全局锁 全局锁是针对数据库实例的直接加锁,MySQL 提供了一个加全局锁的方法, Flush tables with read lock 可以使用锁将整个表的增删改操作都锁上其中包括 ddl 语句,只 ...

  7. MySQL 全局锁、表锁以及行锁

    1. 系统版本 MySQL 5.7.25 ubuntu 16.04 2. 全局锁 全局锁即对整个数据库实例加锁,使得整个库处于只读状态,会阻塞DML和DDL语句.使用如下命令(简称FTWRL)可为数据 ...

  8. MySQL 全局锁和表锁

    根据加锁的范围,MySQL 里面的锁大致可以分成全局锁,表级锁,行锁. 行锁已经在前面几篇文章说过 1. 全局锁 全局锁就是对整个数据库实例加锁.MySQL 提供了一个加全局读锁的方法,命令是Flus ...

  9. MySQL数据库的全局锁和表锁

    1.概念 数据库锁设计的初衷是处理并发问题.作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则.而锁就是用来实现这些访问规则的重要数据结构. 2.锁的分类 根据加锁的范围, ...

  10. MySQL的中的全局锁、表级锁、行锁

    MySQL的中的全局锁.表级锁.行锁 学习极客时间-林晓彬老师-MySQL实战45讲 学习整理 全局锁 对整个数据库实例加锁.通过使用Flush tables with read lock (FTWR ...

随机推荐

  1. php代码审计实战-开源项目Materialized CMS漏洞检测

    一.下载Materialized CMS 链接地址:https://sourceforge.net/projects/materialized-cms/files/latest/download 二. ...

  2. ASP.NET Core 静态资源的打包与压缩

    以 Visual Studio Community 2017 15.5.1 为例 配置文件 bundleconfig.json 新建一个AspNetCore MVC项目,项目中会有一个bundleco ...

  3. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents

    场景重现 npm install --verbose 安装依赖的时,出现如下警告 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1. ...

  4. win11的go安装

    背靠国外各大金主的go语言,在各种推动下,可谓是新的弄潮儿,但国内虽然各种推销,但从安装到开发再到维护,资料都少之又少,可能被垄断了解释权吧. 因此下面的也只是一个记录而已,是一次仅限于本人本机本阶段 ...

  5. js 计算精度问题解决

    js 计算精度问题解决 /** * * * @param x 需处理精度的数 * @param n 小数点后第 n 位 * @returns 处理后的数 */ function roundFracti ...

  6. 康谋方案 | AVM合成数据仿真验证方案

    随着自动驾驶技术的快速发展,仿真软件在开发过程中扮演着越来越重要的角色.仿真传感器与环境不仅能够加速算法验证,还能在安全可控的条件下进行复杂场景的重复测试. 本文将分享如何利用自动驾驶仿真软件配置仿真 ...

  7. 你了解 Java 的 ZGC(Z Garbage Collector)吗?

    Java 的 ZGC(Z Garbage Collector) ZGC(Z Garbage Collector) 是 Java 11 引入的一种低延迟垃圾回收器,旨在减少垃圾回收时的停顿时间,并能够在 ...

  8. jmeter操作数据库增删改查的注意事项

    一,场景 1.在jmeter造数据后,可通过数据库查询数据库是否新增数据,判断脚本执行是否成功. 2.有些数据新增不可重复,因此脚本执行后需要将新增的数据删除,才能再次执行脚本. 二.连接数据库 在通 ...

  9. Cocos Creator3.x小白常见问题笔记&官方视频教程合集收藏分享

    小白常见问题 为什么会有这篇笔记? 这篇笔记旨在答疑解惑官方文档或视频教程里忽略掉的细节.对于小白来说这些细节没人提醒或浪费很多时间,但在熟悉的人眼里这都是些什么问题,回都懒得回. (别问我怎么知道的 ...

  10. Python3爬虫入门(一)

    Python3爬虫入门 ​网络爬虫,也叫网络蜘蛛(Web?Spider).它根据网页地址(URL)爬取网页内容,而网页地址(URL)就是我们在浏览器中输入的网站链接. 在浏览器的地址栏输入URL地址, ...