广告
返回顶部
首页 > 资讯 > 数据库 >一篇文章带你了解清楚Mysql 锁
  • 341
分享到

一篇文章带你了解清楚Mysql 锁

mysql锁机制mysql锁机制应用场景mysql锁表和解锁语句 2022-11-29 09:11:05 341人浏览 薄情痞子
摘要

一丶为什么数据库需要锁 数据库锁设计的初衷是处理并发问题。作为多用户共享 的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实 现这些访问规则的重要数据结构。 根据加锁的范围,Mysql 里面

一丶为什么数据库需要

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

根据加锁的范围,Mysql 里面的锁大致可以分成全局锁表级锁行锁三类

二丶全局锁&全库逻辑备份

全局锁就是对整个数据库实例加锁。全局锁的典型使用场景是,做全库逻辑备份,全库逻辑备份有以下几种方式:

1.Flush tables with read lock (FTWRL)

Flush tables with read lock (FTWRL)可以让整个库处于只读状态的时候,使用这个命令,之后其他线程的数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句讲被阻塞。之所以备份需要加全局锁是为了保证数据的一致性,

2.mysqldump –single-transaction

使用此命令会先启动一个事务拿到一致性视图。由于 mvcC 的支持, 这个过程中其他线程可以进行正常操作,但是使用mysqldump –single-transaction的前提是需要支持事务,如果存在MyISAM引擎的表,并不能保证一致性。

3.set global readonly=true

set global readonly=true也可以保证全库只读,主要有两个原因:

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

三丶锁解决并发事务带来的问题

1.锁解决脏写

多个未提交事务修改相继对同一条记录进行改动的时候,需要进行排队,排队过程其实就是通过为记录加锁实现的。当一个事务想修改记录的时候,首先需要看下有没有于记录相关联的锁结构,如果没有,那么会在内存中生成与之对应的锁结构

一篇文章带你了解清楚Mysql 锁

可能多个事务同时修改同一记录,会产生多个锁结构,其中只有一个事务可以获取到锁,其is_waiting为false,其他事务is_waiting为true,当获取锁的事务结束后,会唤醒其他等待的事务

2.脏读,幻读,不可重复读如何避免

mysql innodb 在repeatable隔离级别下很大程度下避免了幻读(后续详细说到)

2.1 mvcc解决脏读,幻读,不可重复读问题

Mysql InnoDB多版本并发控制MVCC 这篇博客我们详细说到了mvcc的实现的原理,简单来说就是在事务运行时会生成read view,其包含四个部分

  • m_ids:在生成read view时,当前系统中活跃的读写事务id列表
  • min_trx_id:生成read view时,当前系统中活跃的读写事务中最小事务id,也就是m_ids中的最小值
  • max_trx_id:生成read view时,系统应该分配给下一个事务的事务id值
  • creator_trx_id:生成该read view的事务的事务id

一篇文章带你了解清楚Mysql 锁

查询语句只可以查询生成read view 时刻可以看到的数据,及事务id小于min_trx_id中的数据,写操作则针对最新的数据。非当前读的普通语句在读数据的时候,生成read view的时机不同,在可重复读的时候只会在第一次读取(如果使用start transaction with consistent snapshot则是在事务启动时)生成一个read view 后续不变,达到可重复读的目的,对于读已提交,则是每次读取都会生成新的read view,从刷新未提交事务集合,和min_trx_id,读取到已经提交的数据。使用mvcc让读写并不冲突,数据库的并发能力更强。

2.2读写均加锁

比如在银行存款业务中,我们需要先读取账户余额,然后加上新增存款,然后进行写回操作,整个流程中,我们不希望存在另外一个ATM进行存取的操作,读写都需要排队,这时候就得使用锁。

上面我们说了,写操作进行排队可以解决脏写,那么脏读,不可重复读,幻读是怎么使用读写加锁解决昵?

脏读产生的原因是,当前事务读取到了另外一个事务没有提交的数据,那么只需要另外一个事务对操作的记录加锁,当前事务无法获取到锁,自然就不会发生脏读。

不可重复读产生的原因是,当前事务先读取了一条记录,然后存在另外一个事务修改了此记录的数据,那么只要当前事务对记录进行加锁,自然后续的事务将无法修改,自然不会发生不可重复读。

幻读产生的原因是,当前事务根据条件查询得到一批数据,然后后续事务新增了满足这些条件的数据,导致再次查询时发现多了一些数据,如同出现了幻觉。这里加锁则不是单对记录加锁,而是要锁住一个范围,让其他事务无法插入数据,从而解决幻读(后续会说到这种锁)

