首页 > 数据库 >Mysql锁机制

Mysql锁机制

时间:2024-07-20 17:28:56浏览次数:9  
标签:事务 加锁 Lock 数据库 Locks 死锁 Mysql 机制

MySQL加锁的原因

MySQL加锁的原因主要是为了确保数据库事务的ACID属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

  • 原子性(Atomicity):确保事务中的所有操作要么全部完成,要么全部不完成。加锁可以防止多个事务同时修改同一数据,从而避免部分操作被执行而其他操作未执行的情况。

  • 一致性(Consistency):保证事务的执行将数据库从一个一致的状态转移到另一个一致的状态。加锁可以防止在事务执行过程中,其他事务对数据的修改影响当前事务的执行结果,从而确保数据的一致性。

  • 隔离性(Isolation):虽然隔离性主要是通过事务的隔离级别来实现的,但加锁也是实现隔离性的一种手段。通过加锁,可以防止多个事务并发执行时相互干扰,确保每个事务都像是在独立执行一样。

  • 持久性(Durability):虽然持久性主要与事务日志和数据恢复机制有关,但加锁也间接影响持久性。加锁可以确保在事务提交前,其他事务不能访问到不一致的数据,从而在事务提交后,数据库能够保证数据的持久性。

  • 并发控制:在多用户环境中,多个事务可能同时请求访问相同的数据。加锁可以控制并发访问,防止数据竞争条件(Race Condition)。

  • 数据完整性:加锁机制可以防止违反数据完整性的操作,确保数据库中的数据满足特定的完整性约束。

  • 优化性能:虽然加锁可能会在一定程度上影响性能,但合理的锁策略可以减少磁盘I/O操作,通过锁定必要的资源来优化查询和事务的性能。

  • 避免更新丢失:在多个事务同时修改同一数据时,加锁可以确保只有一个事务能够进行修改,从而避免更新丢失。

  • 顺序控制:在某些操作中,特定的执行顺序是必要的。加锁可以确保事务按照正确的顺序执行,避免因并发执行导致的顺序问题。

MySQL支持多种类型的锁,主要包括:

  • 共享锁(Shared Lock, S Lock):允许多个事务同时读取同一数据,但不会让其他事务获取排他锁(写锁)。适用于SELECT ... LOCK IN SHARE MODE;或SELECT ... FOR SHARE;查询。

  • 排他锁(Exclusive Lock, X Lock):只允许一个事务持有,其他事务无法同时获取任何类型的锁,直到排他锁释放。用于数据修改操作,如SELECT ... FOR UPDATE;、UPDATE ...;或DELETE ...;。

  • 表级锁(Table-level Locks):针对整个表的锁定,包括读锁和写锁。读锁允许多个事务同时读取表,但阻塞写锁;写锁只允许一个事务获取,阻塞其他事务的读写操作。

  • 行级锁(Row-level Locks):InnoDB存储引擎支持行级锁,锁定具体的数据行。行共享锁允许多个事务同时读取一行数据,而行排他锁只允许一个事务持有,用于更新或删除操作。

  • 间隙锁(Gap Locks):一种特殊的锁,用于锁定一个范围,而不是具体的行,防止在这个范围内插入新行,避免幻读。通常由数据库自动添加,无需显式指定。

  • 意向锁(Intention Locks):包括意向共享锁(Intention Shared Lock, IS Lock)和意向排他锁(Intention Exclusive Lock, IX Lock),是表级锁,用于表明事务即将对表中的行加共享锁或排他锁。

  • 临键锁(Next-Key Locks):结合了记录锁和间隙锁,是一个左开右闭的区间。InnoDB默认使用临键锁,可以防止幻读。

  • 插入意向锁(Insert Intention Lock, AI Lock):插入操作时使用,是间隙锁的一种特例,与表级意向锁不同,与其他临键锁和间隙锁冲突,防止幻读。

  • 自增锁(Auto-Increment Lock):一种特殊类型的表锁,用于保证自增列值的唯一性,不遵循两阶段锁协议,锁在插入语句执行结束时释放。

  • 乐观锁和悲观锁:不是具体的锁机制,而是一种锁的应用策略。乐观锁通常基于数据版本(如时间戳或版本号)来避免冲突;悲观锁则依赖数据库的锁机制来保证操作的原子性。

了解这些锁的类型和特点对于解决并发访问中的冲突和死锁问题至关重要。选择合适的锁类型可以提高数据库的并发性能和数据一致性。

MySQL中的锁级别主要分为表级锁和行级锁,同时还有一些特殊的锁类型。以下是详细的锁级别说明:

