• MySQL8.0优化 - 锁 - 从数据操作的类型划分:读锁、写锁



    学习资料

    【MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!-哔哩哔哩】
    【阿里巴巴Java开发手册】https://www.w3cschool.cn/alibaba_java

    锁的不同角度分类

    锁的分类图如下

    在这里插入图片描述

    从数据操作的类型划分:读锁、写锁

    对于数据库中并发事务读-读情况并不会引起什么问题。对于写-写读-写写-读这些情况可能会引起一些问题,需要使用MVCC或者加锁的方式来解决它们。在使用加锁的方式解决问题时,由于既要允许读一读情况不受影响,又要使写-写读-写写-读情况中的操作相互阻塞,所以MySQL实现一个由两种类型的锁组成的锁系统来解决。这两种类型的锁通常被称为共享锁(Shared Lock S Lock)排他锁(Exclusive Lock,X Lock),也叫读锁(read lock)写锁(write lock)

    读锁

    读锁:也称为共享锁、英文用S表示。针对同一份数据,多个事务的读操作可以同时进行而不会互相影响,相互不阻塞的。

    写锁

    写锁:也称为排他锁、英文用X表示。当前写操作没有完成前,它会阻断其他写锁和读锁。这样就能确保在给定的时间里,只有一个事务能执行写入,并防止其他用户读取正在写入的同一资源。

    需要注意的是对于InnoDB引擎来说,读锁和写锁可以加在表上,也可以加在行上。

    锁定读

    在采用加锁方式解决脏读、不可重复读、幻读这些问题时,读取一条记录时需要获取该记录的S锁,其实是不严谨的,有时候需要在读取记录时就获取记录的X锁,来禁止别的事务读写该记录,为MySQL提供了两种比较特殊的SELECT语句格式:

    对读取的记录加S锁

    SELECT ... LOCK IN SHARE MODE;
    # 或
    SELECT ... FOR SHARE; #(8.0新增语法)
    
    • 1
    • 2
    • 3

    在普通的SELECT语句后边加LOCK IN SHARE MODE,如果当前事务执行了该语句,那么它会为读取到的记录加S锁,这样允许别的事务继续获取这些记录的S锁(比方说别的事务也使用SELECT ... LOCK IN SHARE MODE语句来读取这些记录),但是不能获取这些记录的X锁(比如使用SELECT ... FOR UPDATE语句来读取这些记录,或者直接修改这些记录)。如果别的事务想要获取这些记录的X锁,那么它们会阻塞,直到当前事务提交之后将这些记录上的S锁释放掉。

    对读取的记录加X锁

    SELECT ... FOR UPDATE;
    
    • 1

    在普通的SELECT语句后边加FOR UPDATE,如果当前事务执行了该语句,那么它会为读取到的记录加X锁,这样既不允许别的事务获取这些记录的S锁(比方说别的事务使用SELECT ... LOCK IN SHARE MODE语句来读取这些记录),也不允许获取这些记录的X锁(比如使用SELECT ... FOR UPDATE语句来读取这些记录,或者直接修改这些记录)。如果别的事务想要获取这些记录的S锁或者X锁,那么它们会阻塞,直到当前事务提交之后将这些记录上的X锁释放掉。

    MySQL8.0新特性

    在5.7及之前的版本,SELECT … FOR UPDATE,如果获取不到锁,会一直等待,直到innodb_lock_wait_timeout超时。在8.0版本中,SELECT … FOR UPDATE,SELECT … FOR SHARE添加NOWAIT、SKIP、LOCKED语法,跳过锁等待,或者跳过锁定。
    通过添加NOWAIT、SKIP、LOCKED语法,能够立即返回。如果查询的行已经加锁:
    那么NOWAIT会立即报错返回。
    而SKIP LOCKED也会立即返回,只是返回的结果中不包含被锁定的行。
    在这里插入图片描述

    写操作

    平常所用到的写操作无非是DELETE、UPDATE、INSERT这三种:
    DELETE:对一条记录做DELETE操作的过程其实是先在B+树中定位这条记录的位置,然后获取这条记录的X锁,再执行delete mark操作。我们也可以把这个定位待删除记录在B+树中的过程看成是一个获取X锁锁定读

    UPDATE:在对一条记录做UPDATE操作时分为三种情况:

    情况1:未修改记录的键值,并且被更新的列占用的存储空间在修改前后未发生变化。
    则现在B+树中定位到这条记录的位置,然后再获取一下记录的X锁,最后原纪录的位置进行修改操作。我们也可以把这个定位待修改记录在B+树中位置的过程看成是一个获取X锁锁定读

    情况2:未修改该记录的键值,并且至少有一个被更新的列占用的存储空间在修改前后发生变化。
    则先在B+树中定位到这条记录的位置,然后获取了一下记录的X锁,将记录彻底删除掉(就是把记录彻底移入垃圾链表),最后再插入一条新纪录。这个定位待修改记录在B+树中位置的过程看成是一个获取X锁锁定读,新插入的记录由INSERT操作提供的隐式锁进行保护。

    情况3:修改了该记录的键值,则相当于在原记录上做DELETE操作之后再来一次INSERT操作,加锁操作就需要按照DELETEINSERT的规则进行了。

    INSERT:一般情况下,新插入一条记录的操作并不加锁,通过一种称之为隐式锁的结构来保护这条新插入的记录在本事务提交前不被别的事务访问。

  • 相关阅读:
    Allegro Design Entry HDL(OrCAD Capture HDL)RF-PCB菜单详细介绍
    【Spring boot 集成 JSP】
    基于springboot的健身管理系统
    九、数据库的备份还原
    Turtlebot4入门教程-产品特征
    gpgcheck介绍
    matplotlib.collections、(二)
    Chrome 103支持使用本地字体,纯前端导出PDF优化
    静态库与动态库笔记
    基于ssm的贫困生管理系统javaEE
  • 原文地址:https://blog.csdn.net/ChinaYangJu/article/details/127938866