MySQL的多版本并发控制(MVCC, Multi-Version Concurrency Control)是一种用于实现高并发性的机制,它允许多个事务同时读取和写入数据,而不会相互阻塞。MVCC主要在InnoDB存储引擎中实现,通过维护数据的多个版本来实现一致性和隔离性。

一、MVCC的基本原理

MVCC通过维护每行数据的多个版本,使得读操作不会阻塞写操作,写操作也不会阻塞读操作。它通过以下机制实现:

  1. 隐藏列

    • InnoDB表的每一行都有两个隐藏列:trx_idroll_pointer
    • trx_id(事务ID)记录了最近一次修改该行的事务ID。
    • roll_pointer指向回滚段中的上一个版本。
  2. 快照读

    • 快照读读取的是数据的某个版本快照,而不是当前最新版本。它通过检查每行数据的trx_id和当前事务的ID来决定读取哪个版本。
    • 快照读通常用于SELECT语句,不会加锁。
  3. 当前读

    • 当前读读取的是数据的最新版本,它会对读取的行加锁,确保数据的最新性和一致性。
    • 当前读通常用于SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE语句。

二、事务隔离级别与MVCC

MVCC在不同的事务隔离级别下有不同的表现:

  1. 读未提交(READ UNCOMMITTED)

    • 事务可以读取其他事务未提交的数据(脏读)。
    • 不适用MVCC。
  2. 读已提交(READ COMMITTED)

    • 事务只能读取其他事务已提交的数据。
    • 每次读取数据时,会读取最新的已提交版本。
  3. 可重复读(REPEATABLE READ)

    • 事务在开始时创建一个一致性视图,所有读取操作都基于这个视图。
    • 事务进行过程中,即使其他事务已提交,也不会看到这些修改。
    • 防止不可重复读和幻读。
  4. 序列化(SERIALIZABLE)

    • 最严格的隔离级别,事务完全串行化执行。
    • 会对读取的每一行数据加锁。

三、示例代码

以下是一些示例代码,展示了在不同隔离级别下,使用MVCC如何避免读写冲突。

1. 创建测试表并插入数据
CREATE TABLE test_mvcc (id INT PRIMARY KEY,value VARCHAR(50)
);INSERT INTO test_mvcc (id, value) VALUES (1, 'Initial Value');
2. 设置事务隔离级别并启动事务
-- 在会话1中(事务1)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;-- 在会话2中(事务2)
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
3. 快照读示例
-- 在会话1中,读取数据
SELECT * FROM test_mvcc WHERE id = 1;-- 在会话2中,更新数据
UPDATE test_mvcc SET value = 'Updated Value' WHERE id = 1;-- 在会话1中,再次读取数据
SELECT * FROM test_mvcc WHERE id = 1;-- 此时,会话1中的两次读取结果都是 'Initial Value',因为使用的是快照读
4. 当前读示例
-- 在会话1中,使用当前读读取数据
SELECT * FROM test_mvcc WHERE id = 1 FOR UPDATE;-- 在会话2中,尝试更新数据
UPDATE test_mvcc SET value = 'Another Update' WHERE id = 1;-- 会话2中的更新操作会被阻塞,直到会话1提交或回滚事务
5. 提交事务
-- 在会话1中,提交事务
COMMIT;-- 在会话2中,更新操作解除阻塞,继续执行
UPDATE test_mvcc SET value = 'Another Update' WHERE id = 1;

四、Java代码示例

以下是一个Java示例程序,展示了如何通过JDBC设置事务隔离级别,并展示使用MVCC的效果。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class MVCCExample {private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database";private static final String USER = "your_db_user";private static final String PASSWORD = "your_db_password";public static void main(String[] args) {try (Connection connection1 = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);Connection connection2 = DriverManager.getConnection(JDBC_URL, USER, PASSWORD)) {connection1.setAutoCommit(false);connection2.setAutoCommit(false);// 设置事务隔离级别为 REPEATABLE READconnection1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);connection2.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);// 在会话1中读取数据try (Statement statement1 = connection1.createStatement()) {ResultSet rs1 = statement1.executeQuery("SELECT value FROM test_mvcc WHERE id = 1");while (rs1.next()) {System.out.println("Session 1 - Initial Value: " + rs1.getString("value"));}}// 在会话2中更新数据try (Statement statement2 = connection2.createStatement()) {statement2.executeUpdate("UPDATE test_mvcc SET value = 'Updated Value' WHERE id = 1");}// 在会话1中再次读取数据try (Statement statement1 = connection1.createStatement()) {ResultSet rs1 = statement1.executeQuery("SELECT value FROM test_mvcc WHERE id = 1");while (rs1.next()) {System.out.println("Session 1 - After Update in Session 2: " + rs1.getString("value"));}}// 提交会话2connection2.commit();// 在会话1中再次读取数据(验证隔离级别的效果)try (Statement statement1 = connection1.createStatement()) {ResultSet rs1 = statement1.executeQuery("SELECT value FROM test_mvcc WHERE id = 1");while (rs1.next()) {System.out.println("Session 1 - After Commit in Session 2: " + rs1.getString("value"));}}// 提交会话1connection1.commit();} catch (SQLException e) {e.printStackTrace();}}
}