很明显读写都加锁,并发能力不及mvcc

3.一致性读

事务利用MVCC进行读取操作称为一致性读(又称一致性无锁读,快照读),基本上所有的普通读在可重复读,读提交隔离级别下,都是一致性读。

4.锁定读

4.1共享锁&独占锁

共享锁:简称S锁,事务要读取一条记录的时候需要先获取到记录的共享锁

独占锁:简称x锁,当事务需要改动记录的时候,需要先获取记录的独占锁

共享锁和共享锁兼容,独占锁和独占锁,独占锁和共享锁互斥

4.2锁定读的语句

select xxx lock in share mode可以对读取的记录加S锁

select xxx for update可以对读取的记录加X锁

4.3 写操作

delete

删除记录首先要在b+数中定位到这条记录的位置,然后获取x锁,然后指向delete mark(标记记录被删除)

update

如果未修改键值,并且修改前后数据的存储空间大小不变,那么现在b+树上定位记录,然后加x锁。反之需要在b+树上定位数据,然后把记录彻底删除吗,然后再插入一条新的记录,对新增的这条数据加x锁

insert

新插入记录一般都是加隐式锁(后面说)不需要在内存中生成对应的锁结构。

三丶InnoDB表锁

1.表级S,X锁

innodb支持表级锁,也支持行级锁,表级锁粒度相对更粗,占用资源较少。使用表级锁效果相当于为表中的所有记录加锁,所以性能比较差。

表级S锁,X锁

使用Lock Tables t Read,innodb存储引擎会对表t加共享锁

使用Lock tables t write,innodb存储引擎会对表t加独占锁

类似于Java中的读写锁,共享锁和共享锁不互斥,独占锁和独占锁,独占锁和共享锁互斥。

2.表级意向锁

innodb存储引擎中,当对表中某些记录加S锁之前,会在表上加上一个IS锁,同样加X锁之前会加表级IX锁,这里的I表示意向锁,SX表示共享还是互斥,表级意向锁存在的目的是后续对表加S锁,X锁的时候,可以快速判断表中是否存在加锁的记录,避免遍历每一个记录查看是否被加锁。

一篇文章带你了解清楚Mysql 锁

3.表级AUTO-INC锁

mysql可以为某列执行Auto Increment自增,系统给自增列赋值的实现方式主要存在两种

使用AUTO-INC锁,执行插入语句的时候加一个表级AUTO-INC锁,然后为每条待插入的记录中的自增列,进行递增赋值,单个插入语句执行结束后释放AUTO-INC锁。这样会导致其他事务的插入被阻塞。 采用轻量级AUTO-INC锁,在为插入列赋值结束后,就释放轻量级锁,而不是插入语句执行完后才释放 四.MDL

一般情况下 对某一个表执行增删改查的时候,都不会加表锁,但是执行一些DDL修改表结构,删除表时,其他事务对这表的增删改查发生阻塞。这是由MDL锁实现的,MDL锁也分为读锁和写锁,在进行crud操作的时候,会加MDL读锁,进行DDL的时候会加MDL写锁。

我们需要注意MDL读锁写锁是互斥的

一篇文章带你了解清楚Mysql 锁

如图四个不同的session先后依次执行语句,其中A,B都是获取MDL读锁,互不阻塞,随即C获取MDL写锁,这时候C会被阻塞,这一阻塞不打紧,还会阻塞后续获取MDL读锁的事务,造成整个表不可用。这启发了我们,在做DDL的时候要解决长事务,事务不提交,就会一直占着MDL锁。在 MySQL 的 infORMation_schema 库的innodb_trx 表中,可以查到当前执行中的事务。如果要做 DDL 变更的表刚好有长事务在执行,要考虑先暂停 DDL,或者 kill 掉这个长事务。

五丶innodb 行锁

1.Record Lock

官方名称Lock_REC_NOT_GAP

一篇文章带你了解清楚Mysql 锁

记录锁有S锁和X锁,S型记录锁之间可以共享,X型记录锁和S型记录锁,X型记录锁互斥

2.GAP Lock

innodb的可重复读级别,使用词锁解决幻读问题,前面我们说过,其难点在于,加锁的时候幻影记录还未出现。官方使用Lock_GAP实现如下操作

一篇文章带你了解清楚Mysql 锁

