mysql-分析并解决可重复读隔离级别发生的删除幻读问题

devtools/2024/11/25 6:36:56/

在 MySQL 的 InnoDB 存储引擎中,快照读和当前读的行为会影响事务的一致性。让我们详细分析一下隔离级别味可重复读的情况下如何解决删除带来的幻读。
场景描述
假设有一个表 orders,其中包含以下数据:
在这里插入图片描述
事务 A 执行快照读

START TRANSACTION;
SELECT * FROM orders WHERE customer_id = 200; -- 快照读

事务 B 执行当前读并删除记录

START TRANSACTION;
DELETE FROM orders WHERE id = 10; -- 当前读,尝试删除
COMMIT;

分析

  • 快照读(事务 A)
  • 快照读:事务 A 执行的是快照读,它基于事务开始时的数据快照,不加锁。
  • 数据快照:事务 A 会看到事务开始时的数据快照,即 customer_id = 200 的记录为 (3, 200, 150) 和 (10,200, 250)。
  • 当前读(事务 B)
  • 当前读:事务 B 执行的是当前读操作,它会尝试获取 id = 10 的记录的行锁。
  • 删除操作:事务 B 成功删除 id = 10 的记录,并提交事务。

影响分析
事务 A 第一次查询:
事务 A 查询 customer_id = 200 的记录,结果为 (3, 200, 150) 和 (10, 200, 250)。
事务 B 删除记录:
事务 B 删除 id = 10 的记录,并提交事务。
事务 A 第二次查询:
事务 A 再次查询 customer_id = 200 的记录,结果为 (3, 200, 150),缺少了 (10, 200, 250)。

结论
幻读:这是因为事务 B 在事务 A 之间删除了一条记录。

解决方案
使用可重复读(Repeatable Read)隔离级别 + 间隙锁

1.设置隔离级别:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

2.使用当前读操作:

  • 在事务 A 中,使用 SELECT … FOR UPDATE 或 SELECT … FOR SHARE 来获取行锁和间隙锁。
  • 这样可以确保在事务 A 的整个生命周期内,查询结果保持一致。

示例
事务 A 执行以下操作:

START TRANSACTION;
SELECT * FROM orders WHERE customer_id = 200 FOR UPDATE; -- 当前读,加锁并获取间隙锁
-- 进行业务逻辑处理
SELECT * FROM orders WHERE customer_id = 200; -- 再次查询
COMMIT;

事务 B 执行以下操作:

START TRANSACTION;
DELETE FROM orders WHERE id = 10; -- 当前读,尝试删除
COMMIT;

由于事务 A 持有 customer_id = 200 范围内的所有记录的行锁和间隙锁,事务 B 的删除操作将被阻塞,直到事务 A 提交或回滚。这样可以确保事务 A 的查询结果在整个事务期间保持一致。

总结
当前读:事务 A 第一次执行的时候使用的是当前读因此会对该行进行加锁,所以其他事务无法对该行进行删除或者更新操作。
快照读:事务 A 第二次执行的时候此时事务并未提交因此使用快照读仍然能读取到该行。
当前读:事务 B 执行当前读并删除记录,由于事务 A 持有锁,导致事务B处于阻塞状态直到事物A释放 。


http://www.ppmy.cn/devtools/136772.html

相关文章

(微信小程序)基于Spring Boot的校园失物招领平台的设计与实现(vue3+uniapp+mysql)

💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

ROS之Topic话题与Message消息,以及如何发布话题(Publish)和订阅话题(Subscribe),以及如何梳理节点之间的关系?

1.什么是Topic话题与Message消息? 在 ROS 中,Topic(话题)是节点Node之间通信的通道,用于实现消息的发布和订阅,类似广播频道;Message(消息)是通过 Topic 传输的数据内容&…

湛江市社保卡申领指南:手机获取电子照片回执单号

在湛江市,社保卡的申领流程已经实现了数字化,为市民带来了极大的便利。特别是通过手机获取数码照片回执单号,这一环节更是简化了申领过程。今天,我们将详细介绍如何不去照相馆,利用手机来获取数码照片回执单号&#xf…

Electron一些概念理解

前言 版本33.2.0 记录官方文档的一些初步理解 官方文档 自写demo: electron-demo 按钮点击发送http请求     主进程 一个Electron应用项目都会有一个主进程,启动入口 只有这个主进程,运行在Node.js环境中,可以require其他模块&#xf…

el-table vue3统计计算数字

固定合计在最下列 父组件 <template><el-tablev-loading"loading"tooltip-effect"light":data"list"style"width: 100%":max-height"maxHeight"element-loading-text"拼命加载中...":header-cell-styl…

蓝桥杯每日真题 - 第20天

题目&#xff1a;&#xff08;机房&#xff09; 题目描述&#xff08;13届 C&CG题&#xff09; 解题思路&#xff1a; 这道题目可以看作在一个无向图中查找两点之间的最短路径。题目中的 n 台电脑和 n−1 根网线形成了一棵树&#xff0c;树是一个特殊的无向图&#xff0c…

el-select 和el-tree二次封装

前言 本文章是本人在开发过程中&#xff0c;遇到使用树形数据&#xff0c;动态单选或多选的需求&#xff0c;element中没有这种组件&#xff0c;故自己封装一个&#xff0c;欢迎多多指教 开发环境&#xff1a;element-UI、vue2 组件效果 单选 多选 组件引用 <treeselec…

C++知识整理day2类与对象(上)——类的定义、实例化、this指针、构造、析构、拷贝构造函数

文章目录 1.类的定义1.1 类定义的格式1.2 访问限定符1.3 类域 2.实例化2.2 对象大小 3.this指针4.类的默认成员函数5.构造函数6. 析构函数7.拷贝构造函数 1.类的定义 1.1 类定义的格式 class为定义类的关键字&#xff0c;Stu为类的名字&#xff0c;{}中为类的主体&#xff0c;…