【MySQL 进阶之路】锁详解

MySQL 锁详解

1. 锁的基本概念

锁在数据库中是用来保证数据一致性防止并发冲突的一种机制。MySQL 中的锁可以分为不同的类型和粒度,每种锁都有特定的使用场景和特点。了解锁的类型、作用以及如何避免锁带来的问题是提升数据库性能和避免数据冲突的关键。

2. 锁的分类

根据不同的标准,MySQL 锁可以分为以下几类:


2.1 按照锁粒度分类
表级锁(Table Lock)
  • 表级锁是加在整个表上的锁,意味着当一个事务获得表锁后,其他事务不能访问这个表的数据,直到当前事务释放锁。表级锁的优点是简单粗暴,但粒度大,容易导致锁竞争
  • 表级锁的类型
    • S锁(共享锁):允许事务读取数据,但不允许修改。多个事务可以持有共享锁,进行读取操作。
    • X锁(排他锁):禁止其他事务读取或修改该数据。只有持有该锁的事务可以修改数据,其他事务无法读取或修改。
    • 使用场景:当表的读写频繁,且数据不需要高并发时,表级锁较为合适。
行级锁(Row Lock)
  • 行级锁是加在单行数据上的锁,通常通过 索引 实现。行级锁比表级锁粒度更细,因此并发能力更强。

  • 行级锁的分类

    1. 行锁(Row Lock):行锁是锁定数据库表中的特定行数据,确保一个事务修改某一行数据时,其他事务不能修改同一行,避免不可重复读现象。行锁最小粒度,适用于高并发操作。
    2. 间隙锁(Gap Lock):间隙锁并不锁定具体的行,而是锁定行之间的"空隙",即某两个行数据之间的位置。这是为了防止其他事务插入数据到该位置,从而避免幻读现象。
    3. 临键锁(Next-Key Lock):临键锁是行锁间隙锁的组合体。它既锁定了特定行的数据,又锁定了该行之前或之后的间隙,用来防止其他事务在相同范围内插入或修改数据。临键锁主要用于避免幻读问题。

    简单来说:

    • 行锁:锁定特定行。
    • 间隙锁:锁定行与行之间的空隙。
    • 临键锁:锁定行及其周围的间隙,防止插入新数据。
  • 行级锁的特点

    • 在高并发的环境中,行级锁能够有效减少锁竞争,提高并发性能。
    • 但是,行级锁会增加锁管理的开销,因此适合那些频繁进行读取和更新操作的表。
    • 使用场景:需要高并发和高响应性能的系统,如电商平台的库存管理、银行转账等。
页级锁(Page Lock)
  • 页级锁是针对数据页(通常一个数据页大小为 16KB)进行加锁,这种方式介于表级锁和行级锁之间。MySQL 中的 MyISAM 存储引擎使用的是页级锁。
  • 这种锁方式适用于数据量大、读写频繁,但不需要对单行数据进行细粒度控制的场景。
    • 使用场景:当表的行数很大,但操作并不依赖于精确的行级锁时,页级锁可能是一个合适的选择。

2.2 按照锁的类型分类
意向锁(Intention Lock)

用于表示事务希望对某些行或表加锁的意图,帮助协调表级锁和行级锁之间的冲突。

  • IS锁(意向共享锁):表示事务将要对某些行加共享锁。

  • IX锁(意向排他锁):表示事务将要对某些行加排他锁。

  • 使用场景:意向锁避免了表级锁和行级锁之间的冲突,是InnoDB引擎内部的一种协调机制。

元数据锁(Metadata Lock, MDL)
  • 元数据锁用于保护数据库对象(如表、索引等)的结构变更操作,以防止在执行 DDL 操作时,其他事务进行并发的 DML 操作(例如读取或更新数据)。
  • 例如,执行 ALTER TABLE 时,MySQL 会对表加上 MDL 锁,防止其他事务对表进行读写操作。
  • 使用场景:在进行数据库表结构变更时,使用 MDL 锁确保表的操作不被其他事务打断。

