MySQL中的锁
2024-3-31
| 2024-4-1
字数 2207阅读时长 6 分钟
type
status
date
slug
summary
tags
category
icon
password
AI summary
Last edited time
Apr 1, 2024 05:27 PM

锁的分类

notion image

FTWRL

用作全库逻辑备份,但是会造成业务停滞(无法 DML,DDL)。 可以在备份时开启 RR 级别事务来避免。如果备份的数据库的工具是 mysqldump,在使用 mysqldump 时加上 –single-transaction 参数的时候,就会在备份数据库之前先开启事务。这种方法只适用于支持「可重复读隔离级别的事务」的存储引擎。

backup lock(mysql 8新增)

解决备份时,全局锁开销太大的问题

Table Lock

Metadata Lock

对于引入MDL,其主要解决了2个问题,一个是事务隔离问题,比如在可重复隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求;另外一个是数据复制的问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致slave在重做时,先重做alter,再重做update时就会出现复制错误的现象。 每执行一条DML、DDL语句时都会申请MDL锁,DML操作需要MDL读锁,DDL操作需要MDL写锁(MDL加锁过程是系统自动控制,无法直接干预,读读共享,读写互斥,写写互斥)
元数据锁不用显式的加锁和释放锁,而是在访问表时被自动加上,以保证读写的正确性。加锁和释放锁规则如下:
  • MDL读锁之间不互斥,允许多个线程同时对加了 MDL读锁的表进行CRUD(增删改查)操作;
  • MDL写锁,它和读锁、写锁都是互斥的,目的是用来保证变更表结构操作的安全性。也就是说,当对表DDL操作时,会被默认加 MDL写锁,因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。
  • MDL读写锁是在事务commit之后才会被释放;

Intention Lock

intention lock的主要作用是通过表明表上是否存在行级锁以减少锁表时的性能消耗。 如果另一个任务试图在该表级别上应用共享或排它锁,则受到由第一个任务控制的表级别意向锁的阻塞。第二个任务在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁
InnoDB 支持多粒度锁(multiple granularity locking),它允许行级锁表级锁共存,而意向锁就是其中的一种表锁
  • 意向共享锁 (intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁) 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
    • 意向排他锁 (intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
      • 意向锁于其他表级锁之间的兼容性
        X
        IX
        S
        IS
        X
        Conflict
        Conflict
        Conflict
        Conflict
        IX
        Conflict
        Compatible
        Conflict
        Compatible
        S
        Conflict
        Conflict
        Compatible
        Compatible
        IS
        Conflict
        Compatible
        Compatible
        Compatible
        意向锁不会与行级的共享 / 排他锁互斥

    AUTO-INC Lock

    An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.
    innodb_autoinc_lock_mode
    变量含义
    0
    传统锁模式
    1
    连续锁模式
    2
    交错锁模式(MySQL8默认)
    传统锁模式
    在传统锁模式下,所有的"INSERT-LIKE"语句为AUTO_INCREMENT列使用表级AUTO_INC锁。一个事务的"INSERT-LIKE"语句在语句执行结束后释放AUTO_INC表级锁,而不是在事务结束后释放。这样做的目的是为了保证这个"INSERT-LIKE"语句的自增列的值是连续的。
    连续锁模式
    连续锁模式对于“Simple inserts”不会使用表级锁,而是使用一个轻量级锁来生成自增值,因为InnoDB可以提前直到插入多少行数据。自增值生成阶段使用轻量级互斥锁来生成所有的值,而不是一直加锁直到插入完成。但是如果其他事务持有AUTO_INC锁,那么“Simple Inserts”类语句也需要等待其他事务完成才能使用轻量级锁来生成所有的自增值。 连续锁模式对于“bulk inserts”类语句使用AUTO_INC表级锁直到语句完成。使用表级AUTO_INC锁的语句:INSERT ... SELECT、REPLACE ... SELECT、LOAD DATA 。
     
    交错锁模式
    所有的“INSERT-LIKE”语句都不使用表级锁,而是使用轻量级互斥锁。
    交错锁模式速度快、可扩展性高,但是对于基于语句复制会有问题,只能使用基于ROW复制。
    之所以称为交错模式是因为并发插入场景下自增值的分配大概率是交替这来的,时刻1事务1获得自增值,时刻2事务2获得自增值,以此类推。

    Record Lock

    Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking. 

    GAP Lock

    A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.
    A gap might span a single index value, multiple index values, or even be empty.
    1. 间隙锁主要用于保护范围查询(Range Query),即使用范围条件(例如WHERE子句中使用BETWEEN或大于/小于等操作符)的查询语句。它们会在查询过程中锁定查询范围内的间隙,防止其他事务在该范围内插入新数据。
    1. 间隙锁是在可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)隔离级别下工作的。在这些隔离级别下,MySQL会自动为范围查询设置间隙锁。在其他隔离级别下,MySQL不会自动使用间隙锁。
    1. 间隙锁是排他锁,意味着它们会阻塞其他事务的插入操作。如果一个事务已经获取了一个间隙锁,并且另一个事务试图在该间隙中插入新数据,那么该插入操作会被阻塞,直到持有锁的事务释放锁。
    1. 间隙锁的使用可能会导致死锁。当多个事务同时获取不同间隙的锁,并且它们互相等待对方释放锁时,就会发生死锁。MySQL通过检测和解决死锁来避免这种情况。
    1. 间隙锁的性能开销较大,特别是在高并发环境中。因此,使用间隙锁时需要谨慎考虑,并根据具体情况进行性能测试和优化。

    Next-Key Lock

    Next-Key锁,称为临键锁,它是Record Lock + Gap Lock的组合,用来锁定一个范围,并且锁定记录本身锁,它是一种左开右闭的范围,可以用符号表示为:(a,b]。
     

    📎 参考文章

     
  • MySQL
  • S.M.A.R.T 原则Docker 常用操作
    Loading...