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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
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,他会自动进行死锁检测,但是因为死锁检测的性能消耗是很高的。毕竟他需要扫描每一个事务对应的线程有没有被其他线程锁住,这很消耗性能。

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

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


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
22天前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
57 3
|
28天前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。
|
15天前
|
关系型数据库 MySQL 分布式数据库
阿里云PolarDB云原生数据库收费价格:MySQL和PostgreSQL详细介绍
阿里云PolarDB兼容MySQL、PostgreSQL及Oracle语法,支持集中式与分布式架构。标准版2核4G年费1116元起,企业版最高性能达4核16G,支持HTAP与多级高可用,广泛应用于金融、政务、互联网等领域,TCO成本降低50%。
|
16天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
17天前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
16天前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
|
22天前
|
Ubuntu 安全 关系型数据库
安装与配置MySQL 8 on Ubuntu,包括权限授予、数据库备份及远程连接指南
以上步骤提供了在Ubuntu上从头开始设置、配置、授权、备份及恢复一个基础但完整的MySQL环境所需知识点。
223 7
|
22天前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(上)
最终建议:当前系统是完美的读密集型负载模型,优化重点应放在减少行读取量和提高数据定位效率。通过索引优化、分区策略和内存缓存,预期可降低30%的CPU负载,同时保持100%的缓冲池命中率。建议每百万次查询后刷新统计信息以持续优化
83 6
|
22天前
|
缓存 监控 关系型数据库
使用MYSQL Report分析数据库性能(中)
使用MYSQL Report分析数据库性能
79 1
|
22天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。

推荐镜像

更多