MySQL的意向共享锁、意向排它锁和死锁

yizhihongxing

MySQL意向锁和死锁攻略

意向锁

MySQL中有两种意向锁:意向共享锁(IS)和意向排它锁(IX)。当一个事务请求一张表的排它锁或者共享锁时,MySQL会先判断表是否已经被其它事务加了锁。若没有加锁,则直接获取锁;若被加锁,则会判断待加的锁类型。若是要请求共享锁,则会在表上加意向共享锁(IS);若是要请求排它锁,则会在表上加意向排它锁(IX)。意向锁只是一个标记而已,并不真正锁住了什么,其目的在于表示一个事务准备加一个类型的锁。

例如,事务A要获取一张表的共享锁(读锁),而该表当前未被锁住。那么,MySQL会在该表上加意向共享锁(IS)。之后,事务B也要获取该表的共享锁,MySQL会发现该表已经有了意向共享锁(IS),那么MySQL就知道有其它事务在该表上存在对该表的读操作,并不需要等待其它事务释放锁。

从意向锁的功能可以看出,意向锁是针对表级别的锁,而不是针对行级别的锁。

死锁

假设有两个事务T1和T2,T1在等待T2释放的锁,而同时T2也在等待T1释放的锁,那么这两个事务就产生了死锁。此时,系统一般会强制回滚其中一个事务,解除死锁的情况。

如下面所示的示例:

  • 执行以下SQL:
SET SESSION autocommit=0; --关闭自动提交
BEGIN; --开启一个事务
SELECT * FROM table1 WHERE id = 10 FOR UPDATE; --对表进行排他锁

上述SQL语句会对表table1中id等于10的一行进行排它锁(FOR UPDATE)。此时,该行的锁定时间会一直持续到当前事务提交或回滚。

  • 现在开启另外一个事务,并尝试获取该行的排它锁:
SET SESSION autocommit=0; --关闭自动提交
BEGIN; --开启一个事务
SELECT * FROM table1 WHERE id = 10 FOR UPDATE; --获取排它锁(FOR UPDATE)

此时,Notice如下提示:

MySQL on localhost (5.7.33)  Warning (1205): Lock wait timeout exceeded; try restarting transaction

它表示这个事务超时(由锁等待超时参数选项决定)了以后,还是没有获得需要的锁,MySQL就会强制回滚该事务。

在该示例中,如果两个事务先后执行,则T1成功获取该行的锁,而T2则始终在等待该锁的释放,最后会超时回滚,解除死锁的情况。

示例

接下来,我们来看一下具体的示例操作。

在该示例中,我们创建一个students表,然后模拟两个事务之间的死锁情况。

首先,我们创建一个students表:

CREATE TABLE `students` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

接着,我们往students表中插入一些记录:

INSERT INTO `students` (`name`, `age`) VALUES
  ('Tom', 18),
  ('Jack', 20),
  ('Lucy', 22),
  ('Mike', 24),
  ('David', 20),
  ('John', 22);

现在,我们让两个事务分别对students表进行操作。

  1. 第一个事务(T1)

在第一个事务中,我们首先查询students表中所有年龄为20岁的学生信息:

SET SESSION autocommit=0;
BEGIN;
SELECT * FROM students WHERE age = 20 FOR UPDATE;

上述SQL对students表中所有age为20的行进行了排它锁,该锁将一直存在于当前事务中。

  1. 第二个事务(T2)

在第二个事务中,我们对students表中年龄为22的行进行更新操作:

SET SESSION autocommit=0;
BEGIN;
UPDATE students SET age = age + 1 WHERE age = 22;

上述SQL需要在students表中获取一行排他锁(FOR UPDATE),但由于第一个事务已经持有了students表的排它锁,因此该事务将等待第一个事务的锁释放,直到超时后回滚。