表级锁(Table-level Locks):

  • 读锁(Read Lock):也称为共享锁(Shared Lock)。允许多个事务同时读取表,但阻塞写锁的获取。适用于读取操作。
  • 写锁(Write Lock):也称为排他锁(Exclusive Lock)。只允许一个事务获取写锁,阻塞其他事务的读锁和写锁获取。适用于更新、删除等写操作。

行级锁(Row-level Locks):

  • 行共享锁(Record Shared Lock, S Lock):允许多个事务同时持有行共享锁,用于读取操作,不阻塞其他事务的读操作,但会阻塞其他事务的行排他锁获取。
  • 行排他锁(Record Exclusive Lock, X Lock):只允许一个事务持有行排他锁,用于更新或删除操作,阻塞其他事务的行共享锁和行排他锁获取。

间隙锁(Gap Locks):

  • 锁定索引记录之间的间隙,防止其他事务在这些间隙中插入新行,从而避免幻读现象。间隙锁通常由数据库自动添加,无需显式指定。

临键锁(Next-Key Locks):

  • 结合了记录锁和间隙锁,是一个左开右闭的区间。用于防止幻读,通常在可重复读(Repeatable Read, RR)隔离级别下使用。

意向锁(Intention Locks):

  • 意向共享锁(Intention Shared Lock, IS Lock):表明事务打算在表的某些行上获取共享锁。
  • 意向排他锁(Intention Exclusive Lock, IX Lock):表明事务打算在表的某些行上获取排他锁。

插入意向锁(Insert Intention Lock, AI Lock):

  • 插入操作时使用,是间隙锁的一种特例。插入意向锁之间不冲突,但与临键锁和间隙锁冲突,防止幻读。

自增锁(Auto-Increment Lock):

  • 用于保证自增列值的唯一性,是一种特殊类型的表锁。自增锁在插入语句执行结束时释放,不遵循两阶段锁协议。

乐观锁和悲观锁:

  • 乐观锁:基于数据版本控制,通常通过时间戳或版本号来实现。乐观锁认为冲突发生的概率较低,通常在事务结束时检查冲突。
  • 悲观锁:依赖数据库的锁机制来保证操作的原子性,通常在事务开始时就获取锁,防止其他事务干扰。

页级锁(Page-level Locks):

  • 页级锁的颗粒度介于行级锁与表级锁之间,主要应用于BDB存储引擎。页级锁的开销和加锁时间介于表锁和行锁之间,也会出现死锁。

通过合理选择和使用这些锁级别,可以有效地控制并发访问,提高数据库的并发性能和数据一致性。

死锁

死锁(Deadlock)是数据库系统中常见的一种现象,它发生在两个或多个事务在执行过程中,因争夺资源而造成的一种相互等待的状态。

在MySQL中,死锁通常由以下原因造成:

  • 资源争夺:当两个或多个事务试图以不同的顺序获得相同的锁时,可能会发生死锁。例如,事务A持有资源1的锁并等待资源2的锁,而事务B持有资源2的锁并等待资源1的锁。

  • 锁的兼容性问题:MySQL中的锁有多种类型,包括行锁、表锁、间隙锁等。不同类型的锁之间可能存在兼容性问题,当多个事务请求不兼容的锁时,可能会导致死锁。

  • 事务的隔离级别:事务的隔离级别越高,锁定的资源就越多,死锁的可能性也就越大。例如,在SERIALIZABLE隔离级别下,MySQL会对涉及的所有数据加锁,增加了死锁的风险。

  • 锁的粒度:锁的粒度越大,锁定的资源就越多,也越容易与其他事务产生冲突。例如,表锁比行锁更容易引发死锁。

  • 事务的执行顺序:如果多个事务以不同的顺序请求相同的资源,也可能导致死锁。事务的执行顺序不当,例如两个事务分别持有对方需要的资源,导致相互等待。

  • 锁的持续时间:长事务持有锁的时间过长,增加了与其他事务冲突的机会,从而增加了死锁的风险。

  • 系统资源限制:当系统资源(如内存或连接数)有限时,事务可能因为等待资源而进入死锁状态。

  • 非规范化的SQL语句:复杂的SQL语句或不恰当的索引使用可能导致数据库锁定更多的资源,增加了死锁的可能性。

  • 锁升级:事务在执行过程中可能需要升级锁的类型(如从共享锁升级到排他锁),如果其他事务已经持有不兼容的锁,可能会导致死锁。

  • 锁请求的顺序:事务请求锁的顺序不一致,可能导致循环等待,形成死锁。

  • 外部因素:网络延迟、系统故障等外部因素也可能导致事务在等待锁的过程中出现死锁。

  • 数据库设计问题:数据库设计不合理,如表结构设计、索引设计不当,可能导致事务更容易发生死锁。