此处的gap锁可以反之其他事务在number为8记录前面的间隙插入新的记录,在区间(3,8)内无法进行插入操作,当另外一个事务要插入number为4的记录时,首先需要定位到该条记录的下一条记录,也就是number为8的记录,此时number为8的记录具备gap锁,所以将阻塞插入操作,直到gap锁被释放,其他事务才能进行插入。
gap锁出现的目的,就是为了防止插入幻影记录,如果对记录上gap锁,并不会限制其他事务对记录加记录锁

innodb有两个虚拟的记录Infimum(虚拟最小),Supermun(虚拟最大)当我们想在(xx,正无穷)范围锁住幻影记录时就可以对Supermun加gap锁。

3.Next-Key Lock

Next-Key Lock = 记录锁 + gap锁,既锁住记录,也锁住记录之前的间隙

一篇文章带你了解清楚Mysql 锁

4.Insert Intention Lock

插入意向锁,表示事务想在某个间隙插入新的记录,但是当前处于等待状态。

比如事务A持有(4,8)范围内的gap锁,事务B和C,想插入(4,8)范围内的记录,就会在内存中生成事务B,C对应的插入意向锁,当前事务A释放gap锁的时候,将唤醒事务B和C,事务B和C可以同时获取插入意向锁,然后进行插入。插入意向锁并不会阻止对记录继续上锁。

5.隐式锁

为事务生成内存中的锁结构并不是一个0成本的事情,为了节省这个成本,提出隐式锁的概念。

当一个事务插入语一条记录A,其他事务

select xxx Lock in share mode读取记录A(获取记录A的S锁),或者使用select xxx for update(获取记录A的X锁) 立即修改记录A(获取x锁)

对于聚簇索引来说,有一个隐藏列trx_id此列存储着最后更改记录的事务id,在当前事务A插入记录后,便是存储着当前事务A的id,其他事务B企图获取x锁,s锁的时候,就需要下先看一下,trx_id隐藏列对应的事务是否存活,如果不是那么正常获取,反之需要为当前事务A创建一个x锁内存结构,并标记is_waiting为false,然后事务B将为自己创建一个锁结构,is_waiting 为true然后事务B进入等待状态

对于二级索引来说,其不具备隐藏列trx_id但是在二级索引页面的page header中的page_maxt_trx_id属性,记录了改动页面最大的事务id,如果其属性值小于当前最小的活跃事务id,那么说明对页面的改动事务已经提交,否则需要定位到二级索引记录,然后回表对聚簇索引进行上述聚簇索引的操作。

一个事务对新插入的记录不需要显示的加锁,由于事务id的存在相当于加了一个隐式锁,别的事务需要加S锁或者X锁的时候,先帮之前的事务生成锁结构,然后为自己生成锁结构,再进入阻塞状态。隐式锁起到了延迟加锁的作用,也许别的事务不会获取于隐式锁冲突的锁,这时候可以减少内存中生成锁结构。

到此这篇关于一篇文章带你了解清楚Mysql 锁的文章就介绍到这了,更多相关Mysql 锁详解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

您可能感兴趣的文档:

--结束END--

本文标题: 一篇文章带你了解清楚Mysql 锁