2.3 按照锁的态度分类
悲观锁(Pessimistic Lock)
  • 假设并发冲突一定会发生,因此每次访问数据时都加锁,保证数据的安全性。这种方式比较适合高并发环境,避免了数据冲突的发生。
  • 悲观锁的实现:通常通过 共享锁(S锁)排他锁(X锁) 实现。
    • S锁:允许多个事务读取数据,但不允许修改。
    • X锁:限制其他事务对该数据的任何操作,只有持锁事务可以修改。
    • 使用场景:银行转账、票务系统等,对数据一致性要求非常高,且并发较为激烈的场景。
乐观锁(Optimistic Lock)
  • 假设并发冲突不会发生,因此在读取数据时不加锁,而是通过某种机制(如版本号、时间戳)在提交时检查数据是否被修改过,若没有修改则提交,若发生修改则回滚。

  • 乐观锁的实现:通过在数据表中添加版本号(version)或时间戳字段,在事务提交时,检查版本号是否一致。

    • 版本号机制:每次更新数据时,版本号加1;提交时,检查版本号是否与读取时一致。
    • 使用场景:适用于冲突较少的系统,读多写少的场景,如博客系统中的评论区、商品的库存管理等。

2.4 其他加锁方式
自增锁(Auto-increment Lock)
  • MySQL 中自增列(AUTO_INCREMENT)是全局共享资源,多个事务可能会在同一时刻尝试修改自增字段。为了避免这种并发操作造成的冲突,MySQL 使用 自增锁 来确保生成自增值时的唯一性和顺序性。
    • 使用场景:自增列通常用于主键字段,特别是在需要高并发插入的场景下,自增锁能保证自增字段值的连续性和唯一性。
显示锁(Explicit Lock)
  • 由用户手动设置的锁,通常使用 LOCK TABLESUNLOCK TABLES 命令来加锁和解锁表。

  • 例如: sql LOCK TABLES my_table WRITE;

隐式锁(Implicit Lock)

  • 由数据库自动加锁,不需要用户显式操作。例如,当一个事务对表进行 SELECT … FOR UPDATEINSERT 操作时,数据库会自动加锁。

全局锁(Global Lock)
在这里插入图片描述

  • 全局锁会锁住整个数据库或所有数据库的操作,通常用于 备份恢复 时的操作。例如:

  • FLUSH TABLES WITH READ LOCK:该命令会锁住所有表,确保备份时数据的一致性。

  • UNLOCK TABLES:释放全局锁


3. 锁的策略与优化

合理选择锁的粒度和类型对于数据库性能至关重要。以下是一些优化建议:

3.1 锁粒度选择
  • 表级锁适合低并发、事务较少的应用场景,但会影响其他事务对表的访问。
  • 行级锁适合高并发、频繁读写的场景,能够最大程度地避免锁竞争。
  • 页级锁则适合一些数据量较大、并发要求不是特别高的场景。
3.2 避免死锁
  • 死锁是指两个或多个事务在执行过程中相互等待对方释放资源,导致所有事务无法继续执行。
  • 为了避免死锁,应该遵循以下几个原则:
    1. 统一的锁访问顺序:所有事务按照相同的顺序请求锁,避免交叉。
    2. 减少锁的持有时间:尽量缩短事务执行时间,及时释放锁。
    3. 适当使用事务隔离级别:选择合适的隔离级别,例如使用 READ COMMITTED 可以避免部分死锁问题。
3.3 使用合适的事务隔离级别
  • READ COMMITTED:每次读取时都会加共享锁,避免读取未提交的数据(脏读)。
  • REPEATABLE READ:保证事务读取的一致性,避免幻读。
  • SERIALIZABLE:最高级别的隔离,事务会按顺序执行,避免并发问题,但性能最差。

4. 总结

