MySQL中的全局锁和表级锁
全局锁和表锁
数据库锁设计的初衷是解决并发出现的一些问题。当出现并发访问的时候,数据库需要合理的控制资源的访问规则。而锁就是访问规则的重要数据结构。
根据锁的范围,分为全局锁、表级锁和行级锁三类。
全局锁
全局锁就是对整个数据库实例加锁。MySQL提供而一个全局读锁的方法。命令是
Flush tables with read lock
当你需要让整个库处于只读的状态时,可以使用这个命令,之后其他线程的数据更新语句、数据定义语句(建表、修改表等)和更新事务的提交语句等都会被阻塞。
全局表的典型使用场景是作为全局逻辑备份
也就是把整个库的每个表都 select出来 存成文本。以前的做法是通过执行声明的语句确保不会有其他线程对数据库做更新操作,然后对整个库做备份。注意,在备份过程中整个库完全处于只读状态。
- 如果在主库上备份,那么在备份期间都不能执行更新操作,业务基本上就得停止。
- 如果你在从库上备份,那么备份期间从库不能执行 从主库同步过来的binlog,会导主从延迟。
看来加全局锁问题会很多,其实备份为什么要加锁呢?
如果不加锁会产生哪些问题?
在支付的场景下,生成订单和扣款两个操作是有先后顺序的。如果是先备份账户余额表再生成订单表, 中间的这个时间段可能会出现一些问题,如果账户余额已经扣了但是生成订单表失败,那么用户会看到自己已经付款了但是还没有生成订单信息。也就是说不加锁的情况下备份系统得到的数据库不是一个逻辑时间点,视图的逻辑不一致。
既然要读全库,为什么不使用set global readonly = true 的方式呢?
确实readonly也可以让钱库进入只读状态,但是建议使用
Flush tables with read lock
主要原因有两个:
- 在有些系统中
readonly的值会被用来做其他逻辑,比如用来判断一个库是主库还是从库。因此在修改global变量的方式影响会更大,不建议使用。 - 在异常处理机制上有差异。如果执行FTWRL命令之后由于客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为readonly后,如果发生异常,数据库不会释放锁,这样导致数据库长时间处于不可写的状态,风险较高。
业务的更新不只是增删改数据(DML),还有可能是加字段等修改表结构的操作(DDL)。不论是哪种方法,一个库被全局锁上后,你要对立面的任何一个表做加字段的操作,都是会被锁住的。
但是即使没有被全局锁住,加字段也不是就能一帆风顺的,因为你还会碰上表级锁。
表级锁
MySQL表级别的锁有两种:一种是表锁,一种是元数据锁(MDL)
表锁的语法是
lock tables ... read/write。与FTWRL类似,可以用unlock tables主动释放锁,也可以在客户端断开的时候自动释放锁。需要注意的是:lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来要处理的事。另一类表锁是MDL。MDL不需要显示使用,在访问一个表的时候回自动加上。MDL的作用是,保证读写的正确性。你可以想象一下,如果一个查询正在遍历一个表中的数据,而执行期间的另一个线程对这个表的结果做了更改,删了一列,那么查询线程拿到的结果和原来的结构对不上肯定是不行的。
因此在5.5版本里面引入了元数据锁,当对于一个表做增删改查的时候,加MDL读锁;当要对表结构做变更操作的时候加MDL写锁。
- 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查
- 读写锁之间、写锁与写锁之间是互斥的,用于保证变更表结构操作的安全性。因此如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完之后才能开始执行。
下面需要注意的是

