MySQL__锁

简介: MySQL__锁

文章目录

😊 @ 作者:Lion J
`💖 @ 主页:
https://blog.csdn.net/weixin_69252724`
🎉 @ 主题: MySQL__锁)
⏱️ @ 创作时间:2024年04月27日
————————————————

什么是MySQL的锁?

锁是一种常见的并发事务的控制方式。

表锁与行锁有什么区别

  • 表级锁: MySQL 中锁定粒度最大的一种锁,是针对非索引字段加的锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。不过,触发锁冲突的概率最高,高并发下效率极低。表级锁和存储引擎无关,MyISAM 和 InnoDB 引擎都支持表级锁。
  • 行级锁: MySQL 中锁定粒度最小的一种锁,是 针对索引字段加的锁 ,只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。行级锁和存储引擎有关,是在存储引擎层面实现的。

1. 什么叫做针对索引字段加锁?
针对索引字段加锁是指在执行 SQL 操作时,数据库会根据索引来对数据行进行加锁,而不是对整个表进行加锁。这样的锁定方式被称为行级锁,因为它仅锁定正在操作的行,而不是整个表。
2. 如果查询不走索引字段, 那还怎么加锁, 直接加表锁吗?
别说,还真是. 如果不走索引, 那他查询时候不知道给哪一行数据加锁, 就只能给表加锁了. 此时就根据操作语句来看是加什么锁, 看是共享锁还是独占锁. InnoDB存储引擎一般对于普通的查询语句来说都是加共享锁

  • 当查询字段是索引字段时,MySQL 可以直接利用索引进行定位,并且只需要锁定索引对应的行,而不需要锁定整个表或者额外的间隙。这样可以最大程度地减少锁定的范围,提高并发性能,同时确保了事务的隔离性和一致性。
  • 当查询字段不是索引字段时,MySQL 需要进行全表扫描或者范围扫描,无法直接利用索引定位到符合条件的行。在这种情况下,为了保证查询结果的一致性,MySQL 可能会使用表级锁定或者间隙锁,以确保事务之间不会出现干扰或者幻读现象。这会增加锁定的范围,降低并发性能,但能保证数据的完整性。

行级锁使用注意什么?

InnoDB 的行锁是针对索引字段加的锁,表级锁是针对非索引字段加的锁。当我们执行 UPDATE、DELETE 语句时,如果 WHERE条件中字段没有命中唯一索引或者索引失效的话,就会导致扫描全表对表中的所有行记录进行加锁。这个在我们日常工作开发中经常会遇到,一定要多多注意!!!

InnoDB 有哪几类行锁?

  • 记录锁:也被称为记录锁,属于单个行记录上的锁。
  • 间隙锁:锁定一个范围,不包括记录本身。
  • 临键锁:临键锁是查询时InnoDB根据查询的条件而锁定的一个范围,这个范围中包含有间隙锁和记录锁;临键锁=间隙锁+记录锁。
    其设计的目的是为了解决Phantom Problem(幻读);主要是阻塞insert,但由于临键锁中包含有记录锁,因此临键锁所锁定的范围内如果包含有记录,那么也会给这些记录添加记录锁,从而造成阻塞除insert之外的操作;

间隙锁 和 临表锁的使用?

在默认情况下, InnoDB在RR的事务级别下, 使用间隙锁和索引扫描来防止幻读的情况, 在默认的隔离级别 RR下,行锁默认使用的是 Next-Key Lock(临键锁)。
  • 如果操作的索引是唯一索引或主键, 数据存在情况
就会将临键锁降级为记录所只对操作的数据进行加锁, 仅仅是 锁住索引本身,而不是范围。
  • 如果Sql语句的条件判断字段如果为唯一索引,且给不存在的记录加锁时,行锁会优化为间隙锁给前后间隙加锁。例如:

在这里插入图片描述

记录3-8, 已经被事务1锁住了导,导致事务2inset不了

  • 如果Sql语句的条件判断字段如果为非唯一索引, 那么就会给此数据, 以及此数据前后的数据加上间隙锁

在这里插入图片描述
比如查询:

SELECT * FROM cum WHERE age = 6 LOCK IN SHARE MODE,那么id为(1,6],[6,10)的数据会加锁。  
  • 范围查询的Sql语句的条件判断字段如果为唯一索引,会将此行数据和后面的全部间隙加上锁。例如:

比如执行:

SELECT * FROM cum WHERE id >= 10 LOCK IN SHARE MODE,那么会将[10,无穷大)加锁。

注意:间隙锁唯一目的是防止其他事务将数据插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。

对于行锁(记录锁, 间隙锁, 临表锁)都是区分一个共享锁和排他锁的

共享锁与排他锁?

不论是表级锁还是行级锁,都存在共享锁(S 锁)和排他锁(X 锁)这两类:

  • 共享锁(S 锁):又称读锁,事务在读取记录的时候获取共享锁,允许多个事务同时获取。
  • 排他锁(X 锁):又称写锁/独占锁,事务在修改记录的时候获取排他锁,不允许多个事务同时获取。如果一个记录已经被加了排他锁,那其他事务不能再对这条事务加任何类型的锁。

排他锁与任何的锁都不兼容,共享锁仅和共享锁兼容。