五、总结

MySQL的MVCC通过维护多个数据版本实现高并发性和一致性,使得读操作和写操作可以并行执行而不会互相阻塞。理解MVCC的工作原理,对于设计高性能、高并发的数据库应用至关重要。通过示例代码,我们可以看到在不同事务隔离级别下,MVCC如何帮助我们实现并发控制和数据一致性。

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

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

相关文章

Docker--将非root用户添加docker用户组,解决频繁sudo执行输入密码的问题

一、为什么要有docker用户组? 根本原因: Linux的设备访问权限控制机制 Docker守护进程(dockerd)运行时会创建一个特殊的Unix套接字文件,如:/var/run/docker.sock。 这个文件就像一个“门”,所有…

C语言---函数的递归与迭代

递归的理解与限制条件 所谓函数递归就是递推加回归的过程,就是函数自己调用自己。递归的思想就是把复杂的问题拆分成与原来那个大问题相似的子问题来求解,大事化小,像剥洋葱一样,最终把问题解决。 递归的限制条件: 一个…

freqtrade在docker运行一个dryrun实例

检查配置 freqtrade trade --config user_data/config.json --strategy MlStrategy config文件,这个配置做期货为主,静态配置了交易对,同时端口和第一个bot要不一样,不然没有办法进行监控,甚至要冲突了。10S钟进行循环&#xff0c…

单片机学习笔记.PWM

PWM原理: 频率占空比:精度占空比变化步距 电机驱动电路:利用PWM实现呼吸灯代码 sbit LEDP2^0;//引脚定义unsigned char Time,i;//变量定义void Delay(unsigned int t)//定义延时 {while(t--); }main函数里:int main() {unsigned c…

【Git】解决使用SSH连接远程仓库时需要多次输入密码的问题

问题产生的原因:你的SSH私钥设置了密码短语(passphrase)。解决问题的方法:使用SSH代理(ssh-agent),ssh-agent是一个后台运行程序,它会记住你解锁过的SSH私钥的密码短语,这…

机器学习—逻辑回归

一介绍逻辑回归是处理二分类问题的线性模型,通过sigmoid函数将线性输出映射到[0,1],输出事件发生概率,广泛用于预测与分类。如果做坐标的话,特征就是p1和p2,结果就是y红的与绿的 二Sigma函数代码说明Sigmoid 函数定义&…

深入解读OpenTelemetry分布式链路追踪:原理与实践指南

深入解读OpenTelemetry分布式链路追踪:原理与实践指南 分布式系统在微服务架构下,服务调用链越来越复杂,追踪单次请求在各个微服务之间的执行情况成为运维与性能优化的关键。作为新一代开源标准,OpenTelemetry为分布式追踪、指标与…

【0基础PS】PS工具详解--图案图章工具

目录前言一、图案图章工具基础认知​二、工具选项栏参数详解​三、图案图章工具应用案例​总结前言 在 Adobe Photoshop 这一强大的图像处理软件中,图案图章工具是一个独具特色的功能,它允许用户利用预先定义好的图案进行绘画操作。 一、图案图章工具基…

剧本杀小程序系统开发:构建数字化剧本杀生态圈

在快节奏的现代生活中,人们越来越渴望在闲暇之余找到一种既能放松心情又能增进社交的方式。剧本杀,作为一种集推理、表演、社交于一体的新兴娱乐形式,恰好满足了这一需求。然而,随着市场的不断扩大,如何保持剧本杀的新…

【DL学习笔记】计算图与自动求导

