在软件开发中,程序在高并发的情况下,为了保证一致性或者说安全性,我们通常都会通过加锁的方式来解决,在 MySQL 数据库中同样有这样的问题,一方面为了最大程度的利用数据库的并发访问,另一方面又需要保证每个用户能以一致的方式读取和修改数据,就引入了锁机制。

在 MySQL 数据库中,锁有很多种类型,不过大致可以分为三类:全局锁、表级锁、行级锁。这篇文章我们就简单的聊一聊这三种锁。

全局锁

全局锁是粒度最大的锁,基本上也使用不上,就像我们家的大门一样,控制这整个数据库实例。全局锁就是对整个数据库实例加锁,让整个数据库处于只读状态。

MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL),加锁之后整个数据库实例处于只读状态,有关数据操作的命令都会被挂起阻塞,例如数据更新语句、数据定义语句、更新类事务语句等等。

所以全局锁一般只用于全库备份的时候,一般只用在不支持一致性读的存储引擎做全库备份时,比如 MyISAM 这种不支持一致性读的存储引擎做全库备份时需要使用全局锁,像 InnoDB 引擎做全库备份时不需要使用全局锁。

表级锁

表级锁是 MySQL 最基本的锁策略,并且是开销最小的策略,它锁住的不是整个数据库实例,而是一张表。

表级锁跟全局锁一样,MySQL 数据库提供了加锁的命令: lock tables … read/write。例如 lock tables t1 read, t2 write; 命令,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能访问其他表。

我们可以使用 unlock tables 主动释放锁,如果没有使用的话,在客户端断开的时候自动释放。

表级锁存在一个问题,如果一个查询正在遍历一个表中的数据,而执行期间另一个线程对这个表结构做变更,删了一列,那么查询线程拿到的结果跟表结构对不上,肯定是不行的。

为了解决这个问题,MySQL 5.5版本之后引入了元数据锁(meta data lock,MDL),MDL 是数据库自动加锁,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

MDL 锁有以下两个特点:

  • 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
  • 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

行级锁

行级锁顾名思义就是针对数据库表中的行记录加锁,行级锁可以最大程度的支持并发处理,但是同时也带来了最大的锁开销。

行级锁比较容易理解,比如事务 A 更新了一行,而这时候事务 B 也要更新同一行,则必须等事务 A 的操作完成后才能进行更新。

行级锁是由存储引擎各自实现的,也并不是所有的存储引擎都支持行级锁,比如 MyISAM 引擎就不支持行级锁,这意味着 MyISAM 存储引擎要控制并发只能使用表级锁。

InnoDB 引擎实现了行级锁,InnoDB 存储引擎中实现了两种标准的行级锁:

  • 共享锁(S Lock):允许事务读一行
  • 排它锁(X Lock):允许事务删除和更新一行

共享锁是兼容锁,就是当一个事务已经获得了行 r 的共享锁,其他事务可以立即获得行 r 的共享锁,因为读并未改变行 r 的数据。

排他锁是非兼容锁,如果有事务想获取行 r 的排他锁,若行 r 上有共享锁或者排它锁,则它必须等其他事务释放行 r 的锁。

在 InnoDB 存储引擎中,默认情况下使用的是一致性的非锁定行读,也就是通过行多版本控制器来读取行数据,我们可以显示的为行加上共享锁和排它锁,语句如下:

  • SELECT ..... FOR UPDATE:对读取的行记录加一个排它锁,其他事务想要在这些行上加任何锁都会被阻塞
  • SELECT ....... LOCK IN SHARE MODE:对读取的行记录加一个共享锁,其他事务可以向被锁定的记录加共享锁,但是想要加排它锁。则会被阻塞。

