MySQL的共享锁和排他锁

这篇具有很好参考价值的文章主要介绍了MySQL的共享锁和排他锁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

锁定读 Locking Reads

有过编程语言并发学习经验的同学,应该都了解过读写锁的概念。读写锁主要是为了解决多读少写条件下,程序的并发性能问题。它的特点即是:如果一个线程持有了读锁,那么其他线程也是可以继续读取它锁定的数据,但是不能进行修改,即加写锁;如果一个线程持有了写锁,那么它会阻止任何其他线程的读取和修改。在数据库领域,也有读写锁的概念,下面让我们来了解一下。

在一个事务中,查询数据并且插入或者更新相关的数据,使用常规的 SELECT 语句并不能提供足够的保护。其他事务可以更新或者删除你刚好查询的数据行。因此,InnoDB 支持了两种不同类型的锁定读来提供额外的安全性。Locking Reads 这里我把它称为锁定读,它的作用就是在查询数据时加上读锁或者写锁。

  • 共享锁 Shared Lock,又称为读锁,简称 S 锁
    允许一个事务读取数据,但不允许其他事务修改数据。共享锁通常用于查询操作,以确保查询期间不会有事务修改数据。
  • 排他锁 Exclusive Lock,又称为写锁,简称 X 锁
    允许一个事务读取和修改数据,但不允许其他事务读取或者修改数据。排他锁通常用于更新或者删除操作,以确保在事务完成之前不会有其他事务修改数据。

注: 我觉得 Exclusive Lock 翻译成独占锁也挺好的。

共享锁和排他锁针对的是数据行级别的锁,而不是针对的整个表的锁。不过,在某些情况下,它也会从行锁退化成表锁(这是很严重的问题,应该极力避免它的发生)。

因此在一个事务中查询数据时,需要根据需要来使用共享锁或者排他锁:

  • 查询加共享锁:SELECT ... FOR SHARE
  • 查询加排他锁:SELECT ... FOR UPDATE

注意:锁定读必须在事务语句中才可以生效,或者关系事务的自动提交。

SELECT ... FOR SHARE

在一个事务中,给查询的数据行设置一个共享锁。在事务提交之前,其他的事务(或者会话)可以读取这些数据行,但是不能修改它们。如果这些数据行中的任何数据被其他事务修改了并且没有提交,你的加锁查询必须等待,直到其他事务结束,并且会获取到最新的值。

SELECT ... FOR SHARESELECT ... LOCK IN SHARE MODE 的替代,但是为了向后兼容后者依然可以使用,所以这两句是等价的。因为我这里使用的 MySQL 是 8.0 的版本,所以参考的文档也是 8.0 的。

SELECT ... FOR UPDATE

在一个事务中,给查询的数据行设置一个排他锁,对于搜索遇到的索引记录,它会锁定数据行和相关的索引项,这与使用 UPDATE 语句的效果是相同的。其他事务会被阻止更新(UPDATE)这些数据行、执行查询加共享锁(SELECT ... FOR SHARE)或者读取在某些隔离级别的数据。一致性读取(Consistent Read)会忽略在读取视图中存在的记录上设置在数据行上的任何锁定。(旧版本的记录行无法被锁定;它们是通过 undo logs 重建在记录的内存副本上的)。

注:后面这个一致性读取涉及另一个 MySQL 的重要特性:MVCC,多版本并发控制

所有通过 FOR SHAREFOR UPDATE 查询设置的锁,在事务被提交或者回滚时都会被释放。

注意:外部查询语句的锁定读不会锁定子查询语句,除非在子查询语句中也使用锁定读。下面是两个官方文档的例子:

这条语句不会锁定表 t2 中的行:

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2) FOR UPDATE;

如果要锁定表 t2 中的行,在子查询中使用锁定读语句:

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;

实践

这里来分别实践一下加读锁和加写锁的场景,以及这个过程。

测试表结构:现在是有一个用户账户表(t_user_account),现在再添加一个用户信息表(t_user_info),它的 account_id 字段是用户账户表的主键。