计算图计算图(Computation Graph)是一种用于描述计算过程的图形化表示方法。在深度学习中,计算图通常用于描述 网络结构、运算过程 和数据流向。计算图是一种有向无环图,用图形方式来表示算子与变量之间的关系,直观高效…

大型地面光伏电站开发建设流程

​地面电站特特点:规模大,通常占用土地、水面等,地面式选址选项多,且不断拓展出新的用地模式,地面式选址集中在山体、滩涂、沼泽、戈壁、沙漠、受污染土地等闲置或废弃土地上。

除数博弈(动态规划)

爱丽丝和鲍勃一起玩游戏&#xff0c;他们轮流行动。爱丽丝先手开局。最初&#xff0c;黑板上有一个数字 n 。在每个玩家的回合&#xff0c;玩家需要执行以下操作&#xff1a;选出任一 x&#xff0c;满足 0 < x < n 且 n % x 0 。用 n - x 替换黑板上的数字 n 。如果玩家…

一起学springAI系列一:初体验

Spring AI是干嘛的官网最权威&#xff0c;直接粘贴&#xff1a;“Spring AI”项目旨在简化那些包含人工智能功能的应用程序的开发过程&#xff0c;同时避免不必要的复杂性。AI相关领域的功能对python的支持是最好的&#xff0c;相关供应商在出了啥功能的时候&#xff0c;都会优…

Ext JS极速项目之 Coworkee

ExtJS Coworkee 是什么? Ext JS 的 Coworkee 是一个由 Sencha 官方提供的完整员工管理应用示例,旨在展示 Ext JS 框架在企业级应用开发中的能力。 在线试用的地址是: https://examples.sencha.com/coworkee/#home 页面效果与布局 登录页面: 主页效果 左右分区结构:左…

飞算科技:原创技术重塑 Java 开发,引领行业数智化新浪潮

在科技革新的浪潮中&#xff0c;飞算科技作为一家坚持自主创新的数字科技企业&#xff0c;同时也是国家级高新技术企业&#xff0c;正深耕互联网科技、大数据、人工智能等前沿领域&#xff0c;为众多企业的数字化与智能化转型提供强劲动力。​飞算科技的成长轨迹&#xff0c;是…

cesium FBO(一)渲染到纹理(RTT)

一听到三维的RTT&#xff08;Render To Texture&#xff09;&#xff0c;似乎很神秘&#xff0c;但从底层实现一看&#xff0c;其实也就那样&#xff0c;设计API的哪些顶级家伙已经帮你安排的明明白白了&#xff0c;咱们只需要学会怎么用就可以了。我认为得从WebGL入手&#xf…

PNP机器人机器人学术年会展示灵巧手动作捕捉方案。

2025年8月1-3日&#xff0c;第六届中国机器人学术年会&#xff08;CCRS2025&#xff09;在长沙国际会议中心举行&#xff0c;主题“人机共融&#xff0c;智向未来”。PNP机器人与灵巧智能联合展出最新灵巧手模仿学习方案&#xff1a;基于少量示教数据即可快速复现复杂抓取动作&…

【45】C#入门到精通——C#调用C/C++生成动态库.dll及C++ 生成动态库.dll ,DllImport()方式导入 C++动态库.dll方法总结

文章目录1 C 生成动态库.dll2 C#调用C/C生成动态库.dll2.1 [DllImport()] 方式导入 C动态库.dll2.2 调用测试3 C/C 生成通用dll,改进3.1改进后.h3.2 .cpp3.2 C# 调用4 [DllImport()] 方式导入C生成的 .dll 总结4.1 指定路径导入4.2 .dll放在 执行目录下&#xff08;一定要放对&…

从协议栈到ath12k_mac_op_tx的完整调用路径

文章目录 从协议栈到ath12k_mac_op_tx的完整调用路径 1. 整体架构概览 2. 详细调用路径分析 2.1 应用层到Socket层 2.2 协议层处理 2.3 网络设备层到mac80211 2.4 mac80211发送入口 2.5 mac80211核心发送处理 2.6 mac80211发送核心处理 2.7 mac80211发送调度 2.8 最终驱动调用 …

WPFC#超市管理系统(4)入库管理

入库管理7. 商品入库管理7.2 入库实现显示名称、图片、单位7.3 界面设计7.3 功能实现7. 商品入库管理 数据库中StockRecord表需要增加商品出入库Type类型为nvarchar(50)。C#中的数据库重新同步StockRecord表在Entity→Model中新建枚举类型StockType namespace 超市管理系统.E…