锁类型锁粒度并发性锁定范围事务隔离性描述
行锁最细粒度(锁单行)高并发锁定特定数据行提供较高的事务隔离性,通常支持 SerializableRepeatable Read锁定表中的单行数据,允许并发事务操作不同的行,但会增加锁竞争
间隙锁锁行之间的间隙(范围)中等并发锁定两个索引值之间的“空隙”避免幻读现象,保证事务一致性。对插入操作有较强的隔离性。锁定一个范围(空隙),防止其他事务在该间隙插入数据,从而避免幻读。
临键锁锁定键值范围中等并发锁定特定的键值范围提供类似于行锁的隔离性,但范围较大,常见于范围查询或索引范围的保护。锁定某个键值范围,用于防止其他事务在此范围内修改数据,通常用于范围查询的场景。
表锁粗粒度(锁整表)低并发锁定整个表提供较低的隔离性,通常用于不需要高并发的全表操作。锁定整个表,所有事务都无法访问该表的数据,适用于全表操作如备份、清理等。
意向锁由行锁或表锁组合成的锁粒度不直接影响并发性锁定事务意图的粒度不直接影响事务隔离性,主要用于协调多粒度锁。用于表示事务希望在更低粒度上加锁的意图,确保高粒度锁和细粒度锁不冲突。

MySQL 提供了丰富的锁机制,帮助我们在不同的并发环境下保护数据的一致性和完整性。合理选择锁的类型和粒度,能够有效提高系统的性能并降低冲突的概率。理解每种锁的特点和使用场景,能够帮助我们在数据库设计和优化时做出更加明智的决策。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/63228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qsort函数用法,以及模拟实现