在这里插入图片描述
由于 MVCC 的存在,对于一般的 SELECT 语句,InnoDB 不会加任何锁, 都是使用 一致性非锁定读的方式来加共享锁方式
不过, 你可以通过以下语句显式加共享锁或排他锁。

 # 共享锁
SELECT ... FOR SHARE;
# 排他锁
SELECT ... FOR UPDATE;

什么是意向锁?

如果需要用到表锁的话,如何判断表中的记录没有行锁呢,一行一行遍历肯定是不行,性能太差。
我们需要用到一个叫做意向锁的东东来快速判断是否可以对某个表使用表锁。

意向锁是表级锁,共有两种:

  • 意向共享锁 :事务有意向对表中的某些记录加共享锁(S 锁),加共享锁前必须先取得该表的 意向共享锁。
  • 意向排他锁:事务有意向对表中的某些记录加排他锁(X 锁),加排他锁之前必须先取得该表的意向排他锁。

意向锁是由数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享/排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。

这种机制可以帮助快速判断表中的记录是否被锁定,从而优化锁定的策略,减少不必要的等待时间和资源浪费。

当前读与快照读区别?

快照读(一致性非锁定读)

就是单纯的 SELECT 语句,但不包括下面这两类 SELECT 语句:
# 排他
SELECT ... FOR UPDATE
# 共享锁  
SELECT ... LOCK IN SHARE MODE;
# 共享锁 
SELECT ... FOR SHARE;

快照即记录的历史版本,每行记录可能存在多个历史版本(这是数据库的多版本技术)。
快照读的情况下,如果读取的记录正在执行 UPDATE/DELETE 操作,读取操作不会因此去等待记录上 X 锁的释放,而是会去读取行的一个快照
只有在事务隔离级别 RC(读取已提交) 和 RR(可重读)下,InnoDB 才会使用一致性非锁定读:

  • 在 RC 级别下,对于快照数据,一致性非锁定读总是读取被锁定行的最新一份快照数据。这也就是为什么会导致不可重复读的原因
  • 在 RR 级别下,对于快照数据,一致性非锁定读总是读取本事务开始时的行数据版本。快照读比较适合对于数据一致性要求不是特别高且追求极致性能的业务场景。

当前读 (一致性锁定读)

就是给行记录加 X 锁或 S 锁。

当前读的常用语句如下

# 加一个X锁
SELECT...FOR UPDATE
# 加一个S锁
SELECT...LOCK IN SHARE MODE
# 加一个S锁
SELECT...FOR SHARE
# 加一个X锁
INSERT...
UPDATE...
DELETE...
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
SQL AliSQL 关系型数据库
MYSQL的全局锁和表锁
本文介绍了MySQL中的锁机制,包括全局锁、表级锁及其应用场景。全局锁通过`Flush tables with read lock (FTWRL)`实现,主要用于全库逻辑备份,但会阻塞更新和结构变更操作。表级锁分为显式表锁(`lock tables`)和元数据锁(MDL),前者用于控制并发访问,后者自动加锁以确保读写正确性。文章还探讨了如何安全地为小表添加字段,建议通过设置DDL等待时间或使用MariaDB/AliSQL的NOWAIT/WAIT功能避免业务阻塞。这些方法有助于在高并发场景下优化数据库性能与安全性。
361 0
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
383 3
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
536 25
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(06)MySQL有几种锁?| 别背答案,现场演示一下
本文详细解析了MySQL InnoDB存储引擎的锁机制,涵盖读锁、写锁、意向锁、记录锁、间隙锁和临键锁等8种锁类型。重点探讨了不同锁类型的加锁与释放方式,以及事务并发场景下的实战验证。通过具体示例,展示了在不同情况下锁的行为及其对事务的影响。文章还特别强调了锁的作用范围主要是索引,并解释了锁如何影响数据的读写操作。最后总结了并发事务中加锁规则,帮助读者深入理解MySQL的锁机制。
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
854 1
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
1613 2
|
监控 关系型数据库 MySQL
MySQL锁机制与解决死锁问题
MySQL锁机制与解决死锁问题
737 5
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
745 1
|
关系型数据库 MySQL 数据库
Mysql的锁
本文介绍了MySQL中表级锁和行级锁的区别,其中MyISAM仅支持表级锁,而InnoDB支持表级锁和行级锁,默认为行级锁。表级锁锁定整个表,实现简单,资源消耗少,但并发度低;行级锁仅锁定相关记录,减少冲突,提高并发度,但加锁开销大。此外,还介绍了共享锁和排他锁的概念及意向锁的作用。
236 1
|
SQL 存储 关系型数据库
"MySQL增列必锁表?揭秘InnoDB在线DDL,让你的数据库操作飞一般,性能无忧!"
【8月更文挑战第11天】在数据库领域,MySQL凭借其稳定高效的表现深受开发者喜爱。对于是否会在给数据表添加列时锁表的问题,MySQL的行为受版本、存储引擎等因素影响。从5.6版起,InnoDB支持在线DDL,可在改动表结构时保持表的可访问性,避免长时间锁表。而MyISAM等则需锁表完成操作。例如,在使用InnoDB的表上运行`ALTER TABLE users ADD COLUMN email VARCHAR(255);`时,通常不会完全锁表。虽然在线DDL提高了灵活性,但复杂操作或大表变更仍可能暂时影响性能。因此,进行结构变更前应评估其影响并择机执行。
398 6

推荐镜像

更多