一起聊聊MySQL全局锁
本篇文章给大家带来了关于mysql的相关知识,其中主要介绍了关于全局锁的相关问题,全局锁就是对整个数据库加锁。当我们对数据库加了读锁之后,其他任何的请求都不能对数据库加写锁了,下面一起来看一下,希望对大家有帮助。
推荐学习:mysql视频教程
数据库设计的初衷是处理并发问题的,作为多用户共享的资源,当出现并发访问时,数据库需要合理地控制资源的访问规则。而锁就是用来实现这个访问规则的重要数据结构。
我们先来贴一个锁的大概分类的图
根据加锁的范围,MySQL 里面的锁大致可以分为全局锁、表锁、行锁。我们主要先来学习这几种锁,这篇我们学习全局锁。
全局锁
全局锁就是对整个数据库加锁。当我们对数据库加了读锁之后,其他任何的请求都不能对数据库加写锁了,当我们对数据库加了写锁之后,后续其他任何的请求都不能对数据库加读锁和写锁了。
FTWRL
MySQL 提供了一个加全局读锁的方法,Flush tables with read lock (FTWRL)。当我们需要让整个库处于只读状态时,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
全局锁的使用场景
全局锁的使用场景:做全库的逻辑备份。逻辑备份也就是把整个库的每个表都 select 出来存成文本。也就是全局锁只有在进行主从备份数据或者导入导出数据的时候才会使用到。
那么为什么需要全局锁呢?
因为我们在做数据备份或者导入导出数据的时候,如果在这个期间还可以同时进行数据的增删改,那么就会出现数据不一致的问题。
以前有一种做法是通过上面提到的 FTWRL 确保在备份的时候不会有其他线程对数据库做更新,注意:这里备份过程中整个库都是完全处于只读状态。
因为全局锁是面向这个数据库的,所以加全局锁听起来很危险:
- 如果我们在主库上备份,在备份期间都不能执行更新,也就是基本上全部业务暂停。
- 如果我们在从库上备份,在备份期间主库同步过来的 binlog 从库都不能执行,也就是会导致主从延迟,数据不一致。
如何避免加锁
既然加全局锁影响这么大,我们能不能避免加锁呢?
通过上面的介绍,我们知道加锁是为了解决数据不一致问题。那么是不是只要我们能解决数据不一致的问题,就可以不用加全局锁了。有这样一个思路:如果我们在开始进行数据备份的时候,记录一个操作日志,备份过程中不加锁允许对数据库的增删改查,而在备份过程中,增删改查的操作记录都记到一个日志文件里,等我们备份完成后,再把这段时间日志文件里的操作都执行一遍。这样就能保证备份前后数据的一致性了。
总结,不加锁的话,备份得到数据和主数据不是一个逻辑时间点,这个视图是逻辑不一致的。如果保证逻辑时间点一致即逻辑视图一致就能保证数据一致,由此我们就想到了我们之前学过的事务隔离级别,可重复复读的隔离级别下开启一个事务就是一个一致性视图。
在 MySQL 的默认引擎 InnoDB 里有一个机制可以保证数据一致性。InnoDB 引擎中有数据快照版本的功能,这个功能叫 MVCC,因为 MVCC 保留了历史版本的快照,每个快照都对应一个事务版本号,而在我们备份数据的时候会申请一个事务版本号,在读取数据的时候,只需要读取比自己事务版本号小的数据即可。
–single-transaction 命令加锁
官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数 –single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。
--single-transaction 参数的作用,设置事务的隔离级别为可重复读,即 REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据,也就大概保证了在 dump 期间,如果其他 InnoDB 引擎的线程修改了表的数据并提交,对该 dump 线程的数据并无影响。
并且设置 WITH CONSISTENT SNAPSHOT 为快照级别。设想一下,如果只是可重复读,那么在事务开始时还没 dump 数据时,这时其他线程修改并提交了数据,那么这时第一次查询得到的结果是其他线程提交后的结果,而 WITH CONSISTENT SNAPSHOT 能够保证在事务开启的时候,第一次查询的结果就是事务开始时的数据 A,即使这时其他线程将其数据修改为 B,查的结果依然是 A。
single-transaction方法只适用于所有的表使用事务引擎的库。在 mysqldump 过程中,加了--single-transaction 就能保证 InnoDB 的数据是完全一致的,对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时候就还是需要全局锁的,所以我们就还是需要使用 FTWRL 命令的。
只读设置
我们可能还会有这样一个疑问,既然要全库只读,我们为什么不适用 set global readonly = true 的方式呢?
确实 readonly 方式也可以让全库进入只读状态,但还是会建议用 FTWRL 方式,主要有两个原因:
- 在有些系统,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此,修改global变量的方式影响面更大。
- 在异常处理机制上有差异。如果执行 FTWRL 命令之后由于客户端发生异常断开,那么 MySQL 会自动释放这个全局锁,整个库回到可以正常更新的状态。
而将整个库设置为 readonly 之后,如果客户端发生异常,则数据库就会一直保持 readonly 状态,这样会导致整个库长时间处于不可写状态,风险较高。
推荐学习:mysql视频教程
以上是一起聊聊MySQL全局锁的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