函数定义 基于快速排列的一个函数,它的四个参数的含义: 1、void* base,是排序开始的地址 2、size_t num 想要排列的个数 3、size_t size 排列对象,一个占多少空间(字节) 4、int (*comper)(void*,voi…

CentOS7虚拟机 网络适配器 NAT模式和桥接模式区别

一、环境介绍 宿主机:Windows电脑 虚拟机:VMware下的CentOS7 局域网:路由器下的各真实主机组成的网络 内部局域网:宿主机构建的一个内部网路 二、NAT和桥接网络链接模式区别 NAT模式:相当于宿主机构建一个内部局域网&a…

全面解析DApp开发中的智能合约设计

在DApp的开发过程中,智能合约的设计起到了至关重要的作用。智能合约是运行在区块链上的程序,负责处理和执行DApp中的逻辑、交易和数据存储。下面我们将深入探讨智能合约的设计原则、挑战和优化方法,帮助开发者掌握如何设计高效、安全的智能合…

锐捷Web认证

文章目录 Web认证二代 Web 认证配置 🏡作者主页:点击! 🤖Datacom专栏:点击! ⏰️创作时间:2024年12月6日11点40分 Web认证 Portal 认证、Web认证 Web认证的介绍 Web 认证使用浏览器进行身份验…

详解日志格式配置:XML 与 Spring Boot 配置文件格式

详解日志格式配置:XML 与 Spring Boot 配置文件格式 日志是现代应用程序中不可或缺的一部分,通过定制化日志格式和颜色,开发人员可以更方便地调试和监控应用。本文将深入讲解如何在 XML 配置文件 和 Spring Boot 配置文件 中设置日志格式&am…

KernelShark在ubuntu24.04.01的编译

KernelShark在ubuntu24.04.01的编译 写在前面具体过程装ubuntu24.04.01安装depends下载代码如何编译cmake 输出make 输出 如何安装 初步启动Add the User to the perf Group 简单的使用trace-cmd抓包 来看我的文章,必有所得。 平凡中,总有我帮您踩过的坑…

Ionic 8.4 简介

Ionic 是一个用于开发混合移动应用、渐进式Web应用(PWA)以及桌面应用的开源框架。它结合了 Angular、React 或 Vue.js 等现代前端框架与 Cordova/PhoneGap 的力量,允许开发者使用 Web 技术(HTML, CSS, JavaScript)构建…

浏览器数据存储方法深度剖析:LocalStorage、IndexedDB、Cookies、OPFS 与 WASM - SQLite

在当今的 Web 开发领域,选择合适的浏览器数据存储方法对于构建高效、功能丰富的应用程序至关重要。随着 Web 应用的不断演进,从早期的静态 HTML 页面到如今复杂的单页应用和本地优先应用,数据存储需求也日益多样化。本文将深入探讨 LocalStor…

要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出

要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出 要使用 OpenResty 创建一个接口,返回客户端的 IP 地址,并以 JSON 格式输出方案一解决方案(openresty使用cjson)说明:使…

解决Unity编辑器Inspector视图中文注释乱码

1.问题介绍 新创建一个脚本,用VS打开编辑,增加一行中文注释保存,在Unity中找到该脚本并选中,Inspector视图中预览的显示内容,该中文注释显示为乱码,如下图所示: 2.图示解决步骤 按上述步骤操作…

【AIGC半月报】AIGC大模型启元:2024.12(上)

【AIGC半月报】AIGC大模型启元:2024.12(上) (1)OpenAI-12日发布会(持续更新中........)Day01-12.06:o1满血版上线(已发布)Day02-12.07:强化微调&a…

JDK21新特性

目录 虚拟线程(JEP 444): 顺序集合(JEP 431): 字符串模板(JEP 430): 模式匹配的增强(JEP 440、441以及443): 结构化并发和作用域值…

【linux 查看网卡设备信息命令记录】

查看设备信息命令 查看网卡芯片相关platform类型网卡(gmac网卡为例)PCI网卡(rtl8125为例) 查看网卡芯片相关 platform类型网卡(gmac网卡为例) gmac 属于CPU资源的一部分,属于平台设备。下面以FT2004 的CPU为例,自带GMAC0和GMAC1。 1、通过平台设备查看…

字节码

字节码 1、字节码文件概述 1.1、字节码文件是跨平台的吗? ​ Java 虚拟机不和包括 Java 在内的任何语言绑定,它只与“Class 文件”这种特定的二进制文件格式所关联。 ​ 无论使用何种语言进行软件开发,只要能将源文件编译为正确的Class文件…

nodejs后端项目使用pm2部署

nodejs后端项目使用pm2部署 安装pm2 npm install pm2 -g查看版本号 pm2 --version启动项目 pm2 start app.js# 设置别名 pm2 start app.js --name demo停止项目 pm2 stop [AppName] pm2 stop [ID]# 停止所有项目 pm2 stop all重启项目 pm2 restart [AppName] pm2 re…

运算符与表达式——培训记录

0.引入 1.计算机通过计算去解决问题的。 Q:这个计算到底是按照什么方式去进行计算的? A:通过各种运算符去进行计算。 --->运算符与表达式 1.运算符 1.运算符:用来进行某种运算的符号。如: - * / % 2.几目运算符&#xf…

排查bug的通用思路

⭐️前言⭐️ APP点击某个按钮没有反应/PC端执行某个操作后,响应较慢,通用的问题排查方法: 从多个角度来排查问题 🍉欢迎点赞 👍 收藏 ⭐留言评论 🍉博主将持续更新学习记录收获,友友们有任何问题可以在评…

AI 建站:Durable

网址:https://app.durable.co 步骤 1) 登录 2)点击创建新业务 3)填写信息后,点击创建 4)进入业务 5)生成网站 6)生成完成后不满意的话可以自己调整 7)点击保存 8)发布 …

部署kafka并通过python操作

目录 一、安装JDK1.81、检查服务器是否已安装JDK2、若已安装JDK,进行卸载3、更新yum源4、搜索JDK1.8安装包5、安装JDK1.86、查看是否安装成功7、配置环境变量 二、安装Kafka1、下载并解压kafka部署包至/usr/local/目录2、修改server.properties3、修改/etc/profile4…

【Linux】 进程池 一主多从 管道通信

目录 1.代码介绍 2.channel 类 3.进程池类编写 4.主函数及其他 5. 源码 1.代码介绍 本文代码采用一主多从式(一个主进程(master)多个子进程(worker))通过管道进行通信,实现主进程分发任务&…