MySQL中的锁

发布于:2025-06-04 ⋅ 阅读:(23) ⋅ 点赞:(0)

MySQL中有哪些锁?

全局锁(FTWRL)

含义:Flush Table with Read Lock的缩写,它会锁定整个数据库实例,让所有表都处于只读状态。

使用全局锁,要执行的命令:

flush tables with read lock

之后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞:

对数据增删改操作,比如insert,update,delete等语句;

对表结构的更改操作,比如alter table,drop table等语句。

insert into student(id,name,sex,birthday,class)values(110,'zz','男','1977-10-11','95034');

如果释放全局锁,则要执行这条命令:

unlock tables

应用场景:

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

缺点

加上全局锁后,整个库都是只读状态,备份耗时常,业务无法更新数据,导致业务停滞。

替代方式

支持可重复读隔离级别的引擎(如InnoDB),用mysqldump --single - transaction开启事务备份;不支持事务的引擎(如MylSAM)只能用全局锁。

数据库备份时,想要替代全局锁,关键在于利用事务特性和多版本并发控制(MVCC);

  • 原理基础:在可重复读隔离级别下,事务开启时会生成一个Read View(数据快照)。之后事务执行期间,都依据这个Read VIew去判断数据的可见性。即使其他事务在此期间对数据进行了修改并提交,基于这个Read View读取的数据依旧是事务开启时的状态,保证了数据的一致性。这就是MVCC的作用机制。
  • 操作方法:用mysqldump --single-transaction备份时,InnoDB 通过事务快照(可重复读隔离级别 + MVCC)固定数据版本,备份期间业务新操作生成独立版本,两者互不干扰,所以不用锁也能保证备份数据一致;MyISAM 不支持事务和 MVCC,只能用全局锁强制冻结数据。

表级锁

MySQL里面表级别的锁有这几种:

  • 表锁:
  • 元数据锁(MDL);
  • 意向锁;
  • AUTO-INC锁;

表锁

使用方法,对学生表加表锁,使用以下命令:

#对学生表加读锁
lock tables student read;

#对学生表加写锁
lock tables student write;
#解开当前会话所有锁
unlock tables;
#查操作
select * from student;
#插入操作
insert into student(id,name,sex,birthday,class)values(111,'gzz','男','1977-10-11','95035');

加完读锁之后执行插入操作会造成以下现象(当前会话)

lock tables student read;(给student表加读锁 )

  • 当前会话限制:只能对student表执行读操作(如SELECT ) ,不能执行写操作(如INSERT、UPDATE、DELETE ) ,也不能对其他表进行读写操作。
  • 其他会话限制:能对student表执行读操作,但不能执行写操作,写操作会被阻塞,直到当前会话释放读锁 。

lock tables student write;(给student表加写锁 )

  • 当前会话权限:可对student表进行读和写操作 。
  • 其他会话限制:不能对student表进行读或写操作,读写操作都会被阻塞,直至写锁被释放 。 两种锁释放均用 unlock tables; 语句 ,且会话断开时锁也会自动释放。

释放表锁,使用unlock tables命令,则会释放当前会话的所有表锁;

会话退出后,也会释放所有表锁。

在更细粒度锁出现前,表锁是处理并发常用手段。InnoDB 引擎场景下表锁弊端:InnoDB 引擎若使用表锁,因其锁粒度大(锁定整张表 ),会影响并发性能。比如多个事务要操作同表不同行数据,表锁会让其他事务等待,降低并发处理能力。InnoDB 优势:实现行级锁,锁粒度更细。仅锁定相关行数据,不同事务可同时操作同表不同行,极大提升数据库并发处理能力。

元数据锁

  • 加锁机制:操作数据库表时自动添加。执行 CRUD 操作加读锁;表结构变更时加写锁。
  • 功能作用:防止在对表进行操作期间,其他线程对表结构进行变更,保证数据操作的一致性。
  • 阻塞规则:读锁期间,阻止其他线程申请写锁;写锁期间,阻止其他线程申请读锁。
  • 释放时机:事务提交后释放,事务执行过程中一直持有。
  • 长事务影响:长事务持有读锁不提交,会阻碍表结构变更的写锁申请,进而阻塞后续 CRUD 操作,可能导致数据库线程资源紧张。
  • 应对措施:表结构变更前,排查并处理长事务。

意向锁

InnoDB 会在有人加「行锁」之前,先在表级别标记一个「我要锁某些行」的意向锁。这样当你想给整个表加锁时,只需看表上有没有这个标记,就能快速知道「表里面有没有行被锁住」,无需逐行检查。

  • 使用InnoDB引擎的表里对某些记录加上共享锁之前,需要先在表级别加上一个意向共享锁;
  • 使用InnoDB引擎的表里对某些记录加上独占锁之前,需要先在表级别加上一个意向独占锁;