CREATE table t_user_account(
	id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    balance INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


CREATE table t_user_info(
	id INT NOT NULL AUTO_INCREMENT,
    account_id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

查询加读锁

那么现在我需要给用户信息表添加一条记录,这样会有问题吗?这里显然是需要事务的,因为这是多条 SQL 语句了,但是这样就高枕无忧了吗?

MySQL的共享锁和排他锁,mysql

MySQL的共享锁和排他锁,mysql

如果在第一个事务执行查询之后,第二个事务把它查询的数据给删除了呢?这样就会失去参照完整性(referential integrity)了。所以,为了确保在第一个事务执行完成之前,它所依赖的数据不被修改,我们需要加读锁(当然可以加写锁了,但是加了写锁其他事务就无法读取了,影响系统的性能)。如下图,加了写锁之后,第二个事务尝试去删除对应的记录就会被卡住(默认的超时时间是 50s)。

MySQL的共享锁和排他锁,mysql

查询加写锁

这里来模拟一个并发存取钱的场景:

事务 A:查询 id = 1 的用户的余额,然后模拟存 200。
事务 B:查询 id = 1 的用户的余额,然后模拟取 400。

如果这里不加写锁,那么我们来看一下可能出现的错误:

MySQL的共享锁和排他锁,mysql

由于可重复读的原因,第二个事务读取的是它那个时间点数据的快照(MVCC),这样就会导致最终的金额是错误的,两个事务对同一个金额进行修改。也就是说,在第一个事务读取到金额之后,应该阻止其他的事务进行读取,在它执行结束后,才能允许其他事务操作。所以这里需要加写锁,下面是在事务开始之后加写锁之后的执行效果,最终的结果是正确的。这样 id = 1 的这行记录就会被锁住,其他事务是无法对其进行查询(加锁 SELECT)和修改(UPDATE、DELETE)。

MySQL的共享锁和排他锁,mysql文章来源地址https://www.toymoban.com/news/detail-679843.html

到了这里,关于MySQL的共享锁和排他锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL中常用查看锁和事务的SQL语句

    当我们在使用MySQL数据库时,了解如何查看锁和事务的状态是非常重要的。这些信息可以帮助我们调试和优化数据库性能,以及解决并发访问的问题。在本博客中,我将介绍一些常用的MySQL查询语句,用于查看锁和事务的状态。 1. 查看当前的锁状态 要查看当前数据库中的锁状

    2024年02月09日
    浏览(30)
  • MySQL中的表锁,行锁,排它锁,共享锁

    表锁与行锁 1 ) 概念 在使用mysql的时候,如果同时向 mysql 里边批量进行 更新 , 插入 或 删除 动作 数据库里的数据不会出问题, 在 mysql内部,它其实自带了一个锁的功能 而它内部有的是用了锁,有的没有用锁,没用锁的需要咱们利用锁来自行处理 mysql 从范围的角度来讲,支

    2024年02月03日
    浏览(29)
  • java+springboot+mysql大学图书共享交流平台

    项目介绍: 使用java+ssm+mysql开发的大学图书共享交流平台,系统包含超级管理员,系统管理员、用户角色,功能如下: 用户:主要是前台功能使用,包括注册、登录;查看图书交流(发布、查看、借阅、评论、收藏图书),系统留言,关于我们, 用户还具备个人中心功能:

    2024年02月15日
    浏览(43)
  • 【】java+swing+mysql校园共享单车管理系统设计与实现

    校园共享单车作为一种绿色、便捷的出行方式,在校园内得到了广泛的应用。然而,随着单车数量的增加,管理难度也不断加大。如何提高单车的利用率和管理效率,成为校园共享单车发展面临的重要问题。本文针对这一问题,提出设计和实现一个java+swing+mysql的校园共享单车

    2024年02月05日
    浏览(39)
  • 基于微信小程序校园共享系统设计与实现(PHP+Mysql后台)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年02月20日
    浏览(27)
  • 基于微信小程序共享充电桩系统设计与实现(PHP+Mysql后台)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年02月20日
    浏览(34)
  • springboot+mysql+微信小程序共享车位系统-计算机毕业设计源码94559

    摘  要 在信息飞速发展的今天,网络已成为人们重要的信息交流平台。每天都有大量的农产品需要通过网络发布,为此,本人开发了一个基于springboot共享车位系统小程序。 对于本共享车位系统的设计来说,它主要是采用后台采用java语言、springboot框架,它是应用mysql数据库、

    2024年02月06日
    浏览(34)
  • Java高校学校校园学习资料共享平台系统设计与实现(Idea+Springboot+mysql)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年03月14日
    浏览(52)
  • 云计算项目五:部署数据库服务mysql |部署共享存储服务NFS | 配置网站服务

    机器配置 具体配置如下: 添加磁盘 磁盘分区 创建LV 格式化 分别给2台虚拟机添加2块5G的磁盘 查看物理卷 创建卷组 查看卷组大小 创建逻辑卷 两台主机都要做此项操作 具体操作如下: 安装MySQL软件 挂载LV分区 启动服务 管理员登录

    2024年01月25日
    浏览(33)
  • idea Springboot 高校科研资源共享系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

    一、源码特点   springboot 高校科研资源共享系统是一套完善的信息系统,结合springboot框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发), 系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 springboot 高校科研资源共享

    2024年02月07日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包