数据库隔离级别并非安装后就固定,绝大多数主流数据库(如MySQL、PostgreSQL、SQL Server)都支持动态调整和运行中自定义,具体调整范围可分为全局、会话和语句三个层级。

  1. 全局级别调整:修改数据库配置文件(如MySQL的my.cnf)并重启服务,会影响所有新创建的会话,属于长期生效的配置。
  2. 会话级别调整:在当前数据库连接中执行特定SQL命令(如MySQL的SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED),仅对当前会话生效,关闭连接后失效,适合临时切换隔离级别。
  3. 语句级别调整:部分数据库支持为单个事务语句指定隔离级别(如SQL Server的SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN TRANSACTION; ... COMMIT;),仅对该次事务生效,灵活性最高。

不同数据库的具体调整语法略有差异,但核心逻辑均支持动态修改,无需重新安装数据库。

要模拟MySQL 5.7中事务并发的脏读、不可重复读、幻读,需先创建测试表和基础数据,再通过「两个会话模拟并发事务」,结合不同隔离级别验证问题及解决办法。以下是完整步骤:

一、基础准备:创建表与初始化数据

1. 创建测试表(用户余额表)
-- 建表:id(主键)、user_id(用户ID)、balance(余额)
CREATE TABLE `user_balance` (`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id` INT(11) NOT NULL COMMENT '用户ID',`balance` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '账户余额',PRIMARY KEY (`id`),UNIQUE KEY `idx_user_id` (`user_id`) -- 唯一索引,确保用户ID不重复
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户余额表';
2. 插入初始化数据
-- 插入1条测试数据:用户ID=1001,初始余额1000元
INSERT INTO user_balance (user_id, balance) VALUES (1001, 1000.00);-- 验证数据
SELECT * FROM user_balance WHERE user_id = 1001;

二、核心概念:MySQL隔离级别与并发问题

MySQL 5.7默认隔离级别是 REPEATABLE READ(可重复读),不同隔离级别对并发问题的抑制能力不同:

隔离级别脏读不可重复读幻读
READ UNCOMMITTED(读未提交)允许允许允许
READ COMMITTED(读已提交)禁止允许允许
REPEATABLE READ(可重复读)禁止禁止禁止(InnoDB通过MVCC实现)
SERIALIZABLE(串行化)禁止禁止禁止

模拟规则:需打开「两个MySQL会话」(如Navicat的两个查询窗口、CMD的两个mysql连接),分别执行「事务A」和「事务B」,按步骤操作。

三、场景1:脏读(Dirty Read)

什么是脏读?

事务A读取了事务B未提交的修改数据,若事务B后续回滚,事务A读取的就是“无效脏数据”。

1. 模拟脏读(需先设置隔离级别为「READ UNCOMMITTED」)
步骤1:两个会话均设置隔离级别
-- 会话1、会话2均执行:设置当前会话隔离级别为读未提交
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
步骤2:开启事务并执行操作(按顺序执行)
步骤会话1(事务A:查询用户余额)会话2(事务B:修改用户余额但不提交)
1BEGIN;(开启事务)
SELECT balance FROM user_balance WHERE user_id=1001;
– 结果:1000.00
-
2-BEGIN;(开启事务)
UPDATE user_balance SET balance=balance-200 WHERE user_id=1001;
– 不执行COMMIT(事务未提交)
3SELECT balance FROM user_balance WHERE user_id=1001;
– 结果:800.00(读取到事务B未提交的修改,脏读发生!)
-
4-ROLLBACK;(事务B回滚,修改作废)
5SELECT balance FROM user_balance WHERE user_id=1001;
– 结果:1000.00(数据恢复,验证步骤3读的是脏数据)
-
6COMMIT;(关闭事务A)-
2. 解决脏读:提升隔离级别至「READ COMMITTED」及以上
-- 两个会话均设置隔离级别为读已提交
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;-- 重复上述步骤2,会发现:步骤3中会话1读取的余额仍为1000.00(事务B未提交的修改不可见),脏读被禁止。

四、场景2:不可重复读(Non-Repeatable Read)

什么是不可重复读?

事务A在同一事务内多次读取同一数据,若事务B在两次读取间「提交了修改」,则事务A两次读取的结果不一致。

1. 模拟不可重复读(需设置隔离级别为「READ COMMITTED」)
步骤1:两个会话均设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
步骤2:开启事务并执行操作(按顺序执行)
步骤会话1(事务A:多次查询同一用户余额)会话2(事务B:修改并提交用户余额)
1BEGIN;(开启事务)
SELECT balance FROM user_balance WHERE user_id=1001;
– 结果:1000.00
-
2-BEGIN;(开启事务)
UPDATE user_balance SET balance=balance-200 WHERE user_id=1001;
COMMIT;(提交事务,修改生效)
3SELECT balance FROM user_balance WHERE user_id=1001;
– 结果:800.00(与步骤1结果不一致,不可重复读发生!)
-
4COMMIT;(关闭事务A)-
2. 解决不可重复读:提升隔离级别至「REPEATABLE READ」及以上
-- 两个会话均设置隔离级别为可重复读(MySQL默认级别)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 重复上述步骤2,会发现:步骤3中会话1读取的余额仍为1000.00(事务B提交的修改对事务A不可见),不可重复读被禁止。

五、场景3:幻读(Phantom Read)

什么是幻读?

事务A在同一事务内按同一条件多次查询,若事务B在两次查询间「提交了新数据插入/删除」,则事务A两次查询的「结果行数不一致」(像出现了“幻觉”)。

1. 模拟幻读(需设置隔离级别为「READ COMMITTED」,MySQL默认的REPEATABLE READ已禁止幻读)
步骤1:两个会话均设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
步骤2:开启事务并执行操作(按顺序执行)
步骤会话1(事务A:按条件多次查询用户)会话2(事务B:插入新用户并提交)
1BEGIN;(开启事务)
SELECT COUNT(*) FROM user_balance WHERE user_id > 1000;
– 结果:1(仅user_id=1001)
-
2-BEGIN;(开启事务)
INSERT INTO user_balance (user_id, balance) VALUES (1002, 1500.00);
COMMIT;(提交事务,新用户插入生效)
3SELECT COUNT(*) FROM user_balance WHERE user_id > 1000;
– 结果:2(新增了user_id=1002,行数不一致,幻读发生!)
-
4COMMIT;(关闭事务A)-
2. 解决幻读:使用「REPEATABLE READ」或「SERIALIZABLE」隔离级别
-- 两个会话均设置隔离级别为可重复读(MySQL默认)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 重复上述步骤2,会发现:步骤3中会话1查询的COUNT(*)仍为1(事务B插入的新数据对事务A不可见),幻读被禁止。-- 若用SERIALIZABLE级别:会话2插入数据时会被阻塞,直到会话1提交事务,彻底避免幻读(但性能损耗大)。

六、关键总结

  1. 问题本质:并发事务对数据的「修改/插入」与「读取」的时序冲突,隔离级别通过控制数据可见性解决冲突。
  2. MySQL默认隔离级别:REPEATABLE READ,已能禁止脏读、不可重复读、幻读(InnoDB的MVCC机制实现),兼顾性能与一致性。
  3. 语法记忆
    • 查看当前会话隔离级别:SELECT @@tx_isolation;(MySQL 5.7)/ SELECT @@transaction_isolation;(MySQL 8.0+)
    • 设置会话隔离级别:SET SESSION TRANSACTION ISOLATION LEVEL 级别名称;
    • 开启/提交/回滚事务:BEGIN; / COMMIT; / ROLLBACK;

在 MySQL 5.7 配置文件中,用于设置事务默认隔离级别的参数是 transaction_isolation(或旧版兼容参数 tx_isolation,两者功能一致,推荐使用 transaction_isolation)。

1. 参数说明

  • 核心作用:定义 MySQL 实例启动后,所有新创建会话的默认事务隔离级别,无需在每个会话中手动设置。
  • 参数值(对应 4 种隔离级别)
    • READ-UNCOMMITTED:读未提交(可能出现脏读、不可重复读、幻读)
    • READ-COMMITTED:读已提交(避免脏读,可能出现不可重复读、幻读)
    • REPEATABLE-READ:可重复读(MySQL 5.7 默认级别,避免脏读、不可重复读,通过 MVCC 减少幻读)
    • SERIALIZABLE:串行化(完全避免三种问题,性能最低)

2. 配置方式(永久生效)

  1. 找到 MySQL 5.7 的配置文件(路径因系统而异):
    • Linux:通常为 /etc/my.cnf/etc/mysql/my.cnf
    • Windows:通常为 MySQL安装目录/my.ini
  2. [mysqld] 模块下添加/修改参数:
    [mysqld]
    # 设置默认事务隔离级别为可重复读(MySQL 5.7 默认值,可根据需求修改)
    transaction_isolation = REPEATABLE-READ
    
  3. 重启 MySQL 服务使配置生效:
    • Linux:systemctl restart mysqld
    • Windows:在“服务”中重启“MySQL”服务

3. 临时生效方式(当前会话/全局)

若无需永久修改,可通过 SQL 语句临时设置(重启服务后失效):

  • 当前会话生效
    SET SESSION transaction_isolation = 'READ-COMMITTED';
    
  • 全局生效(对新会话生效,已存在会话不影响)
    SET GLOBAL transaction_isolation = 'SERIALIZABLE';
    

4. 验证隔离级别

通过以下 SQL 查看当前生效的隔离级别:

-- 查看当前会话的隔离级别
SELECT @@session.transaction_isolation;-- 查看全局的隔离级别
SELECT @@global.transaction_isolation;

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

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

相关文章

JVM从入门到实战:从字节码组成、类生命周期到双亲委派及打破双亲委派机制

摘要:本文围绕 Java 字节码与类加载机制展开,详解字节码文件组成、类的生命周期,介绍类加载器分类、双亲委派机制及打破该机制的方式,还阐述了线程上下文类加载器与 SPI 机制在 JDBC 驱动加载中的应用,帮助深入理解 Ja…

多源最短路(Floyd算法

多源最短路简介 多源最短路算法用于解决图中任意两节点间最短路径的问题,广泛应用于交通网络、社交关系分析、路由优化等场景。与单源最短路(如Dijkstra)不同,它一次性计算所有节点对的最短距离,适合需要全局路径规划的…

【攻防实战】记一次攻防实战全流程

那天我向众神祈祷,最后回答我的却只有挣扎十年依旧不甘的自己!成功究竟是馈赠还是偿还。 前言 网络安全技术学习,承认⾃⼰的弱点不是丑事,只有对原理了然于⼼,才能突破更多的限制。 拥有快速学习能力的安全研究员&…

Anaconda配置环境变量和镜像

Anaconda配置环境变量和镜像 下载失败就是开了梯子 Anaconda 作用:包管理(集中,有序)和环境管理(版本切换)使用conda命令对虚拟环境创建、删除自带python解释器pip(python自带的包管理工具&…

给定单词倒排

实现代码&#xff1a;public static void main(String[] args) {Scanner scanner new Scanner(System.in);// 输入的字符串String input scanner.nextLine();// 存储单词List<String> words new ArrayList<>();// 存储当前单词StringBuilder currentWord new S…

IO进程——进程引入、进程函数接口

一、引入1、进程&程序1.1 程序编译好的可执行的文件存放在磁盘上的指令和数据的有序集合&#xff08;文件&#xff09;程序是静态的&#xff0c;没有任何执行的概念1.2 进程一个独立的可调度的任务执行一个程序所分配的资源的总称进程是程序执行的一次过程进程是动态的&…

周末游戏推荐:安卓端俄罗斯方块,经典与创新的结合

前段时间&#xff0c;每到周末我都会给大家推荐一些离线的经典游戏&#xff0c;原本打算将这个传统一直延续下去。然而&#xff0c;我实在找不到足够好用且无广告的游戏了。有些游戏刚开始用的时候还不错&#xff0c;但用着用着就开始频繁弹出广告&#xff0c;这让我实在不敢向…

《用 Scikit-learn 构建 SVM 分类模型:从原理到实战的全流程解析》

《用 Scikit-learn 构建 SVM 分类模型:从原理到实战的全流程解析》 一、引言:为什么选择 SVM? 在机器学习的众多算法中,支持向量机(SVM)以其强大的分类能力和良好的泛化性能,在文本分类、人脸识别、医学诊断等领域广泛应用。尤其在中小规模数据集上,SVM 往往能提供比…

一文学会CMakeLists.txt: CMake现代C++跨平台工程化实战

你能学到什么&#xff1f;朋友们好久不见&#xff0c;我是alibli&#xff0c;好久没有更新博客了。今天本人将通过构造一个实际的虚拟小项目&#xff0c;来让你彻底掌握CMake跨平台工程构建&#xff0c;学会CMakeLists.txt语法。该项目实现了一个简单的平方、立方的计算程序&am…

高并发场景下限流算法实践与性能优化指南

高并发场景下限流算法实践与性能优化指南 在大规模并发访问环境中&#xff0c;合理的限流策略能保护后端服务稳定运行&#xff0c;避免系统因瞬时高并发导致资源耗尽或崩溃。本文将从原理出发&#xff0c;深入解析几种主流限流算法&#xff0c;并结合Java和Redis给出完整可运行…

Vue3应用执行流程详解

精确化的完整执行流程 (以 Vite Vue3 SPA 为例)整个过程可以分为两部分&#xff1a;首次访问的“冷启动”和后续的Vue应用接管。第一部分&#xff1a;首次访问与页面加载客户端&#xff1a;发送请求用户打开浏览器&#xff0c;输入 URL&#xff08;如 http://localhost:5173&a…

Redis 持久化与高可用实践(RDB / AOF / Sentinel / Cluster 全解析)

这篇是我把几套生产环境踩坑与复盘整理成的一份“从 0 到 1 长期可维护”的实践文。目标是&#xff1a;明确策略、给出默认可用的配置模板、把常见坑一次讲透。 适用场景&#xff1a;新项目选型、老项目稳定性加固、从单机迁移到 HA/Cluster、应对数据安全与故障切换要求。目录…

Linux内核的PER_CPU机制

参考书《Linux内核模块开发技术指南》 1.原理 在多核CPU的情况下&#xff0c;为了提高CPU并发执行的效率&#xff0c;对于某些不是必须要在核间进行同步访问的资源&#xff0c;可以为每一个CPU创建一个副本&#xff0c;让每个CPU都访问自身的数据副本&#xff0c;而不是通过加锁…

VSCode 的百度 AI编程插件

VSCode 的百度 AI编程插件主要是 Baidu Comate&#xff08;文心快码&#xff09;&#xff0c;这是一款基于文心大模型的新一代编码辅助工具&#xff0c;旨在提升开发者的编码效率&#xff0c;让写代码变得更简单。以下是关于 Baidu Comate 的详细介绍&#xff1a; 一、功能特点…

阿里云监控使用

阿里云的云监控服务&#xff08;CloudMonitor&#xff09;是一款简单易用、功能强大的监控工具&#xff0c;主要用来帮助用户实时监控阿里云上的各种资源&#xff08;比如服务器、数据库、网络等&#xff09;&#xff0c;并在出现问题时及时发出警报&#xff0c;确保业务稳定运…

嵌入式C语言-关键字typedef

定义和作用 typedef是C/C中的一个关键字&#xff0c;作用是为现有的数据类型&#xff08;int 、char 、flaot等&#xff09;创建新的别名&#xff0c;其目的是为了方便阅读和理解代码。 用法 typedef 原有类型名 新类型名;基本类型创建别名 typedef unsigned char uint8_t; typ…

【混合开发】【大前端++】Vue节点优化Dome之单节点轮播图片播放视频二

动图更精彩 背景 Vue作为大前端开发页面交互&#xff0c;在数字屏&#xff0c;智慧大屏等大屏幕开发过程中&#xff0c;轮播效果作为丰富的展示组件经常作为首选。但也因为这个组件的交互体验很好&#xff0c;于是各种单点组件增加到轮播效果里。经过业务的扩展&#xff0c;人…

前端开发核心技术与工具全解析:从构建工具到实时通信

觉得主包文章可以的,可以点个小爱心哟&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 主页:一位搞嵌入式的 genius-CSDN博客 系列文章专栏: https://blog.csdn.net/m0_73589512/category_13028539.html 前端开发核心技术与工具全解…

GPT 系列论文 gpt3-4 175B参数 + few-shot + 多模态输入 + RLHF + system

GPT&#xff0c;GPT-2&#xff0c;GPT-3 论文精读【论文精读】 GPT-4论文精读 从1750亿参数的文本预言家&#xff0c;到多模态的通用天才&#xff0c;OpenAI用两次震撼世界的发布&#xff0c;重新定义了人工智能的可能性边界。这份笔记将带你深入GPT-3和GPT-4的核心突破&#…

.gitignore文件的作用及用法

目录 ​​.gitignore 文件的作用​​ ​​.gitignore 的基本语法​​ ​​Python 项目的 .gitignore 示例​​ ​​如何使用 .gitignore​​ ​​1. 创建 .gitignore 文件​​ ​​2. 编辑 .gitignore​​ ​​3. 检查 Git 状态​​ ​​常见问题​​ ​​Q1&#xff…