为了避免死锁,可以采取以下措施:

  • 设计合理的数据库访问逻辑,避免不合理的资源访问顺序。
  • 尽量减少锁的粒度,使用行锁代替表锁。
  • 避免长事务,及时提交或回滚事务。
  • 优化SQL语句,减少不必要的锁定。
  • 在应用层面实现死锁检测和重试机制。
  • 当死锁发生时,MySQL通常会通过死锁检测算法来识别,并选择一个事务进行回滚,以解决死锁状态。

标签:事务,加锁,Lock,数据库,Locks,死锁,Mysql,机制
From: https://www.cnblogs.com/OpenSourceSite/p/18313382

相关文章

  • 解决 SpringBoot 应用中 MySQL 时区配置引起的时间不一致问题
    在开发SpringBoot项目时,表中有两个时间字段一个通过Java代码使用newDate()方法获取当前时间再插入数据库另一个是使用MySQL的CURRENT_TIMESTAMP作为默认值实际运行时发现数据库中的这两个时间值不一致,代码插入的时间比数据库自动生成的时间早了8小时,最终发现是y......
  • MySQL数据库 DQL操作
    一、数据库相关概念          1.数据库存储数据的仓库:数据是有组织的进行存储英文:DataBase,简称DB数据库就是将数据存储在硬盘上,可以达到持久化存储的效果2.数据库管理系统:管理数据库的大型软件......
  • 基于Flask + MySQL + PyQt5 +QtChart + HTML + js + CSS 的新冠数据大屏
    项目数据来源covid19_city_20211224.xlsx功能介绍数据清洗、存储数据增晒改查功能数据条件查询柱状图可视化饼状图可视化曲线图可视化雷达图可视化折线图可视化地图可视化使用到的库B端HTMLjsCSSechartsajaxC端PyQt5QtChartsqlalchemyFlaskMySQL项目启动安......
  • 观察者模式实战:Spring Boot中联动更新机制的优雅实现
    引言在许多应用系统中,我们经常需要处理多个表之间的关联更新问题。例如,在教育管理系统中,当学生的基本信息表中的年龄字段发生更改时,我们可能还需要同步更新学生档案表和学生成绩表中的相关信息。本文将通过一个具体的案例,介绍如何在SpringBoot项目中利用观察者模式来优雅地解......
  • 记一个引起MYSQL死锁Deadlock found when trying to get lock; try restarting transac
    一、记一个引起MYSQL死锁Deadlockfoundwhentryingtogetlock;tryrestartingtransaction的例子  今天在尝试MYSQL事务的时候,这种情况总会引起死锁,不知道为什么,我使用的测试MYSQL表的创建SQL如下:CREATETABLE`user`(`id`int(10)unsignedNOTNULLAUTO_INC......
  • 超详细的MySQL基本使用教程(1) 黑马程序员javaweb学习笔记+练习(附带idea新版ui图形化页
    什么是数据库MySQL概述数据模型关系型数据库SQL简介小结DDL-数据库的设计数据库的常见操作选中该语句然后点运行就成功运行了可以直接用图形化界面进行操作跳转到控制台表的常见操作1.创建练习在db01中创建这张表其中comment是鼠标悬停在......
  • 宝塔面板下,如果mysql服务意外停止,如何定时检测并恢复服务
    如果mysql服务因为某些原因意外停止的话,可以通过宝塔面板加一个定时任务,让服务自动恢复,以免影响服务正常运行。脚本代码:ps=`ps-efl|grepmysqld|grep-v$0|grep-vgrep|wc-l`if[$ps-eq0];thenecho-e"\n$(date'+%Y-%m-%d%H:%M:%S')start"/etc/init.d......
  • 0基础学python-18:掌管匹配机制的模块——re
    目录前言使用正则表达式的背景: 元字符 匹配的范围 正则表达式1.importre2.re.match(r"匹配的规则",所要匹配的字符串) 3.匹配一个变量名 4.转义字符的匹配5.分组匹配6.贪婪匹配7.预编译前言        正则表达式(RegularExpression,简称regex或......
  • MongoRepository 操作 AWS DocumentDB时,如何达到与MySql 中有 select … for update
    在MySQL中,SELECT...FORUPDATE用于在事务中对读取的数据行加锁,以防止其他事务同时修改这些行。这种行级锁定机制在关系型数据库中广泛使用,以确保数据一致性。在MongoDB或AWSDocumentDB中,类似的效果可以通过以下方式实现:使用FindandModify操作:MongoDB提供了f......
  • 说一说MySQL中的索引下推
    首先说说索引的分类:按照物理存储结构划分:聚簇索引、非聚簇索引按照索引的数据结构划分:B+树索引、Hash索引、Full-Text索引按照字段属性划分:主键索引、唯一索引、普通索引按照字段个数划分:单一索引、联合索引在MySQl中以InnoDB存储引擎为例,建立的索引默认情况下是B+Tre......