• Mysql中常见的锁


    加锁的目的就是保证共享资源在任意时间里,只有一个线程访问,这样就可以避免多线程导致共享数据错乱的问题。

    分类:

    操作数据的粒度分类:全局锁、表级锁、行锁

    数据操作的类型分类:

    1. 悲观锁:读锁(共享锁),写锁(排他锁)都不支持并发;
    2. 乐观锁:支持多线程并发,事务不需要排队,都可以对该数据进行修改,不过该数据需要有版本号,只有修改前和修改后的版本号一致才会修改成功,否则就会回滚。(先修改再验证) ,如在线文档
      只有在冲突概率非常低,且加锁成本非常高的场景时,才考虑使用乐观锁。

    锁的级别分类:

    1. 高级锁:读锁、写锁
    2. 低级锁: 互斥锁、自旋锁 (都是悲观锁)

    高级的锁都会由低级锁来实现,比如读写锁既可以选择互斥锁实现,也可以基于自旋锁实现。

    1. 全局锁

    执行后,整个数据库就处于只读状态了,DQL查询可用,DML和DDL不可用。

    场景

    全局锁主要应用于做全库逻辑备份,这样就不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样的情况。

    缺点: 粒度太大,造成业务停滞

    上锁:flush tables with read lock;
    解锁:unlock tables;

    2. 表锁

    InnoDb和MyISAM都支持;开销小,加锁快,粒度大,冲突概率高,并发度低下;

    上锁:
    lock tables 表名 read; (读锁)
    lock tables 表名 weite; (写锁)

    解锁:
    unlock tables;

    注意:当上读锁时,上锁的这个会话中也不能对该表进行写(DML、DDL)操作

    3. 行锁

    InnoDb引支持行级锁,MyISAM不支持,开销大,加锁慢,粒度小,冲突概率低,并发度高;

    上锁:
    select... where... lock in share mode;
    select... where... for update;

    3. 互斥锁和自旋锁

    当已经有一个线程加锁后,其他线程加锁则就会失败,互斥锁和自旋锁对于加锁失败后的处理方式是不一样的:

    • 互斥锁加锁失败后,线程会释放 CPU ,给其他线程;
    • 自旋锁加锁失败后,线程会忙等待,直到它拿到锁;

    互斥锁:
    互斥锁是一种「独占锁」,比如当线程 A 加锁成功后,此时互斥锁已经被线程 A 独占了,只要线程 A 没有释放手中的锁,线程 B 加锁就会失败,于是就会释放 CPU 让给其他线程,既然线程 B 释放掉了 CPU,自然线程 B 加锁的代码就会被阻塞态。
    对于互斥锁加锁失败而阻塞的现象,是由操作系统内核实现的。当加锁失败时,内核会将线程置为「睡眠」状态,等到锁被释放后,内核会在合适的时机唤醒线程,当这个线程成功获取到锁后,于是就可以继续执行。所以,互斥锁加锁失败时,会从用户态陷入到内核态,让内核帮我们切换线程,虽然简化了使用锁的难度,但是存在一定的性能开销成本。

    自旋锁:
    使用自旋锁的时候,当发生多线程竞争锁的情况,加锁失败的线程会「忙等待」,
    自旋锁是最比较简单的一种锁,一直自旋,利用 CPU 周期,直到锁可用,
    但如果被锁住的代码执行时间过长,自旋的线程会长时间占用 CPU 资源,

    比较:
    旋锁与互斥锁使用层面比较相似,但实现层面上完全不同:当加锁失败时,互斥锁用「线程切换」来应对,自旋锁则用「忙等待」来应对。

    它俩是锁的最基本处理方式,更高级的锁都会选择其中一个来实现,比如读写锁既可以选择互斥锁实现,也可以基于自旋锁实现,

    场景:
    互斥锁加锁失败会切换线程来应对,会增加开销;如果被锁住的代码的执行时间短,应该选择自旋锁,忙等待时间也短,开销小;

    参考:
    https://blog.csdn.net/qq_34827674/article/details/108608566
    https://xiaolincoding.com/mysql/lock/mysql_lock.html#%E5%85%A8%E5%B1%80%E9%94%81

  • 相关阅读:
    【LeetCode刷题日志】225.用队列实现栈
    Ubuntu 20.04 LTS配置JDK、Git
    4-7再谈方法之重载
    有源晶振与无源晶振的区别
    【Go 基础篇】Go语言标识符解析:命名的艺术与最佳实践
    Sharding JDBC案例实战
    springboot海纳部门人事管理系统毕业设计源码
    《深度学习进阶 自然语言处理》第七章:seq2seq介绍
    Day32.String内存特性(不可变性、实例化方式、字符拼接) -Java常用类#、集合、IO
    C#连接MySql数据库
  • 原文地址:https://blog.csdn.net/Swofford/article/details/125553723