与 select 关系

普通 select 靠 MVCC 实现一致性读,不加行级锁 。但 select ... lock in share mode 会先加意向共享锁,再给记录加共享锁;select ... for update 先加意向独占锁,再给记录加独占锁 。

冲突规则

意向共享锁和意向独占锁是表级锁 ,和行级共享锁、独占锁不冲突 ,意向锁之间也不冲突 ,只和共享表锁(lock tables ... read )、独占表锁(lock tables ... write )冲突 。表锁和行锁满足 “读读共享、读写互斥、写写互斥” 。

作用原理

没意向锁时,加独占表锁得遍历全表看有无记录加独占锁,效率低 。有了意向锁,加独占锁前先加意向独占锁,加独占表锁时,查看有无意向独占锁,就能快速判断表里记录是否被加锁 。

意向锁是表级的「占位符」,用来快速告诉你表中是否有行已被锁定,避免全表扫描。

AUTO-INC锁

表里的主键通常会设置为自增的,这是通过对主键字段声明AUTO-INCREMENT属性实现。

之后可以在插入数据时,可以不指定主键的值,数据库会自动给主键赋值递增的值,这主要时通过AUTO-INC锁实现的。

用途:用于实现数据库表主键等字段自增 。插入数据时,数据库利用它自动给被AUTO_INCREMENT 修饰字段赋递增的值 。

锁机制:是特殊表锁 ,执行完插入语句立即释放 ,非事务提交后释放 。持有锁时,阻塞其他事务插入 ,确保自增值连续递增 ,但影响大量数据插入性能 。

改进:MySQL 5.1.22 起,InnoDB 引入轻量级锁 。通过innodb_autoinc_lock_mode 控制 :

= 0 ,用 AUTO - INC 锁,语句执行完释放 。

= 1 ,普通insert 申请后即释放,insert ... select 等批量插入语句结束后释放 。

= 2 ,用轻量级锁,申请自增主键后就释放 ,性能高,但搭配statement 格式binlog 用于主从复制时会有数据不一致问题 。

行级锁

InnoDB引擎是支持行级锁的,而MylSAM引擎并不支持行级锁。

在查询时对记录加行锁,可以使用这下面两个方式,这种查询会加锁的语句称为锁定读。

#对读取的记录加共享锁
select ... lock in share mode

#对读取的记录加独占占领
select ... for update

上面这两条语句必须在一个事务中,因为当事务提交了,所就会被释放,所以在使用这两条语句的时候,要加上begin、start transaction或者set autocommit = 0。

共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。

行级锁的主要有三类:

  • Record Lock,记录锁,也就是仅仅把一条记录锁上;
  • Grap Lock,间隙锁,锁定一个范围,但是不包含记录本身;
  • Next-Key Lock:Record Lock+ Grap Lock的组合,锁定一个范围,并且锁定记录本身。

Record Lock(记录锁)

含义:针对数据库表中某一条具体记录进行加锁。例如在含有主键 id 的表中,使用 SELECT * FROM table WHERE id = 1 FOR UPDATE; 语句,就会对 id 为 1 的这条记录添加记录锁,其他事务不能对该记录执行修改、删除等操作 。
作用:保障单条记录在被操作过程中的完整性与一致性,有效避免因多个事务并发修改同一条记录而产生的数据问题 。

Gap Lock(间隙锁)

含义:锁定的是数据库表中记录之间的间隙范围,并不包含记录本身。比如表中存在记录 id 为 13 ,那么 1 和 3 之间的间隙就能够被间隙锁锁定。当对这个间隙加锁后,若有插入 id 为 2 记录的操作,会因涉及到已锁定的间隙范围而被阻塞 。
作用:主要用于阻止在锁定的间隙范围内插入新记录,防止因新记录的插入导致数据逻辑出现混乱,是应对幻读问题的常用手段 。

Next - Key Lock(临键锁)

含义:它是记录锁与间隙锁的组合形式。不仅会锁定某条特定记录,还会将该记录前后的间隙范围一并锁定。举例来说,若对 id 为 3 的记录添加临键锁,那么 id 为 3 的这条记录本身以及其前后的间隙范围都会被锁定,新记录无法插入到这个被锁定的范围之内 。
作用:在确保单条记录操作安全性的同时,也能防止因在相关范围内插入新记录而引发的数据不一致问题,是 InnoDB 默认的行锁算法,在防止幻读方面效果显著 。


网站公告

今日签到

点亮在社区的每一天
去签到