全局锁和表锁

数据库锁设计的初衷是解决并发出现的一些问题。当出现并发访问的时候,数据库需要合理的控制资源的访问规则。而锁就是访问规则的重要数据结构。

根据锁的范围,分为全局锁、表级锁和行级锁三类。

全局锁

全局锁就是对整个数据库实例加锁。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中的全局锁和表级锁的更多相关文章

  1. MySQL的中的全局锁、表级锁、行锁

    MySQL的中的全局锁.表级锁.行锁 学习极客时间-林晓彬老师-MySQL实战45讲 学习整理 全局锁 对整个数据库实例加锁.通过使用Flush tables with read lock (FTWR ...

  2. MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?

    大家好,我是小林. 最近重新补充了<MySQL 有哪些锁>文章内容: 增加记录锁.间隙锁.net-key 锁 增加插入意向锁 增加自增锁为 innodb_autoinc_lock_mode ...

  3. 详述 MySQL 中的行级锁、表级锁和页级锁

    转自:https://blog.csdn.net/qq_35246620/article/details/69943011 refer:cnblogs.com/f-ck-need-u/p/899547 ...

  4. MySQL行级锁、表级锁、页级锁详细介绍

    原文链接:http://www.jb51.net/article/50047.htm 页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , ...

  5. MySQL行级锁和表级锁

    锁定用于确保事务完整性和数据库一致性. 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据. 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能 ...

  6. Mysql的行级锁与表级锁

    在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM ...

  7. mysql行级锁和表级锁的区别

    表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低:行级锁:开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也最高:

  8. [数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

    注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的 ...

  9. 【数据库】数据库的锁机制,MySQL中的行级锁,表级锁,页级锁

    转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...

随机推荐

  1. 谈谈MySQL bin log的写入机制、以及线上的参数是如何配置的

    目录 一.binlog 的高速缓存 二.刷盘机制 三.推荐的策略 推荐阅读 问个问题吧!为什么你需要了解binlog的落盘机制呢? 我来回答一下: ​ 上一篇文章提到了生产环境中你可以使用binlog ...

  2. 如何使用交易开拓者(TB)开发数字货币策略

    更多精彩内容,欢迎关注公众号:数量技术宅.想要获取本期分享的完整策略代码,请加技术宅微信:sljsz01 为何使用交易开拓者(TB)作为回测工具 交易开拓者(后文以TB简称)是一个支持国内期货市场K线 ...

  3. IOS UITableView 加载未知宽高图片的解决方案

    在开发中遇到了UITableView列表 UITableViewCell装载图片但不知Image的宽高 问题. 在解决该问题的时候,首先想到的是异步加载图片 采用第三方框架SDWebImage 实现对 ...

  4. ACL 的功能、匹配原则、端口号类别

    功能 1)限制网络流量.提高网络性能.例如,ACL可以根据数据包的协议,指定这种类型的数据包具有更高的优先级,同等情况下可预先被网络设备处理. 2)提供对通信流量的控制手段. 3)提供网络访问的基本安 ...

  5. 2020-2021-1 20209307《Linux内核原理与分析》第四周作业

    一.Linux内核源代码简介 1.计算机三大法宝 存储程序计算机 函数调用堆栈 中断机制 2.操作系统两把宝剑 中断上下文的切换 进程上下文的切换 3.函数目录 Linux-3.18.6/arch/x ...

  6. 如何用Python判断一个文件是否被占用?

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 今天有同学问,用os模块的access()能否判断一个文件是否被占用?直觉上,这是行不通的,因为ac ...

  7. 给小白整理的一篇Python知识点

    1.基本概念 1.1 四种类型 python中数有四种类型:整数.长整数.浮点数和复数. python中数有四种类型:整数.长整数.浮点数和复数. 整数, 如 1 长整数 是比较大的整数 浮点数 如 ...

  8. Access 数据库容量问题

    1.单个表的最大容量  2G. 2.单个表的最大条数 3.自动编号的最大数 4.数据库的最大容量 5.text备注形式的字段的最大数据量 6.ole对象字段的最大数据量,图片的最大大小 7.文本字段的 ...

  9. ribbon源码分析

    对于ribbon的使用我们只需要在RestTemplate的申明上面加上 @LoadBalanced 注解之后那么这个RestTemplate就具有了负载均衡的功能 ribbon是怎么实现这一功能的? ...

  10. [LeetCode]141. Linked List Cycle判断循环链表

    快慢指针用来判断循环链表  记住 快慢指针有四种常用的应用场景: 1.找到有序链表的中点,快指针到头的时候,慢指针就是中点. 2.判断是不是循环链表,快慢指针相遇就是 3.找到循环链表的起点,以链表头 ...