MySQL数据库的全局锁、表级锁和行级锁的全面深度解析

本文深入探讨了MySQL数据库中的三种锁机制:全局锁、表级锁(包括表锁和MDL)以及行级锁。全局锁在逻辑备份、防止数据不一致时使用,如`FLUSH TABLES WITH READ LOCK`。表级锁分为表锁和MDL,用于控制并发和表结构修改。行级锁则提供更高的并发性能,包括共享锁和排他锁,以及意向锁。文章还讨论了锁释放、死锁、锁实现以及加锁规则,帮助读者理解如何在并发环境中高效管理MySQL的锁定策略。
摘要由CSDN通过智能技术生成

详细介绍了MySQL数据库中的全局锁、表级锁和行级锁的概念、使用方式,以及相关特性。

和程序中的锁一样,数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当数据出现并发访问的时候,数据库需要合理地控制资源的访问规则,而锁就是用来实现这些访问规则的重要数据结构。

根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行级锁三类。MyISAM支持全局锁和表级锁(table-level locking)。InnoDB 支持全局锁、行级锁(row-level locking)和表级锁,默认为行级锁。

MySQL的隔离级别,有时候就会利用锁来实现:4种隔离级别以及MVCC一致性视图的实现原理

1 全局锁

全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法,命令是Flush tables with read lock ,即FTWRL。

当你需要让整个库处于只读状态的时候,可以使用这个命令,之后将会禁止该数据库中的数据更新和表的结构修改操作,一般在对整个库进行逻辑备份时使用。

在对整个库进行逻辑备份时,如果不加全局锁,由于数据库的备份不可能一瞬间完成,那么将可能造成最终数据不一致的问题。

比如有一个用户余额表,一个商品表,逻辑是用户先在余额表中扣款,然后在商品表中添加购买的商品。假设在此处操作的余额表扣款之前发起了数据库备份,首先备份的余额表,那么此时备份的余额表并没有在此次交易中扣款,在备份余额表之后,余额表发起了扣款,并且商品表增加了商品信息,此时备份到商品表,那么备份的商品表中增加了本次交易的商品。最终结果就是在备份的数据之中,余额表并没有扣款,但是商品表中增加了商品,这样商家就承担了损失。而如果是先添加商品,然后扣款的话,那么最终可能导致商品没有添加,但是被扣了款,那么用户就会来找你了!

也就是说,不加锁的话,备份系统备份的得到的库不是一个逻辑时间点,这个视图是逻辑不一致的。

对于整个数据库加全局锁的确会非常的影响性能:

  1. 整个数据库变得只读,那么正常的业务逻辑肯定会受到影响,业务基本上就得停摆;

  2. 如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;

  3. 如果你在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟。

对于事务性执行引擎来说,还可以使用官方自带的逻辑备份工具是mysqldump,他利用了MVCC的一致性视图的原理,当mysqldump使用参数–single-transaction的时候,导数据之前就会启动一个事务,来确保拿到一致性视图,而由于MVCC的支持,这个过程中数据是可以正常更新的。

对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL命令而不能使用mysqldump了。

还有一种方法,那就是使用set global readonly=true的方式,让整个数据库变得只读,但这种方式并不推荐:

  1. 在有些系统中,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此修改 global 变量的方式影响面更大,不建议适用。
  2. 在异常处理机制上有差异,如执行 FTWRL 命令之后由于客户端发生异常断开,那么 MySQL 会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为 readonly 之后,如果客户端发生异常,则数据库就会一直保持 readonly 状态,这样会导致整个库长时间处于不可写状态,风险较高。

记住,业务的更新不只是增删改数据(DML),还有可能是加字段等修改表结构的操作(DDL)。不论是哪种方法,一个库被全局锁上之后,你要对里面任何一个表做更改操作,都会被锁住的。

2 表级锁

表锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持,最常使用的 MyISAM 与 InnoDB 都支持表级锁定。当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。

默认使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。

另外,在MySQL 5.5版本中引入了元数据锁(MDL,meta data lock),也算作一种表级锁。

2.1 表锁

MySQL的表锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。表锁是MySQL Server负责的实现的。

某个请求对于某个表加了读锁之后,其他请求可以继续获取读锁,但不能获取写锁(当一个请求在读数据时,其他请求也可以读,但是不能写),获取写锁的请求会阻塞。某个请求对于某个表加了写锁之后,其他请求既不能获取写锁也不能获取读锁,都会被阻塞(当一个请求在写数据时,其他请求不能执行任何操作)。

对于一个或者多个表主动加读/写表锁的命令是:

LOCK TABLES tablename1 READ/WRITE,tablename2 READ/WRITE,……
复制代码

释放表锁:使用UNLOCK TABLES主动释放所有获取的表锁,也可以在客户端断开的时候自动释放。UNLOCK TABLES会隐含地提交事务,应放在COMMIT之后。

在用LOCK TABLES给

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值