在上述示例中,我们展示了MySQL意向锁和死锁的操作过程。需要注意的是,在实际应用中,我们通常需要注意编写高效的SQL语句,避免出现死锁等问题,同时也可以根据实际需求对MySQL锁相关的配置进行适当调整,以提高系统的性能和稳定性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:MySQL的意向共享锁、意向排它锁和死锁 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解Redis list列表使用方法

    Redis list(列表)相当于 Java 语言中的 LinkedList 结构,是一个链表而非数组,其插入、删除元素的时间复杂度为 O(1),但是查询速度欠佳,时间复杂度为 O(n)。 认识Redis List列表 Redis List是一个可以存储多个有序字符串的数据结构,他的底层是一个链表。我们可以通过左右两端追加、裁剪、查看元素,还可以通过列表的一…

    Redis 2023年3月18日
    00
  • mysql操作(精简版)

    一、数据库操作(建库、删库) 1、查看数据库:show databases; 2、创建数据库:DROP DATABASE 数据库名; 3、删除数据库:CREATE DATABASE 数据库名; 4、使用数据库:use 数据库名;   二、表操作(建表、删表、增删属性) 1、创建表: create table 表名(     列名1  类型(长度) [约束],…

    MySQL 2023年4月12日
    00
  • Linux history命令的几个使用小技巧

    当你在使用Linux终端时,历史命令可能是最有用的命令之一。History命令可以帮助你查找并重复执行之前执行过的命令。下面是Linux history命令的几个使用小技巧: 1. 使用‘history’命令来查找历史命令 最基本的用法就是输入history命令来查找历史命令。这将显示当前用户在该终端会话中执行的所有命令,每个命令前有一个数字序列,这表示执行…

    database 2023年5月22日
    00
  • 如何使用Python将一个JSON文件中的数据导入到数据库中?

    以下是如何使用Python将一个JSON文件中的数据导入到数据库中的完整使用攻略。 使用Python将一个JSON文件中的数据导入到数据库中的前提条件 在Python将一个JSON文件中的数据导入到数据库中,需要确保已经安装并启动支持导入数据的数据库,例如MySQL或PostgreSQL,并且需要安装Python的相应数据库驱动程序例如mysql-conne…

    python 2023年5月12日
    00
  • 用PHP连mysql和oracle数据库性能比较

    下面是详细讲解“用PHP连mysql和oracle数据库性能比较”的完整攻略。 准备工作 在进行数据库性能比较前,我们需要先搭建好PHP、MySQL和Oracle的环境。 安装PHP环境 我们首先需要在本地安装PHP环境。可以在PHP官网上下载并安装对应系统的PHP版本。 安装MySQL 我们可以在MySQL官网上下载并安装MySQL Community S…

    database 2023年5月22日
    00
  • ecmall二次开发 直接实例化mysql对象

    $db = &db(); // 第一步赋值数据库类库, $db->query(sql); // 第二步执行mysql 语句; 常用的数据库函数: 得到一行数据 $user=$db->getrow(“select * from ecm_member where user_id=111”); print_r($user); 得到一列数据 $u…

    MySQL 2023年4月13日
    00
  • 解决SQL SERVER数据库备份时出现“操作系统错误5(拒绝访问)。BACKUP DATABASE 正在异常终止。”错误的解决办法

    当我们在SQL SERVER中备份数据库时,有时会遇到错误提示“操作系统错误5:拒绝访问”。这种情况下,我们无法对数据库进行备份。造成这种错误的原因可能是我们没有足够的权限或者备份路径不正确。 下面是解决“操作系统错误5:拒绝访问”错误的完整攻略: 一、检查数据库备份路径及权限 1.检查备份路径 首先要确认备份文件夹所在路径是否正确,同时可在电脑上新建一个文…

    database 2023年5月21日
    00
  • Go http client 连接池不复用的问题

    Go HTTP client 连接池不复用的问题可能会导致应用程序性能下降,因此需要进行及时的优化和解决。下面将介绍一些应对该问题的具体步骤。 1. 使用全局变量保存HttpClient对象 在已知 HttpClient 对象的场景下,建议将其存储在全局变量中,并在需要使用时从该变量中获取。这样可以确保多次使用同一个 HTTP 域名时复用连接池。以下是示例代…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部