MySQL事务隔离级别

文章目录

  • 一、前置知识
    • 1、为什么要隔离级别?
    • 1、隔离级别种类
    • 2、查看/设置隔离级别
    • 3、手动控制事务
    • 4、事务的锁信息查看
  • 二、实战
    • 1、READ UNCOMMITTED
    • 2、READ COMMITTED
    • 3、REPEATABLE READ
    • 4、SERIALIZABLE
  • 三、总结

一、前置知识

1、为什么要隔离级别?

并发事务会出现更新丢失、脏读、不可重复读,幻读。

  • 更新丢失:当两个或多个事务更新同一行记录,会产生更新丢失现象。回滚覆盖,一个事务回滚操作,把其他事务已提交的数据给覆盖了;提交覆盖,一个事务提交操作,把其他事务已提交的数据给覆盖了
  • 脏读:一个事务读取到了另一个事务修改但未提交的数据
  • 不可重复读:一个事务读到了另一个事务已经提交的update数据,导致多次查询结果不一致
  • 幻读:在同一个事务中,前后两次查询同一个范围的数据时,发现有新的数据插入,导致结果集不一致的情况。

通过隔离级别可以解决。
在这里插入图片描述

1、隔离级别种类

在MySQL中,可以使用SET TRANSACTION ISOLATION LEVEL语句设置事务的隔离级别。隔离级别用于控制并发事务之间的相互影响程度。

MySQL支持以下四种事务隔离级别:

  1. READ UNCOMMITTED(未提交读):允许事务读取其他未提交的事务所做的修改。但是,会出现脏读、不可重复读和幻读等问题。

  2. READ COMMITTED(提交读):只允许事务读取已经提交的事务所做的修改。在同一个事务内,对同一行数据的查询可能返回不同的结果。

  3. REPEATABLE READ(可重复读):事务执行期间,保证多次读取同一数据结果一致。但是,可能出现幻读问题。

  4. SERIALIZABLE(可串行化):最高级别的隔离级别,完全串行化事务执行。确保每个事务对数据库的读写操作是相互独立的。

2、查看/设置隔离级别

查看事务隔离级别:

-- 查看当前会话的事务隔离级别  
SELECT @@transaction_isolation;
SELECT @@tx_isolation;
-- 查看全局的事务隔离级别  
SELECT @@GLOBAL.tx_isolation;
SELECT @@GLOBAL.transaction_isolation;

可以使用以下命令来设置事务的隔离级别:

SET [GLOBAL | SESSION] TRANSACTIONtransaction_characteristic [, transaction_characteristic] ...transaction_characteristic: {ISOLATION LEVEL level| access_mode
}level: {REPEATABLE READ| READ COMMITTED| READ UNCOMMITTED| SERIALIZABLE
}access_mode: {READ WRITE| READ ONLY
}

具体情况如下,详细可以查看官方文档:https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
在这里插入图片描述
例如,我们要设置当前会话的隔离级别为可重复读:

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

3、手动控制事务

开启事务:BEGIN; 和 START TRANSACTION; 在功能上是等价的。它们都会开始一个新的事务。
提交事务:COMMIT;
回滚事务:ROLLBACK;

例如:

BEGIN;
// 相关操作
COMMIT;

4、事务的锁信息查看

具体可以查看官方文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-transactions.html

其中关键就三张表,如下:

Three InnoDB INFORMATION_SCHEMA tables enable you to monitor transactions and diagnose potential locking problems:

INNODB_TRX: Provides information about every transaction currently executing inside InnoDB, including the transaction state (for example, whether it is running or waiting for a lock), when the transaction started, and the particular SQL statement the transaction is executing.

提供了当前在InnoDB内部执行的所有事务的信息

INNODB_LOCKS: Each transaction in InnoDB that is waiting for another transaction to release a lock (INNODB_TRX.TRX_STATE is LOCK WAIT) is blocked by exactly one blocking lock request. That blocking lock request is for a row or table lock held by another transaction in an incompatible mode. A lock that blocks a transaction is always held in a mode incompatible with the mode of requested lock (read vs. write, shared vs. exclusive). The blocked transaction cannot proceed until the other transaction commits or rolls back, thereby releasing the requested lock. For every blocked transaction, INNODB_LOCKS contains one row that describes each lock the transaction has requested, and for which it is waiting. INNODB_LOCKS also contains one row for each lock that is blocking another transaction, whatever the state of the transaction that holds the lock (INNODB_TRX.TRX_STATE is RUNNING, LOCK WAIT, ROLLING BACK or COMMITTING).

