全局锁和表锁

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

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

全局锁

全局锁就是对整个数据库实例加锁。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. 题解-The Number of Good Intervals

    题面 The Number of Good Intervals 给定 \(n\) 和 \(a_i(1\le i\le n)\),\(m\) 和 \(b_j(1\le j\le m)\),求对于每个 \ ...

  2. 深入理解Java虚拟机(一)——JVM内存模型

    文章目录 程序计数器 定义 作用 特点 Java虚拟机栈 定义 特点 本地方法栈 定义 Java堆 定义 特点 方法区 定义 特点 运行常量池 直接内存 总结 Java虚拟机的内存空间分为五个部分: ...

  3. 使用Tomcat Native提升Tomcat IO效率

    目录 简介 Tomcat的连接方式 APR和Tomcat Native 在tomcat中使用APR 简介 IO有很多种,从最开始的Block IO,到nonblocking IO,再到IO多路复用和异 ...

  4. 十、TestNG分组测试

    使用 groups 属性 package com.lc.tesgFenZu; import org.testng.annotations.AfterGroups; import org.testng. ...

  5. screw一键生成数据库文档

    1. 简介   在项目开发和交付阶段,数据库文档是必不可少的.对于大型项目多个数据库几百甚至几千张表来说,手写数据库文档必然是耗时且痛苦的.因此需要一个插件自动生成文档.   screw提供了多种文件 ...

  6. 密码管理平台ratticdb的部署,在centos7上的部署

    一,前言 一直想用ratticdb这个有web界面的密码管理工具,百度了一下居然没有找到中文的部署文档,访问官网也是notfound.找到了官方的部署指南:https://github.com/til ...

  7. IDEA将Java Web项目打war包

    准备工作 1.IntelliJ IDEA开发工具 2.可以正常运行的Java Web项目 打war包流程 1.使用快捷键Ctrl+Alt+Shift+s 或者 鼠标点击选中项目名按F4 打开 Proj ...

  8. web服务器专题:tomcat(二)模块组件与server.xml 配置文件

    web服务器专题:tomcat(二)模块组件与server.xml 配置文件 回顾: Web服务器专题:tomcat(一) 基础模块 一个Server.xml的实例 <?xml version= ...

  9. 移动端 rem和flexible

    一.rem布局 rem是相对于根元素的字体大小单位. 假设html的字体大小为16px,那么1rem = 16px; 一旦根元素html定义的font-size变化,整个页面中运用到的rem都会随之变 ...

  10. 【Go语言绘图】图片添加文字(一)

    前一篇讲解了利用gg包来进行图片旋转的操作,这一篇我们来看看怎么在图片上添加文字. 绘制纯色背景 首先,我们先绘制一个纯白色的背景,作为添加文字的背景板. package main import &q ...