女朋友问我:什么是 MySQL 的全局锁、表锁、行锁?(上)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 女朋友问我:什么是 MySQL 的全局锁、表锁、行锁?

01 前言


小胖真的让人不省心。继上次小胖误删数据之后,这次这货直接给我把整个表锁住了。页面无响应,用户疯狂投诉,我特么脸都绿了。。。


事情是这样的,线上有个数据库几十万的数据,由于一开始没做好规划并没有给热点字段加索引。我就让小胖有空加个索引,没想到这货在用户使用高峰期加。。。


知道原因,我还是比较淡定的。毕竟最近都在研究 MySQL,对于 MySQL 锁的问题解决起来还是得心应手。小胖见我三两下就解决了问题,客户也给出了卧槽,牛逼的肯定,忙问我怎么解决的,我点燃手中 82 年的华子深深吸了一口,花了几个小时写了这篇文章给它。


全文 6618 字,从下午两点写到晚上九点,先上张思维导图镇楼:


640.png


1.1 往期精彩


1、小胖问我:select 语句是怎么执行的?

2、女朋友问我:MySQL 索引的原理是怎样的?

3、小胖问我:MySQL 日志到底有啥用?

4、老王问我:MySQL 事务与 MVCC 原理是怎样的?


02 全局锁


全局锁是对整个数据库实例加锁,让其处于只读状态。MySQL 可以通过  Flush tables with read lock (FTWRL) 实现, PS:unlock tables 可以解除只读状态


执行该命令之后,数据更新语句(DML)数据的增删改操作以及数据操纵语句(DDL)修改表结构等操作将被阻塞。


2.1 全局锁的应用场景


最典型的要数全库逻辑备份,就是把整个库的所有表都 select 出来存成文本


假设现在我的数据库是读写分离的:主写从读。有一种思路是使用 FTWRL 定时备份 + binlog 恢复增量数据。


用 FTWRL 确保备份期间不会有其他线程对数据库做更新操作,然后整库备份。这时数据库实例会处于只读状态,就会造成两个问题:


  • 在主库备份,备份期间不能写入,业务就会收到严重影响。


  • 在从库备份,备份期间不能执行主库同步的过来的 binlog(锁住了,不能写入),就会导致主从延迟,业务也会受到影响。


如果非要用这种方式,那么建议是在一个月黑风高,系统最少用户在使用的时候。


2.2 为什么要加锁?


上面说了,利用全局锁备份会造成两个问题。那不加锁行吗?废话,肯定是不行的。不加锁,你养我呀(备份出问题被开除)?


不加锁同样会出现意想不到的问题:举个栗子,看电影买票,系统有个余额表和用户已购票表。


640.png


锁?


现在我要备份,期间有人买票。逻辑上:余额表减掉相应金额,已购票表加上一张票。备份就会出现两个问题:


  • 先备份余额表,用户购买,再备份用户表。这是会怎样呢?方便理解,我画张图:


从上图,我们也大概知道发生了啥。我来捋一捋:


T1 时刻是备份前两个表的数据状态;T2 时刻开始备份,只备份了余额表;T3 时刻,由于没有加锁,用户买票;T4 时刻是买完票后的状态;T5 时刻备份到已购票表。

看最终的备份状态你发现没有???用户钱没少,票却多了一张(用户窃喜,程序员苦逼)。


以上就是不加锁的下场,它会导致数据前后不一致。这还是先备份余额表后备份已购票表的情况出现的问题。


如果,备份的顺序颠倒一下就会出现:用户钱少了,票却没增加(你指定被投诉,程序员还是苦逼)。


通过上面分析知道,不加锁的话。备份得到的库不是同一个逻辑时间点,才会造成这种后果。那怎么保证是同一逻辑时间点呢?


这时候就要引入上篇文章提到的一致性视图。


2.3 一致性视图备份


上篇说到在可重读隔离级别下开启一个事务,会创建一致性视图


PS:不了解事务,看这里肯定一脸懵。建议看这篇:《MySQL 事务与 MVCC 原理》


你可能会问:狗狗你说得,我都知道。问题是怎么在备份的时候开启事务呢?


是这样,MySQL 自带的逻辑备份工具是 mysqldump 。它使用参数 -single-transaction 可以启动一个事务,从而确保拿到一致性视图。并且由于 MVCC 的支持,备份期间数据库仍可以写入。比如像这样:


// 详细参数见:cnblogs.com/markLogZhu/p/11398028.html
// 格式:mysqldump [选项] --数据库名 [选项 表名] > 脚本名
mysqldump -uroot -p test -single-transaction > /backup/mysqldump/test.db


这时好学的朋友可能会说:既然有了这功能,那不用 FTWRL 命令行不行呀?


答案是:可以的,前提是你的数据库引擎要支持可重复读隔离级别,比如:InnDB;如果是 MyLSAM,那么很抱歉,你还是得用 FTWRL,不然备份拿到的视图还是不一致。就会出现上面数据不一致的问题。


2.4 readonly = 1 的方式行么?


提到全库只读你可能想到这个命令:


mysql> set global read_only=1;


能使用它来让全库只读么?不行或者说是不建议,主要原因有三点:


  • 影响业务逻辑;set global read_only=1 可能会用于一些业务判断,比如:主从的判断,从库只读。


  • 异常不释放状态;FTRWL 命令在异常发生时,会自动释放全局锁;而 set global read_only=1 在异常时,数据库会一直保持只读状态,这时候业务就完犊子了。


  • set global read_only=1 这个命令对超级管理员角色无效;备份期间,超管更新数据库还是会导致数据不一致问题。
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 存储 关系型数据库
【MySQL 数据库】11、学习 MySQL 中的【锁】
【MySQL 数据库】11、学习 MySQL 中的【锁】
76 0
|
1月前
|
存储 关系型数据库 MySQL
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
最全MySQL面试60题(含答案):存储引擎+数据库锁+索引+SQL优化等
157 0
|
7天前
|
关系型数据库 MySQL 数据库
MySQL锁三部曲:临键、间隙与记录的奇妙旅程
MySQL锁三部曲:临键、间隙与记录的奇妙旅程
15 0
|
1月前
|
SQL 关系型数据库 MySQL
MySQL中的锁(简单)
MySQL中的锁(简单)
|
2月前
|
存储 关系型数据库 MySQL
mysql的锁机制实现原理
mysql的锁机制实现原理
|
10天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL 数据库连接
关于MySQL-ODBC的zip包安装方法
关于MySQL-ODBC的zip包安装方法
|
28天前
|
关系型数据库 MySQL 数据库
rds安装数据库客户端工具
安装阿里云RDS的数据库客户端涉及在本地安装对应类型(如MySQL、PostgreSQL)的客户端工具。对于MySQL,可选择MySQL Command-Line Client或图形化工具如Navicat,安装后输入RDS实例的连接参数进行连接。对于PostgreSQL,可以使用`psql`命令行工具或图形化客户端如PgAdmin。首先从阿里云控制台获取连接信息,然后按照官方文档安装客户端,最后配置客户端连接以确保遵循安全指引。
81 1
|
23天前
|
Ubuntu 关系型数据库 MySQL
Ubuntu 中apt 安装MySQL数据库
Ubuntu 中apt 安装MySQL数据库
66 0
|
2天前
|
关系型数据库 MySQL Linux
Linux联网安装MySQL Server
Linux联网安装MySQL Server
10 0