提供了有关InnoDB事务已请求但尚未获取的每个锁的信息,以及事务持有的阻止另一个事务的每个锁的信息。
通过查看这个表,你可以了解哪些事务正在等待锁,哪些事务持有锁,以及这些锁是如何影响数据库并发的。

INNODB_LOCK_WAITS: This table indicates which transactions are waiting for a given lock, or for which lock a given transaction is waiting. This table contains one or more rows for each blocked transaction, indicating the lock it has requested and any locks that are blocking that request. The REQUESTED_LOCK_ID value refers to the lock requested by a transaction, and the BLOCKING_LOCK_ID value refers to the lock (held by another transaction) that prevents the first transaction from proceeding. For any given blocked transaction, all rows in INNODB_LOCK_WAITS have the same value for REQUESTED_LOCK_ID and different values for BLOCKING_LOCK_ID.

包含了每个被阻止的InnoDB事务的信息,可以快速识别出哪些事务因为锁等待而被阻塞.

例子:查看哪些事务正在等待,哪些事务正在阻止它们

SELECTr.trx_id waiting_trx_id,r.trx_mysql_thread_id waiting_thread,r.trx_query waiting_query,b.trx_id blocking_trx_id,b.trx_mysql_thread_id blocking_thread,b.trx_query blocking_query
FROM       information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx bON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx rON r.trx_id = w.requesting_trx_id;SELECTwaiting_trx_id,waiting_pid,waiting_query,blocking_trx_id,blocking_pid,blocking_query
FROM sys.innodb_lock_waits;

二、实战

表结构如下:

