【MySQL】数据库管理过程中的锁问题

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 【MySQL】数据库管理过程中的锁问题

按照锁的大小,我们分为全局锁,表锁,页锁,和行锁。

不同级别的锁有不同的作用,这里我简单列出我在工作过程中对这些锁的理解。

什么使用用全局锁?

全局锁是用来对整个数据库加锁的锁。

我们可以使用Flush Table With Read Lock(FTWRL)来让数据库进入只读状态。

使用这个命令之后,其他线程的如下操作会被阻塞:DML数据增删改操作,DDL数据定义操作,如建表,修改表结构等操作以及更新类事务的提交语句。

全局锁的使用场景在我们公司为:重要库的一天一次的全量备份,次要库的一周一次的全量备份。

做全库的逻辑备份,我们就需要保证再这段时间内没有新的数据,保证数据库只读,否则就会出现数据异常问题,之后恢复数据也会出现问题。

虽然说全局锁肯定也不太好,毕竟使用了全局锁就意味着主库备份时肯定不能写入修改数据了,而从库备份时也就不能同步主库过来的binlog日志,都会有些影响。

但是如果不加全局锁,再备份期间就会导致一些修改操作,而备份恢复的时候这些修改操作已经执行,从而导致的一些数据异常问题,所以加锁能帮助我们避免这些问题。

其实这也就是所谓的数据一致性问题而已,我们在备份的时候,如果可以记录对这些备份数据的修改,并且我们备份数据的时候,能先拿到一下这些数据的快照,那么似乎就可以解决这些数据不一致的问题了,所以就有了mysql自带的备份工具mysqldump。

当 mysqldump 使用参数–single-transaction的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于MVCC 的支持,这个过程中数据是可以正常更新的。但是对于 MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL命令了。所以,single-transaction方法只适用于所有的表使用事务引擎的库。如果有的表使用了不支持事务的引擎,那么备份就只能通过FTWRL 方法。

补充:内容来自《MySQL45讲》

为什么不使用 set global readonly=true 的方式呢?

readonly 方式也可以让全库进入只读状态,但我还是会建议你用 FTWRL 方式,主要有两个原因:

一是,在有些系统中,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此,修改 global 变量的方式影响面更大,我不建议你使用。

二是,在异常处理机制上有差异。如果执行 FTWRL 命令之后由于客户端发生异常断开,那么 MySQL 会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为 readonly 之后,如果客户端发生异常,则数据库就会一直保持 readonly 状态,这样会导致整个库长时间处于不可写状态,风险较高。业务的更新不只是增删改数据(DML),还有可能是加字段等修改表结构的操作(DDL)。不论是哪种方法,一个库被全局锁上以后,你要对里面任何一个表做加字段操作,都是会被锁住的。

什么时候用表锁?

对于MyISAM这种不支持行锁的存储引擎,我们需要锁数据的时候就只能以表为单位来进行加锁,比如使用lock table xxx read/write的方式,并且使用unlock tables的方式来释放锁。

表锁的加锁消耗相比于行锁更小,但是由于锁的粒度比较大,因此容易导致并发问题。

当我们在某个线程使用lock table xxx 的方式来对一张表加上读锁的时候,其他线程只能读取当前这张表,如果写那么会阻塞,也就是我们所谓的读读不互斥,读写互斥。

而如果我们对一张表加了写锁,那么其他线程读取这张表的时候就会直接阻塞,可想而知,死锁的发生概率非常的大。

还要注意的一个锁是MDL元数据锁,这个锁不需要显式的调用,它的作用是帮助我们再执行操作的时候保证表结构不被修改。

同样的,我们在读(包括增删改查)取一个表的时候,会得到MDL读锁,读锁之间不互斥。

但是如果我们开始使用alter语句去修改表结构,那么我们必须确保能拿到MDL写锁,而写锁的获取需要保证前面没有读锁,否则前面有读锁时,写锁需要先阻塞,而此时写锁阻塞,再当前alter语句之后的所有语句,包括获取MDL读锁的语句也会进行阻塞,那么此时就又会出现死锁了。

所以我们一般再要进行alter语句的时候我们会设一个超时时间。

什么时候用行锁?