sessionA先启动,这时候会对表 t 加一个MDL读锁。由于sessionB需要的也是读锁因此可以正常执行。
但是sessionC会被阻塞,因为sessionC是需要写锁的,读锁和写锁之间是会被阻塞的。
这时候后面又来了sessionD,sessionD需要读锁,但是前面的sessionC还没获取到写锁所以一直阻塞到那里,他也跟着阻塞。如果某个表上的查询语句很频繁,而且客户端有重试机制,也就是说超时后会再起一个新的session请求,这样整个库的线程就会被堆满。
解决方法:
在MySQL的information_schema库的innodb_trx表中,你可以查到当前执行中的事务。如果你要做DDL变更的表,刚好有长事务在执行,要考虑先暂停DDL,或者直接kill掉事务。
如果更新表的请求很频繁的话,kill未必管用,因为新的请求会很快到来。比较理想的机制是,在alter table语句里面设置等待时间,如果超过了这个时间就先放弃不在阻塞,之后开发人员再重试这个命令。
MariaDB一个数据库引擎已经合并了AliSQL的这个功能,所以这两个开源分支目前都支持DDL,设置等待时间的语法。
ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...
MySQL中的全局锁和表级锁的更多相关文章
- MySQL的中的全局锁、表级锁、行锁
MySQL的中的全局锁.表级锁.行锁 学习极客时间-林晓彬老师-MySQL实战45讲 学习整理 全局锁 对整个数据库实例加锁.通过使用Flush tables with read lock (FTWR ...
- MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?
大家好,我是小林. 最近重新补充了<MySQL 有哪些锁>文章内容: 增加记录锁.间隙锁.net-key 锁 增加插入意向锁 增加自增锁为 innodb_autoinc_lock_mode ...
- 详述 MySQL 中的行级锁、表级锁和页级锁
转自:https://blog.csdn.net/qq_35246620/article/details/69943011 refer:cnblogs.com/f-ck-need-u/p/899547 ...
- MySQL行级锁、表级锁、页级锁详细介绍
原文链接:http://www.jb51.net/article/50047.htm 页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , ...
- MySQL行级锁和表级锁
锁定用于确保事务完整性和数据库一致性. 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据. 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能 ...
- Mysql的行级锁与表级锁
在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM ...
- mysql行级锁和表级锁的区别
表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低:行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高:
- [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁
注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...
- 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁
转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...
随机推荐
- MySQL技术内幕InnoDB存储引擎(三)——文件相关
构成MySQL数据库和InnoDB存储引擎表的文件类型有: 参数文件:MySQL实例运行时需要的参数就是存储在这里. 日志文件:用来记录MySQL实例对某种条件做出响应时写入的文件. socket文件 ...
- .Net Core Excel导入导出神器Npoi.Mapper
前言 我们在日常开发中对Excel的操作可能会比较频繁,好多功能都会涉及到Excel的操作.在.Net Core中大家可能使用Npoi比较多,这款软件功能也十分强大,而且接近原始编程.但是直接使用Np ...
- 【开源】基于 SpringBoot 的 web kettle 在线采集平台
kettle-scheduler-boot 开发计划 序号 项目 状态 优先级 1 在线管理,编辑kettle脚本 紧急 2 通过源码实现集群,多线程执行任务 紧急 2 重构jpa部分,改为mybat ...
- pip下载超时问题详解
前言 pip下载的安装包都是在国外的pipy服务器上面,又因国内某种墙的策略,导致速度非常的慢,甚至无法访问. 于是国内很多的企业和爱好者纷纷搭建自己的服务器,定时从pypi上拉起所有的镜像文件.然后 ...
- [日常摸鱼]bzoj2463 [中山市选2009]谁能赢呢?
题意:两个人在$n*n$的棋盘上玩游戏,一开始棋子在左上角,可以上下左右的走到没有走过的地方,最后不能走的那个输,两个人都采取最优决策问哪个赢 猜结论!$n$为偶数则先手赢,否则后手赢. 考虑用$1* ...
- [水题日常]UVA Partitioning by Palindromes
一句话题意:每次给你一个字符串问最少划分成多少段才能使得每一段都是回文串. (下面用\(s[1..n]\)来表示这个字符串) 记\(dp[i]\)为\(s[1..i]\)的答案,如果对于某个\(j&l ...
- Eureka系列(九)Eureka自我保护机制
因为本篇简文并不是自己总结的,而是当了下搬运工,所以直接直接附上原作者博客链接. 参考链接: 1.SpringCloud Eureka自我保护机制 2.Spring Cloud Eurek ...
- Python高级语法-对象实例对象属性-类与实例,class方法静态方法等(4.6.1)
@ 目录 1.说明 2.代码 关于作者 1.说明 python中属性:类属性,实例属性 方法:类方法,实例方法,静态方法 想修改类属性,只能是类方法,因为只有类方法把cls(类)传入数据里面 静态方法 ...
- iOS 自定义tabBarController(中间弧形)
效果图 1.在继承自UITabBarController的自定义controller中调用以下方法(LZCustomTabbar为自定义的tabbar) - (void)viewDidAppear:( ...
- c# 递归 yield关键字的用法
1.yield实现的功能 yield return: 先看下面的代码,通过yield return实现了类似用foreach遍历数组的功能,说明yield return也是用来实现迭代器的功能的. u ...