CREATE TABLE `isolation_level_test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`age` int(11) DEFAULT NULL,`create_time` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

初始数据如下:

INSERT INTO `test`.`isolation_level_test` (`id`, `name`, `age`, `create_time`) VALUES (1, 'forlan1', 12, '2024-03-07 13:45:11');

1、READ UNCOMMITTED

会话1(为了验证在会话2中有啥效果)

BEGIN;
SELECT name,age,create_time FROM isolation_level_test;
INSERT INTO `isolation_level_test` (`name`, `age`) VALUES ('forlan2', 13);
SELECT name,age,create_time FROM isolation_level_test;
COMMIT;

查询结果如下:
在这里插入图片描述

会话2

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
SELECT name,age,create_time FROM isolation_level_test;
-- 等会话1插入数据后,再查询一次
SELECT name,age,create_time FROM isolation_level_test;
COMMIT;

查询结果如下:
在这里插入图片描述
可以看到,会话2读到会话1还没提交的数据,出现了脏读

2、READ COMMITTED

会话1(为了验证在会话2中有啥效果)

BEGIN;
SELECT name,age,create_time FROM isolation_level_test;
INSERT INTO `isolation_level_test` (`name`, `age`) VALUES ('forlan2', 13);
SELECT name,age,create_time FROM isolation_level_test;
COMMIT;

会话2

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SELECT name,age,create_time FROM isolation_level_test;
-- 等会话1插入数据,提交事务后,再查询一次
SELECT name,age,create_time FROM isolation_level_test;
COMMIT;

查询结果如下:
在这里插入图片描述

可以看到,这种会话,不会出现脏读,但出现了不可重复读

3、REPEATABLE READ

会话1(为了验证在会话2中有啥效果)

BEGIN;
SELECT name,age,create_time FROM isolation_level_test;
INSERT INTO `isolation_level_test` (`name`, `age`) VALUES ('forlan2', 13);
SELECT name,age,create_time FROM isolation_level_test;
COMMIT;

会话2

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT name,age,create_time FROM isolation_level_test WHERE age>10;
-- 等会话1插入数据后,再查询一次
SELECT name,age,create_time FROM isolation_level_test WHERE age>10;
-- 等会话1插入数据,提交事务后,再查询一次
SELECT name,age,create_time FROM isolation_level_test WHERE age>10;
-- 修改数据,让后续查询变成当前读
UPDATE isolation_level_test SET name='forlan' WHERE age>10;
SELECT name,age,create_time FROM isolation_level_test WHERE age>10;
COMMIT;

在这里插入图片描述

可以看到,在当前读的情况下,会出现幻读,这就很奇怪了对吧,因为MySQL宣称是解决了幻读问题,其中"快照读"依靠MVCC控制,"当前读"通过Next-key Lock解决。
还有另外一种说法是,幻读主要关注的是SELECT操作可能看到“幻影”行,而不是UPDATE或DELETE操作可能影响到更多的行。

4、SERIALIZABLE

这个不用验证了,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰了,一般不用,性能特别低。

三、总结

Oracle 默认使用READ COMMITTED(读已提交)隔离级别
MySQL默认使用REPEATABLE(可重复读)隔离级别
总的来说,选择什么隔离级别,取决于你要并发性能还是数据一致性,两者之间的一个权衡。

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

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

相关文章

9款世界级垂直领域软件架构师Visio平替作图工具!

1 LucidChart 一个基于HTML5的在线流程图绘制和协作应用平台,用户可以通过它方便快速的实现流程图表的绘制,同时还可以实现与他人进行实时的流程图绘制和修改功能,对需要群组协作功能的团队来说,这点非常方便。 由于LucidChart是…

vue el-avatar 使用require提示无法找到图片

报错信息 错误代码 问题分析 vue初始化DOM树时没有挂载数据,导致无法找到模块 解决方案

Android 13 WMS-动画流程

动画的类型如下 IntDef(flag true, prefix { "ANIMATION_TYPE_" }, value {ANIMATION_TYPE_NONE,ANIMATION_TYPE_APP_TRANSITION,ANIMATION_TYPE_SCREEN_ROTATION,ANIMATION_TYPE_DIMMER,ANIMATION_TYPE_RECENTS,ANIMATION_TYPE_WINDOW_ANIMATION,ANIMATION_TYPE_…

片上网络(NoC)技术的发展及其给高端FPGA带来的优势

片上网络(NoC)技术的发展及其给高端FPGA带来的优势 1. 概述 在摩尔定律的推动下,集成电路工艺取得了高速发展,单位面积上的晶体管数量不断增加。 片上系统(System-on-Chip,SoC)具有集成度高、功耗低、成本低等优势,已经成为大规模集成电路系统设计的主流方向,解决了…

【Linux】Linux原生异步IO(一):libaio-介绍

1、IO模型 1.1 简述 相信大家在搜索的时候,都会看到下面这张图,IO的使用场景:同步、异步、阻塞、非阻塞,可以组合成四种情况: 同步阻塞I/O: 用户进程进行I/O操作,一直阻塞到I/O操作完成为止。同步非阻塞I/O: 用户程序可以通过设置文件描述符的属性O_NONBLOCK,I/O操作可…

量化交易日记 基础概念篇

联系方式 17710158550 NBEATS (Neural Basis Expansion Analysis for Time Series)、NHiTS (Neural Hierarchical Interpolation for Time Series Forecasting)、LSTNet (Long Short-Term Memory Network)、TCN (Temporal Convolutional Network)、Transformer、DeepAR (DeepAR…

2024.3.7每日一题

LeetCode 找出字符串的可整除数组 题目链接:2575. 找出字符串的可整除数组 - 力扣(LeetCode) 题目描述 给你一个下标从 0 开始的字符串 word ,长度为 n ,由从 0 到 9 的数字组成。另给你一个正整数 m 。 word 的 …

今天分享一个好看的输入法皮肤相信每个人心里住着一个少女心我们美化一下她吧

标题: 白日梦皮肤上线,百度输入法助你开启梦幻之旅! 正文: 大家好呀!今天我来给大家安利一款超级梦幻的百度输入法皮肤——“白日梦”系列! 这款皮肤的设计灵感来源于我们内心深处的白日梦,充…

Matlab 多项式插值(曲线拟合)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 由于对曲线拟合有些兴趣,这里就找了一些资料从最基本的方法来看一下曲线拟合的效果: 二、实现代码 % **********

就业班 2401--3.7 Linux Day13--日志轮转+jumpserver堡垒机

一、日志轮转 日志重要性 Linux系统日志对管理员来说,是了解系统运行的主要途径,因此需要对 Linux 日志系统有个详细的了解。 Linux 系统内核和许多程序会产生各种错误信息、告警信息和其他的提示信息,这些各种信息都应该记录到日志文件中&a…

SQOOP安装与使用

SQOOP安装及使用 文章目录 SQOOP安装及使用SQOOP安装1、上传并解压2、修改配置文件3、修改环境变量4、添加MySQL连接驱动5、测试 准备MySQL数据登录MySQL数据库创建student数据库切换数据库并导入数据另外一种导入数据的方式使用Navicat运行SQL文件导出MySQL数据库 importMySQL…

Leetcode : 147. 对链表进行插入排序

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 每次迭代中,插入排序只从输…