MySQL是一个开源的关系型数据库管理系统。1)创建数据库和表:使用CREATEDATABASE和CREATETABLE命令。2)基本操作:INSERT、UPDATE、DELETE和SELECT。3)高级操作:JOIN、子查询和事务处理。4)调试技巧:检查语法、数据类型和权限。5)优化建议:使用索引、避免SELECT*和使用事务。

可以通过以下步骤打开 phpMyAdmin:1. 登录网站控制面板;2. 找到并点击 phpMyAdmin 图标;3. 输入 MySQL 凭据;4. 点击 "登录"。

使用 Navicat Premium 创建数据库:连接到数据库服务器并输入连接参数。右键单击服务器并选择“创建数据库”。输入新数据库的名称和指定字符集和排序规则。连接到新数据库并在“对象浏览器”中创建表。右键单击表并选择“插入数据”来插入数据。

MySQL是一种开源的关系型数据库管理系统,主要用于快速、可靠地存储和检索数据。其工作原理包括客户端请求、查询解析、执行查询和返回结果。使用示例包括创建表、插入和查询数据,以及高级功能如JOIN操作。常见错误涉及SQL语法、数据类型和权限问题,优化建议包括使用索引、优化查询和分表分区。

选择MySQL的原因是其性能、可靠性、易用性和社区支持。1.MySQL提供高效的数据存储和检索功能,支持多种数据类型和高级查询操作。2.采用客户端-服务器架构和多种存储引擎,支持事务和查询优化。3.易于使用,支持多种操作系统和编程语言。4.拥有强大的社区支持,提供丰富的资源和解决方案。

可在 Navicat 中通过以下步骤新建 MySQL 连接:打开应用程序并选择“新建连接”(Ctrl N)。选择“MySQL”作为连接类型。输入主机名/IP 地址、端口、用户名和密码。(可选)配置高级选项。保存连接并输入连接名称。

Redis 使用单线程架构,以提供高性能、简单性和一致性。它利用 I/O 多路复用、事件循环、非阻塞 I/O 和共享内存来提高并发性,但同时存在并发性受限、单点故障和不适合写密集型工作负载的局限性。

MySQL和SQL是开发者必备技能。1.MySQL是开源的关系型数据库管理系统,SQL是用于管理和操作数据库的标准语言。2.MySQL通过高效的数据存储和检索功能支持多种存储引擎,SQL通过简单语句完成复杂数据操作。3.使用示例包括基本查询和高级查询,如按条件过滤和排序。4.常见错误包括语法错误和性能问题,可通过检查SQL语句和使用EXPLAIN命令优化。5.性能优化技巧包括使用索引、避免全表扫描、优化JOIN操作和提升代码可读性。