MySQL:聊一聊数据库中的那些锁的更多相关文章

  1. 涂抹mysql笔记-数据库中的权限体系

    涂抹mysql笔记-数据库中的权限体系<>能不能连接,主机名是否匹配.登陆使用的用户名和密码是否正确.mysql验证用户需要检查3项值:用户名.密码和主机来源(user.password. ...

  2. 自定义tt文本模板实现MySql指数据库中生成实体类

    自定义tt文本模板实现MySql指数据库中生成实体类 1.在项目中依次点击“添加”/“新建项”,选择“文本模板”,输入名称后点击添加. 2.在Base.tt中添加如下代码. <#@ templa ...

  3. 聊一聊 MySQL 数据库中的那些锁

    在软件开发中,程序在高并发的情况下,为了保证一致性或者说安全性,我们通常都会通过加锁的方式来解决,在 MySQL 数据库中同样有这样的问题,一方面为了最大程度的利用数据库的并发访问,另一方面又需要保证 ...

  4. 优化MD5和IP在(MySQL)数据库中的存储

    1.MD5在MySQL数据库中的存储 用CHAR(32)来存储MD5值是一个常见的技巧.如果你的应用程序使用VARCHAR(32),则对每个值得字符串长度都需要花费额外的不 必要的开销.这个十六进制的 ...

  5. java和数据库中所有的锁都在这了

    1.java中的锁 1.1 锁的种类 公平锁/非公平锁 可重入锁/不可重入 独享锁/共享锁 读写锁 分段锁 偏向锁/轻量级锁/重量级锁 自旋锁 1.2 锁详细介绍 1.2.1 公平锁,非公平锁 公平锁 ...

  6. Android+PHP+MYSQL把数据库中的数据显示在Android界面上

    俗话说,好记性不如烂笔头.今天终于体会其中的道理了.昨天写好的代码不知道为何找不到了.所以今天我一定得抽出一点时间把我的代码保存起来,以防我的代码再没有了. 还是先上图片. 这个界面是用ListVie ...

  7. MySql 查询数据库中所有表名

    查询数据库中所有表名select table_name from information_schema.tables where table_schema='csdb' and table_type= ...

  8. mysql查询数据库中包含某字段(列名)的所有表

    SELECT TABLE_NAME '表名',TABLE_SCHEMA '数据库名',ORDINAL_POSITION '顺序',COLUMN_NAME '字段',DATA_TYPE '类型' ,CH ...

  9. mysql 从数据库中获取多条记录,二维展示数据

    展示要求: 客户/日期 2017-10-16 1017-10-17 2017-10-18 客户1       客户2       数据库中数据: 解决办法: 1.新建一个实体类:客户名称.客户数据(A ...

随机推荐

  1. php单列模式和工厂模式

    一.单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的.所有的单例模式至少拥有以下三种公共元素: 1. 它们必须拥有一个构造函数,并且必须被标记为pr ...

  2. NetCore3.1及Vue开发通用RBAC前后端通用框架

    目录 框架说明 项目框架图 多租户权限设计表 效果图 后端拉取运行 前端项目请参考 前端系列 发布到docker中 netcore3.1 发布到docker中所遇到的坑及解决 框架说明 该框架是本人学 ...

  3. stm32开发笔记(二):stm32系列使用V3.5固件库的帮助文件以及GPIO基本功能(一)

    前言   stm32系列是最常用的单片机之一,不同的版本对应除了引脚.外设.频率.容量等'不同之外,其开发的方法是一样的.  本章讲解使用库函数使用GPIO引脚功能.   补充   本文章为多年前学习 ...

  4. [MySQL数据库之表的详细操作:存储引擎、表介绍、表字段之数据类型]

    [MySQL数据库之表的详细操作:存储引擎.表介绍.表字段之数据类型] 表的详细操作 存储引擎 mysql中建立的库======>文件夹 库中建立的表======>文件 用来存储数据的文件 ...

  5. for 循环语句 (enumerate枚举,据说直接写出索引值)

    for i in ***: 今天上课看到alex用了 for index,i in enumerate(list): print(index,i) (enumerate好像可以设置开头序号enumer ...

  6. [DB] MySQL 索引分类

    按数据结构 B树索引 数据位于叶子节点,到任何一个叶子节点的距离相同,一般不超过3-4层 B+树索引:每个叶子节点除了数据还存放前后叶子节点的指针,方便快速检索,是InnoDB采用的索引结构 Hash ...

  7. 四大浏览器JavaScript性能/硬件加速测试

    四大浏览器JavaScript性能/硬件加速测试 出处:快科技 2010-09-19 10:52:59    人气: 27925 次   作者:萧萧 编辑:萧萧[爆料]  评论(42)  收藏文章 新 ...

  8. maven build和push image中遇到的坑(学习过程记录)

    最近在做jenkins的持续集成构建,其中一项是要实现docker容器化部署.项目本身是maven项目,我对于maven和docker都没有什么认知基础,于是求助百度和官网,从头开始啃起.遇到了不少的 ...

  9. 使用nuget包下载Entity Framework6.0无法使用模型类与数据库上下文自动生成controller与view

    解决方法:卸载掉原有的6.0版本EF,从控制台安装5.0版本的. >工具>库程序包管理器>程序包管理器控制台.在PM>后面输入安装命令. 命令如下 Install-Packag ...

  10. 几种新的MCU开发环境和语言

    https://kuaibao.qq.com/s/20171108A0LQST00?refer=kb_news 桥大学数学科学中心的Damien P. George在研究各种深奥数学.物理问题之余,还 ...