mysql-锁

一 什么是锁

锁机制用于管理对公共资源的并发访问。

1.1 优点

数据是一种供多用户共享的资源,保证数据并发访问的一致性,有效性

1.2 缺点

加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否已解除、释放锁等 ,都会增加系统的开销。

1.3 两段锁

数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)

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


    mysql-锁_第1张图片
    截屏2021-04-01 10.45.38.png

    这种方式虽然无法避免死锁,但是两段锁协议可以保证事务的并发调度是串行化(串行化很重要,尤其是在数据恢复和备份的时候)的。

1.4 隔离级别

在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。我们的数据库锁,也是为了构建这些隔离级别存在的。


mysql-锁_第2张图片
截屏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-锁_第3张图片
截屏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 索引 行锁 否则 表锁

你可能感兴趣的:(mysql-锁)