4.mysql锁

    • 锁是计算机协调多个进程或纯线程并发访问某一种资源的机制
    • 锁冲突也是影响数据库并发访问性能的一个重要因素
  1. 锁的分类
    1. 页面锁(全局锁)

      • 开销和加锁位于表锁和行锁之间,会出现死锁,锁定粒度界于表锁和行锁之间,并发一般
      • 场景:全库逻辑备份,注意innodb由于有mvcc是支持备份的时候支持更新操作的
      • 案例:

        使用全局锁,执行之后整个数据库处于只读状态
        flush tables with read lock
        释放锁
        unlock tables

    2. 表级锁

      • 开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发最低
        • 表锁

          表级别的共享锁,也就是读锁
          lock tables t_student read
          表级别的独占锁,也就是写锁
          lock tables t_student write
          释放锁
          unlock tables
          表锁除了会限制别的线程的读写外,也会限制本线程的读写操作

        • 元数据锁(MDL)
          • 不需要对显示的使用MDL,因为对数据库表进行操作的时候会自动给这个表加入MDL
            • 对一张表进行CURD操作,加的MDL读锁(读读是不冲突的)
            • 对一张表进行结构变更操作的时候,加的是MDL写锁
          • MDL是在事务提交之后才会释放的,意味事务执行期间,MDL是一直持有的
          • 申请MDL锁的操作会形成一个队列,队列中的写锁获取优先级高于读锁的,一旦出现MDL写锁等待,会阻塞后续该表的所有CRUD操作
        • 意向锁
          • 在使用innodb引擎时,对表里的某些记录加入【共享锁】之前,需要先在表级别加入【意向共享锁】
          • 在使用innodb引擎时,对表里的某些记录加入【独占锁】之前,需要先在表级别加入【意向独占锁】
          • 当执行插入、更新、删除操作时,需要先对表加上【意向独占锁】然后对记录加独占锁,而普通的select是不会加行级别锁的,select利用mvcc实现一致性读,是无锁的

            select也是可以对记录加独占锁和共享锁的(锁定读)
            先在表上加入意向共享锁,然后对读取的记录加入共享锁
            select .... lock in share mode
            先在表上加入意向独占锁,然后对读取的记录加入独占锁
            select ... for update
            这两条语句必须在一个事务中,因为当事务提交了,锁就会释放了

          • 意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables ... read)和独占表锁(lock tables ... write)冲突
          • 表锁和行锁满足读读共享,读写互斥,写写互斥的
          • 加入意向锁的目的是为了快速判断表里是否有记录被加锁
          • img
        • Auto-Inc锁
          • 假如说表主键字段设置了自增,之后插入数据可以不指定主键的值,会自动给主键赋自增的值。 这是由(auto-inc锁)来实现的
          • Auto-Inc锁是特殊的表锁机制,不是再一个事务提交后才释放,而是执行完插入语句就立即释放
          • 在插入数据时,会加一个表级别的Auto-Inc锁,然后被Auto_increment修饰字段赋值递增的值,等插入语句执行完成后,才会把Auto-Inc锁释放掉(mysql 5.1.22提供一种轻量化的锁(通过innodb_autoinc_lock_mode系统变量来控制)来实现自增,赋值自增的值就把锁释放了,不需要等待插入语句执行完成)
          • innodb_autoinc_lock_mode
            • 0 采取Auto-Inc锁,语句执行结束后才释放锁
            • 2 采取轻量化锁,申请自增主键后就释放锁,并不需要等语句执行完成(性能最高,但当binlog日志格式是statment一起使用时,在主从复制会出现数据不一致的问题,可以使用binlog_format = row
            • 1 普通insert,自增锁在申请之后就马上释放,如果是批量插入,自增锁还是等语句执行完成
    3. 行级锁

      • 开销大,加锁慢,会出现死锁,锁定粒度最小,发生锁冲突的概率最低,并发最高。 (Innodb引擎是支持行锁的,myIsam是不支持的)
      • 行锁的分类(3类)
        • Record Lock 记录锁,也就是仅仅把一条记录锁上(锁住的是一条记录,在读已提交隔离级别下,行级别锁只有记录锁
        • Gap Lock 间隙锁,锁定一个范围,但是不包含记录本身
        • Next-Key Lock(临键锁):Record Lock+ Gap Lock的组合,锁定一个范围,并锁定记录本身
      • Record Lock锁
        • img
      • Gap Lock锁(只存在于可重复读隔离级别,目的为了解决可重复读级别下幻读的现象)(间隙锁的X和S并不存在互斥关系
        • img
      • Next-Key Lock锁(包含了间隙锁和记录锁)
        • img
      • 插入意向锁
        • 插入意向锁虽然名字有意向锁,但它不是意向锁,它是一种特殊的间隙锁,属于行级别锁(间隙锁锁的是一个区间,而插入意向锁锁的是一个点)
        • 一个事务在插入一条记录时,需要判断插入的位置是否被其他事务加入间隙锁,如果有的话就阻塞,直到拥有间隙锁提交为止,在此期间会生成一个插入意向锁,表明有事务想在此区间插入新纪录,但是现在是等待状态
        • 插入意向锁和间隙锁的一个区别:尽管插入意向锁也属于间隙锁,但两个事务不能同一时间内,一个拥有间隙锁,另一个拥有该间隙锁区间的插入意向锁img
    4. 链接:

posted @ 2023-02-20 17:41  乐天--  阅读(33)  评论(0)    收藏  举报