mysql-锁

一 什么是锁 锁机制用于管理对公共资源的并发访问。
1.1 优点 数据是一种供多用户共享的资源,保证数据并发访问的一致性,有效性
1.2 缺点 【mysql-锁】加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否已解除、释放锁等 ,都会增加系统的开销。
1.3 两段锁 数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)

  • 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁(共享锁,其它事务可以继续加共享锁,但不能加排它锁),在进行写操作之前要申请并获得X锁(排它锁,其它事务不能再获得任何锁)。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
  • 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。

    mysql-锁
    文章图片
    截屏2021-04-01 10.45.38.png
    这种方式虽然无法避免死锁,但是两段锁协议可以保证事务的并发调度是串行化(串行化很重要,尤其是在数据恢复和备份的时候)的。
1.4 隔离级别 在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。我们的数据库锁,也是为了构建这些隔离级别存在的。

mysql-锁
文章图片
截屏2021-04-01 10.51.42.png
  • 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
  • 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
  • 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
  • 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
查看事务的隔离级别(注意:polardb用的是READ-COMMITTED)
select @@global.transaction_isolation;
select @@global.tx_isolation;
二 锁分类 2.1表锁 2.1.1 特点
由MySQL SQL layer层实现,表锁是对整张表加锁,开销小,加锁快,无死锁,锁粒度大,发送锁冲突概率极高,并发性极低(myisam引擎是表锁,并发读没有问题,并发插入性能会差一些)
2.1.2 分类
1 表锁
2 元数据锁(meta data lock, MDL)
在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结
构变更操作的时候,加 MDL 写锁。
1、session1: begin; --开启事务 select * from mylock; --加MDL读锁 2、session2: alter table mylock add f int; -- 修改阻塞 3、session1:commit; --提交事务 或者 rollback 释放读锁 4、session2:Query OK, 0 rows affected (38.67 sec) --修改完成 Records: 0 Duplicates: 0 Warnings: 0

MySQL 实现的表级锁定的争用状态变量

mysql-锁
文章图片
截屏2021-03-31 15.43.56.png
  • table_locks_immediate:产生表级锁定的次数(包括意向锁 ,可能很大,一般不看这个);
  • table_locks_waited:出现表级锁定争用而发生等待的次数;、
show open tables:
查看哪个表被锁住 in_use
2.2页锁 加锁时间和锁粒度介于表锁和行锁之间,会出现死锁,并发处理能力一般
2.3行锁 2.3.1 分类
InnoDB存储引擎实现, 行锁很重要本章重点研究行锁
InnoDB的行级锁,按照锁定范围来说,分为三种:
记录锁(Record Locks):锁定索引中一条记录。 主键指定 where id=3
间隙锁(Gap Locks): 锁定记录前、记录中、记录后的行 RR隔离级 (可重复读)-- MySQL默认隔离级
Next-Key 锁: 记录锁 + 间隙锁
按照功能来说,分为两种:
共享读锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他写锁(X):允许获得排他写锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁(不是读)和排他写锁。
2.3.2 示例
对表执行新增、修改、删除,或者select ...for update时,会触发数据库的锁机制
InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过
索引条件检索的数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
where 索引 行锁 否则 表锁

    推荐阅读