MySQL InnoDB 存储引擎的行锁是基于索引的。当执行一个含有 WHERE 条件的 SQL 查询时,InnoDB 存储引擎会根据相应的索引定位到符合条件的记录,并对这些记录加上行锁。

行锁的粒度是以记录为单位的,只有在命中对应的索引之后,才会对符合条件的记录进行行锁加锁。这种方式可以提高并发性能,因为只有真正需要锁定的记录才会被锁定,而不是对整个表或整个索引进行锁定。

需要注意的是,如果查询没有命中索引,而是使用全表扫描的方式进行,那么会出现全表锁(Table Lock),而不是行锁。全表锁会锁定整个表,对于并发性能会有一定的影响。因此,在设计数据库表和索引时,合理选择和创建合适的索引是非常重要的。

并且行锁的使用遵循两阶段锁原则,上面我也提到了,只有用到了某条记录才会对某条记录加锁,而如果两个事务都需要对同一个行锁进行修改,那么后来者需要等待先来者事务提交之后才会结束阻塞,否则需要等待事务提交。

也正是这个原因,我们应该需要确保最有可能导致阻塞的语句,放在最接近事务结束的地方,我们公司有一个SKU系统,我们会确保对SKU的操作一定是放在最后进行的,也就是一般情况都是我们的save/update语句的下一条语句就是return,确保对其他事务的影响最小。

随着上面的情况,如果我们的事务一修改了记录1,然后事务二修改了记录2,而之后当事务一需要操作记录2的时候,事务二需要操作记录1的时候就会出现死锁。

对于这种死锁,我们的计划是设定锁超时自动释放,参数为innodb_lock_wait_timeout,由于我们是下游,我们的上游接口有一定的时间,所以我们设定这个参数为10s左右。

mysql害提供了一个innodb_deadlock_detect,他会自动进行死锁检测,但是因为死锁检测的性能消耗是很高的。毕竟他需要扫描每一个事务对应的线程有没有被其他线程锁住,这很消耗性能。

所以我们编码的时候一般需要保证尽可能多的测试,确保业务尽可能不出现死锁,也就是从源头上减少出现死锁的可能性。

同时当初还考虑到由于死锁是出现在对同一行记录的操作,所以我们有的时候会把一条记录进行拆分,合并之后才是这条完整的记录,我们可以吧一些操作先操作在其他行上,或者说我们也会创建中间表,然后再一定时间之后合并操作。


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5天前
|
存储 关系型数据库 MySQL
MySQL的锁机制
MySQL的锁机制主要用于管理并发事务对数据的一致性和完整性的访问控制
21 4
|
7天前
|
关系型数据库 MySQL Linux
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
【MySQL-10】数据库函数-案例演示【字符串/数值/日期/流程控制函数】(代码演示&可cv代码)
|
7天前
|
SQL 关系型数据库 MySQL
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)
【MySQL-5】DDL的数据库操作:查询&创建&删除&使用(可cv代码+演示图)
|
7天前
|
SQL 关系型数据库 MySQL
【MySQL-1】理解关系型数据库&数据的数据模型
【MySQL-1】理解关系型数据库&数据的数据模型
|
8天前
|
关系型数据库 MySQL 数据库
Docker数据库Mysql
Docker数据库Mysql
|
9天前
|
存储 SQL 关系型数据库
mysql查询数据库表大小怎么操作
mysql查询数据库表大小怎么操作
|
9天前
|
关系型数据库 MySQL PHP
【PHP 开发专栏】PHP 连接 MySQL 数据库的方法
【4月更文挑战第30天】本文介绍了 PHP 连接 MySQL 的两种主要方法:mysqli 和 PDO 扩展,包括连接、查询和处理结果的基本步骤。还讨论了连接参数设置、常见问题及解决方法,如连接失败、权限和字符集问题。此外,提到了高级技巧如使用连接池和缓存连接信息以优化性能。最后,通过实际案例分析了在用户登录系统和数据管理中的应用。
|
9天前
|
关系型数据库 MySQL 数据库
【MySQL】:数据库事务管理
【MySQL】:数据库事务管理
23 0
|
9天前
|
SQL 关系型数据库 MySQL
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
20 0
|
9天前
|
SQL 关系型数据库 数据库
【MySQL】:DDL数据库定义与操作
【MySQL】:DDL数据库定义与操作
12 0