本文链接: https://www.lsjlt.com/news/173614.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 一篇文章带你了解清楚Mysql 锁
    一丶为什么数据库需要锁 数据库锁设计的初衷是处理并发问题。作为多用户共享 的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实 现这些访问规则的重要数据结构。 根据加锁的范围,mysql 里面...
    99+
    2022-11-29
    mysql锁机制 mysql锁机制应用场景 mysql锁表和解锁语句
  • 一篇文章带你弄清楚Redis的精髓
    目录一、Redis的特性1.1 Redis为什么快?1.2 Redis其他特性1.3 Redis高可用二、Redis数据类型以及使用场景2.1 String2.1.1 基本指令2.1...
    99+
    2023-02-08
    redis基础知识 redis入门指南 redis的原理
  • 一篇文章讲解清楚MySQL索引
    目录一丶什么是索引二丶索引的数据结构1.哈希表2.有序数组3.跳表4.平衡二叉搜索树5.B-树,B+树三丶InnoDB索引方案1.InnoDB行结构2.InnoDB页结构2.1行结构...
    99+
    2022-11-13
    MySQL索引 MySQL索引详解 mysql索引教程
  • 一篇文章带你了解MySQL索引下推
    目录前言SELECT 语句执行过程什么是索引下推?动手实验:索引下推限制拓展:虚拟列总结前言 本文围绕这三个话题来学习索引下推: SELECT 语句执行过程什么是索引下推?索引下推限制 SELECT 语句执行过...
    99+
    2022-10-08
  • 一篇文章让你搞清楚JavaScript事件循环
    目录前言宏任务微任务事件循环宏任务与微任务总结参考资料前言 异步函数也是有执行顺序的。本质上来说,JavaScript是单线程语言,不管是在浏览器中还是nodejs环境下。浏览器在执...
    99+
    2022-11-13
  • 一篇文章让你搞清楚docker常用命令
    目录1、显示docker的系统信息docker info2、镜像命令docker images2.1、搜索镜像2.2、拉取镜像2.3、删除镜像3、容器命令3.1、新建容器并启动3.2...
    99+
    2022-11-16
    docker常用命令 docker常用命令大全 linux安装docker命令
  • 一篇文章带你了解初始Spring
    目录为什么要使用SpringSpring概述Spring容器使用流程1.启动容器2.完成bean的初始化3.注册bean到容器中4.装配bean的属性bean的注册bean属性注入总...
    99+
    2022-11-12
  • 一篇文章带你了解Java SpringBoot Nacos
    目录1、什么是Nacos 1.1与eureka对比1.2与zookeeper对比1.3与springcloud config 对比 2、Spring Cloud Alibaba 套件...
    99+
    2022-11-12
  • 一篇文章带你了解Java Stream流
    目录一、Stream流引入现有一个需求:1.用常规方法解决需求2.用Stream流操作集合,获取流,过滤操作,打印输出二、Stream流的格式三、获取流四、Stream流的常用方法方...
    99+
    2022-11-12
  • 一篇文章带你了解JavaScript-对象
    目录创建对象对象直接量通过new创建对象原型Object.create()属性的查询和设置继承属性访问错误删除属性检测属性序列化对象总结创建对象 对象直接量 对象直接量是由若干名/值...
    99+
    2022-11-12
  • 一篇文章带你了解JavaScript-语句
    目录表达式语句复合语句和空语句复合语句空语句声明语句varfunction条件语句ifif/elseelse ifswitch循环whiledo/whileforfor/in跳转标签...
    99+
    2022-11-12
  • 一篇文章带你了解XGBoost算法
    目录1. 什么是XGBoost1.1 XGBoost树的定义1.2 正则项:树的复杂度1.3 树该怎么长1.4 如何停止树的循环生成2. XGBoost与GBDT有什么不同3. 为什...
    99+
    2022-11-12
  • 一篇文章带你了解jQuery动画
    目录1.控制元素的显示与隐藏 show() hide()2.控制元素的透明度 fadeIn() fadeOut()3:控制元素的高度 slideUp() slideDown()总结 ...
    99+
    2022-11-12
  • 一篇文章带你了解vue路由
    目录概念Vue Router简介Vue Router的特性Vue Router的使用步骤分类嵌套路由动态路由命名路由编程式导航总结概念 路由的本质就是一种对应关系,比如说我们在url...
    99+
    2022-11-13
  • 一篇文章带你深入了解Mysql触发器
    目录1.对SC表进行插入或修改时,如果考试成绩不在0-100范围内时,则撤销插入或修改操作。2.对SC表进行插入时,如果学生的选课总学分超过30,则报错并撤销插入。3.对SC表进行修...
    99+
    2022-11-12
  • 一篇文章带你了解MySQL数据库基础
    目录1. 数据库概念1.1 数据库是干嘛的?1.2 数据库和数据结构是啥关系?1. 数据库是一个软件/程序1.3 两种类型的数据库2. MySQL数据库2.1 MySQL数据...
    99+
    2022-11-12
  • 一篇文章带你了解SpringBoot Web开发
    目录SpringBoot Web开发静态资源定制首页thymeleaf模板引擎1、导入依赖2、controller书写源码分析Thymeleaf语法基本语法:MVC配置原理总结Spr...
    99+
    2022-11-12
  • 一篇文章带你了解Python中的类
    目录1、类的定义2、创建对象3、继承总结1、类的定义 创建一个rectangle.py文件,并在该文件中定义一个Rectangle类。在该类中,__init__表示构造方法。其中,s...
    99+
    2022-11-12
  • 一篇文章带你了解Spring AOP 的注解
    目录1、xml 的方式实现 AOP①、接口 UserService②、实现类 UserServiceImpl③、切面类,也就是通知类 MyAspect④、AOP配置文件 applic...
    99+
    2022-11-13
  • 一篇文章带你深入了解javaIO基础
    目录一.认识IO1.IO的分类2.IO的方式3.IO读写的方式4.IO的特性二.文件操作1.文件的构成2.文件的创建3.文件操作的API使用三.IO流1.流的分类2.流的创建3.流的...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作