您的位置:首页 > 游戏 > 游戏 > Mysql 锁

Mysql 锁

2024/12/23 11:44:56 来源:https://blog.csdn.net/qq_43157273/article/details/141819175  浏览:    关键词:Mysql 锁

分类

MySQL中的锁是在服务器层或者存储引擎层实现的,保证了数据访问的一致性与有效性。
  • 按模式:
    • 乐观锁、悲观锁
  • 按粒度:
    • 全局锁、表级锁、页级锁、行级锁
  • 按属性:
    • 共享锁、排它锁
  • 按状态:
    • 意向共享锁、意向排它锁
  • 按算法:
    • 间隙锁、临键锁、记录锁

全局锁、表级锁、页级锁、行级锁

全局锁

  • 对整个数据库实例加锁
  • 应用场景:全库逻辑备份
  • 实现:Flush tables with read lock (FTWRL)

表级锁

  • 当前操作的整张表加锁,MyISAM 与 InnoDB 都支持表级锁定
  • 有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)
  • 实现:lock tables … read/write
  • 注意:需要在低峰期做ddl 变更

页级锁

  • 表级锁速度快,但冲突多,行级冲突少,但速度慢
  • 因此,采取了折衷的页级锁,一次锁定相邻的一组记录
  • BDB 引擎支持页级锁

行级锁

  • 行级锁是粒度最低的锁,发生锁冲突的概率也最低、并发度最高,但是加锁慢、开销大,容易发生死锁现象
  • InnoDB默认为行级锁,行级锁分为共享锁和排他锁
  • 实现:
    • 行级锁并不是直接锁记录,而是锁索引,索引分为主键索引和非主键索引两种
    • 如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引
    • 如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引
    • 在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking

乐观锁和悲观锁

乐观锁和悲观锁并不是锁,而是锁的设计思想

乐观锁

乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测
如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做
  • 应用:适用于读多写少
  • 实现:采用版本号机制或者时间戳机制实现
    • 版本号机制
      • 在表中设计一个版本字段 version
      • 第一次读的时候,会获取 version 字段的取值
      • 对数据进行更新或删除操作时,会执行UPDATE … SET version=version+1 WHERE version=version
      • 如果已经有事务对这条数据进行了更改,修改就不会成功
    • 时间戳机制
      • 与版本号机制一样,也是在更新提交的时候,将当前数据的时间戳和更新之前取得的时间戳进行比较
      • 如果两者一致则更新成功,否则就是版本冲突

悲观锁

对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。
  • 应用:适合写多读少、并发量不大、数据一致性比较高
  • 实现:关闭MySQL的自动提交,set autocommit=0
  • 共享锁和排它锁是悲观锁不同的实现

共享锁、排它锁

共享锁

- 共享锁,又称之为读锁,简称S锁
- 多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改- 当事务A对数据加上读锁后,其他事务只能对该数据加读锁,不能做任何修改操作,也就是不能添加写锁- 只有当事务A上的读锁被释放后,其他事务才能对其添加写锁,从而避免"不可重读"问题的出现
  • 应用:适合于两张表存在关系时的写操作
  • 实现:select …lock in share mode

排它锁

- 排它锁,又称之为写锁,简称X锁
- 当事务对数据加上写锁后,其他事务既不能对该数据添加读锁,也不能对该数据添加写锁,写锁与其他锁都是互斥的注:InnoDB引擎默认update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型
  • 应用:为了解决在修改数据时,不允许其他事务对当前数据进行修改和读取操作,从而可以有效避免”脏读”问题的产生
  • 实现:select …for update

意向共享锁、意向排它锁

- 意向锁是表锁,为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存- 当事务A有行锁时,MySQL会自动为该表添加意向锁,事务B如果想申请整个表的写锁,那么不需要遍历每一行判断是否存在行锁,而直接判断是否存在意向锁,增强性能注:排它/共享锁指的都是表锁, 意向锁不会与行级的共享/排它锁互斥

间隙锁、临键锁、记录锁

记录锁、间隙锁、临键锁都是排它锁

记录锁

- 记录锁是封锁记录,记录锁也叫行锁

间隙锁

- 间隙锁基于非唯一索引,它锁定一段范围内的索引记录
- 使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据

临键锁

- 临键锁,是记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间,是一个左开右闭区间
- 临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效
- 注:InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com