数据库系列:InnoDB下实现高并发控制

1 介绍

并发控制是为了防止多用户并发使用数据库时造成数据错误和程序运行错误,保证数据的完整性。当多个事务并发地存取数据库时,就会产生同时读取和/或修改同一数据的情况。若对并发操作不加控制就可能会存取和存储不正确的数据,破坏数据库的一致性(Consistency)。因此,数据库中间件必须提供并发控制(Concurrency Control)机制能力,而MySQL的InnoDB引擎,很好的支持了这一块。

2 InnoDB并发控制

MySQL 是一个流行的关系型数据库管理系统,它支持多用户并发访问。并发控制是确保数据库一致性和完整性的重要机制。在 MySQL 中,有几种方法可以实施并发控制:

  • 读写锁(Read-Write Locks):MySQL 使用了读写锁来控制对数据的并发访问。读写锁是共享的,多个客户端可以同时持有读锁,但只有一个客户端可以持有写锁。当一个客户端获得写锁时,其他客户端无法获得读锁或写锁,直到写锁被释放。

  • 事务隔离级别 :MySQL 提供了不同的事务隔离级别,包括读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。较低的隔离级别允许更多的并发访问,但可能导致数据不一致;较高的隔离级别可以确保数据一致性,但会限制并发访问。

  • 锁等待和死锁:MySQL 提供了锁等待和死锁检测机制。当一个事务尝试获取一个已经被其他事务持有的锁时,MySQL 会阻塞等待,直到锁被释放。如果事务之间形成死锁,MySQL 会检测到并终止其中一个事务以解除死锁。

  • 分段锁定(Segmented Locking):MySQL 还支持分段锁定,它允许对数据库的特定部分进行锁定,而不是对整个数据库进行锁定。这对于处理大型数据集时非常有用,因为它可以减少锁定范围,提高并发性能。

  • 乐观并发控制(Optimistic Concurrency Control):MySQL 还支持乐观并发控制,它假设冲突不太可能发生,因此不会立即锁定数据。而是在更新时检查是否存在冲突,如果存在冲突,则进行适当的处理,比如回滚或重试。

  • 多版本并发控制(MVCC):MVCC允许在事务隔离级别下执行一致性读操作,以提高并发性能。

通过合理配置和使用上述机制,可以在 MySQL 中实现有效的并发控制,来保证在数据库中执行一致性和数据完整性。下面详细来说说通过并发控制保证数据一致性的常见手段:

  • 锁(Locking)

  • 数据多版本(Multi Versioning)

3 锁的基本实现

MySQL 使用锁来保持数据的一致性。在并发控制中,锁是用来防止多个事务同时对同一数据进行修改或删除,以保持数据的一致性。MySQL 中的锁机制包括共享锁和排他锁。锁的基本实现,一般是这样的:

  • 当用户对数据进行操作前,锁住,实施互斥,不允许其它任务的操作;

  • 当前操作完成后,释放锁之后,其他任务才可以执行;

但是存在一个问题,他的执行本质是串行的,无论读写,都无法并行,这样性能太差了,也不符合互联网高并发需求。于是MySQL 中的锁机制实现了共享锁和排他锁:

  • 共享锁(Shared Lock):多个事务可以同时持有共享锁,用于读取数据,但不允许修改数据。共享锁允许并发读取,提高了并发性能。

  • 排他锁(Exclusive Lock):只有一个事务可以持有排他锁,用于修改数据,不允许其他事务同时修改。排他锁会阻塞其他事务的读写操作,降低了并发性能。

简而言之就是:

共享锁之间不互斥,即读读可以并行,这样提高了数据读取的并发能力

排他锁与任何锁互斥,所以写读,写写不可以并行,其他线程的读写操作都在锁释放之后才能执行,这样对并发度是有较大影响的

所以说,单纯的锁机制,还是不满足需求,为了保证写任务没有完成之时,其他读的任务也可以并发执行,我们就需要使用另外一个能力来补充。那就是数据多版本(Multi Versioning)

4 数据多版本的实现原理

MySQL的并发控制是通过多版本并发控制(MVCC)实现的。MVCC允许在事务隔离级别下执行一致性读操作,以提高并发性能。在MySQL的MVCC中,每个数据行都有多个版本,每个版本都表示该行在不同时间点的状态。当一个事务读取数据时,它只看到该事务开始之前存在的数据版本,而不是当前最新的数据版本。这种方式允许并发读取多个数据版本,而不会相互阻塞,进一步提高并发的效果。详细拆分开来,读写同步执行的原理是这样的:

  • 执行写任务发时,Clone一份数据,打上新的版本号,与原版本号区分

  • 写任务实际操作的是克隆那个版本的数据,直至操作并提交完成后

  • 读任务可以并发执行,持续读取,读的是原版本的数据,并不会造成阻塞

image

如图所示,可以分成这几个步骤去解读:

  1. 初始数据版本为V1.0

  2. T1发起了一个写任务,这时候把数据clone了一份,进行修改,版本变为V2.0,这时候修改进行中,任务还未完成

  3. T2并发了一个读任务,依然读的是V1.0版本的数据

  4. T3又并发了一个读任务,依然不会阻塞,读的还是V1.0的版本

  5. 这时候数据修改,V1.0的数据变为V2.0的数据

  6. T4这时候发起的度任务,读到的就是V2.0的数据了

从这边可以看出,数据多版本,读写之间不需要阻塞,能够极大提高任务的并发能力。

  • 普通意义上的锁机制,本质是串行执行,效率十分低下

  • 读写锁,可以实现读读并发,但是写读依然是互斥的,也不符合互联网的机制

  • 数据多版本(Multi Versioning),才是实现读写并发的要素

5 MySQL 数据多版本的相关实现

5.1 概念介绍

在MySQL的InnoDB存储引擎中,使用MVCC(多版本并发控制,Multiversion Concurrency Control)实现多版本控制。MVCC的实现主要基于undo日志、redo日志、rollback segment 回滚存储区间、和read view。undo日志用于回滚操作,而read view用于生成数据行的历史版本。通过这种方式,InnoDB实现了非阻塞的一致性读操作。

  • redo日志数据库事务提交后,必须将更新的数据刷到磁盘上,以保证ACID特性。磁盘随机写性能较低,且过度频繁的刷盘,会极大影响数据库的吞吐量。优化方式是将修改行为先写到redo日志里,这样随机就变成了有序性,再按照时间周期将数据持久化到磁盘上,极大提高了性能。另外一方面,即使数据库崩溃,恢复之后也可以从redo日志里面获取操作Log,重新提交事务操作,然后刷盘,最终保证数据的一致性。

  • undo日志数据库事务未提交时,会将事务修改数据的Mirror Data(修改前的版本 )存放到 Undo Log中,它的主要作用是在事务执行过程中,如果发生错误或者需要回滚操作,可以通过Undo Log中的记录来撤销已经执行的操作,恢复数据到事务开始之前的状态。另外一方面,数据库奔溃时,也可以使用undo日志,撤销未提交事务,保证事务的ACID特性。

  • insert操作:undo日志存储新数据的PK(ROW_ID),回滚时执行删除即可。

  • delete/update操作:undo日志存储旧数据row(整行数据),回滚时直接恢复。

  • rollback segmentRollback Segment(回滚存储区)是数据库中的一部分存储空间,用于临时保存当数据库数据发生改变时的先前值。它主要有两个作用:

  • 通过Rollback操作来取消数据操作,使之恢复到改变之前的原始值,在transaction的过程才有效。如果执行了commit命令,那么Rollback Segment里面的值就会标识为失效,数据的改变将永久化。

  • select读取的同时另一个事务也在修改这个表的值,那么select出来的数据是修改前的值,因为修改之前的原数据存入到了Rollback Segment中,所以不会被阻塞到。

5.2 示例说明

5.2.1 初始数据

# 表结构
t_userinfo(id PK, name, sex, age);# 默认数据
1,Brand,0,22
2,Helenlyn,1,19
3,Sol,0,21

image

先初始化一个默认的表,里面模拟几条数据。此时没有任何的事务未提交操作,所以回滚段是空的,如上图。

5.2.2 事务操作示例

start transaction;
delete from t_userinfo where id = 1;
update t_userinfo set name = 'Helenlyn...' where id = 2;
insert  into t_userinfo(name, sex, age) valus ('Lili', 1, 18);

还未执行commit 或者 rollback,所以事务处于未提交的状态

image

综上,我们可以看出Commit之前我们进行如下操作:

  • 正式提交删除前,id=1的数据作为旧版本的数据,进入了回滚存储区;

  • 正式提交修改前,id=2的数据作为旧版本的数据,进入了回滚存储区;

  • 新插入的数据 ('Lili', 1, 18), id= 4,在正式提交之前,也进入了回滚段;

我们上面说了,不是所有的操作最终都会commit,如果失败,事务rollback,就可以通过回滚存储区中的undo日志对操作进行回滚。

如果成功commit,则整体提交成功了

image

可以看到:

  • id=1 数据删除成功;

  • id=2 字段更新成功;

  • id=4 数据行插入成功;

  • 回滚存储区相关日志清掉

如果失败并执行rollback,则全部回滚

image

  • 数据删除的恢复了

  • 被修改的旧数据也恢复

  • 新增写入的数据删除

  • 回滚存储区相关日志清掉

6 总结

  • MySQL实现并发控制,保证数据一致性的方法有锁,数据多版本等

  • 普通锁串行,读写锁读读并行,Multi Versioning 读写并行;

  • redo日志保证已提交事务的ACID特性, undo日志用来回滚未提交的事务,rollback segment 为临时回滚存储区;

  • InnoDB是基于多版本并发控制的存储引擎;

  • InnoDB用的多版本是快照读不加锁,所有select都是快照读,这些数据不会被修改,并发性能特别高;

文章转载自:Hello-Brand

原文链接:https://www.cnblogs.com/wzh2010/p/17794217.html

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

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

相关文章

web前端(第二次作业)

1、计算用户指定的数值内的奇数和。例如用户输入的是 10&#xff0c;则计算 1 3 5 7 9 的和 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script>var nprompt("请输入数值&#xff1a;&…

基于开源组件自主开发工作流引擎系统

目前基于Java语言开发的主流开源工作流引擎有osworkflow、jbpm、activiti、flowable、camunda。其中osworkflow、jbpm技术较老已经过时&#xff0c;activiti包括activiti5、activiti6、activiti7三个版本&#xff0c;flowable分开源版和商业版&#xff0c;camunda包括camunda7和…

ETCD 未授权访问实战案例

1、发现 etcd 未授权。 https://xxx200:2379/v2/keys 2、尝试在etcd里查询管理员的token&#xff0c;然后使用该token配合kubectl指令接管集群。 proxychains ./etcdctl --insecure-transportfalse --insecure-skip-tls-verify --endpointshttps://xxx0:2379/ get / --prefix…

12月威胁态势 | 0day占比超82%!两大勒索家族“均分天下”

近日&#xff0c;亚信安全正式发布《亚信安全2023年12月威胁态势报告》&#xff08;以下简称“报告”&#xff09;报告显示&#xff0c;12月份新增安全漏洞1511个&#xff0c; APT 攻防较量日趋复杂&#xff0c;成为网络空间与现实地缘政治融汇交织新的风险点&#xff1b;监测发…

精品量化公式——“主力拉升”,信号出现股价随时准备拉升

► 日线表现 代码评估 技术指标代码评估&#xff1a; 计算变量: HSL1:5;&#xff1a;设置了一个常数变量。 VAR0 到 VAR6&#xff1a;这些变量通过复杂的计算公式来定义&#xff0c;通常涉及收盘价、最高价、最低价、开盘价以及它们的历史数据。 技术指标和信号: 线: VAR6 …

使用Dockerfile构建镜像的详细指南

目录 前言 一、什么是 Dockerfile 二、使用 Dockerfile 定制镜像 开始构建镜像 上下文路径 三、指令详解 四、构建阿里云仓库 前言 Docker是一种流行的容器化平台&#xff0c;可以帮助开发人员和运维团队更轻松地构建、发布和运行应用程序。在Docker中&#xff0c;镜像是…

虾皮开通:如何在虾皮(Shopee)平台上开通店铺详细步骤

在全球电商市场的竞争中&#xff0c;越来越多的卖家选择在虾皮&#xff08;Shopee&#xff09;平台上开设店铺。作为东南亚地区最大的电子商务平台之一&#xff0c;虾皮提供了一个便捷的销售渠道&#xff0c;吸引了数百万的买家和卖家。如果您想在虾皮上开设自己的店铺&#xf…

使用官方构建工具来创建一个vue3的项目

当你使用 Vite 构建项目时&#xff0c;可能会发现在命令行界面无法选择是否包含 TypeScript 等其他基础配置。此外&#xff0c;使用 vue create 命令创建项目时&#xff0c;默认会使用 vue-cli&#xff0c;但项目启动等过程可能较慢。在这种情况下&#xff0c;你可以参考以下步…

Matlab论文插图绘制模板第135期—隐函数曲面图(fimplicit3)

在之前的文章中&#xff0c;分享了Matlab隐函数折线图的绘制模板&#xff1a; 进一步&#xff0c;再来分享一下隐函数曲面图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。有需要的朋友可以关…

CG Magic分享3dmax渲染太亮问题如何解决?

3D Max软件渲染时&#xff0c;渲染问题较多也是正常的&#xff0c;对于行业小白来说&#xff0c;渲染问题多也是能理解的&#xff0c;因为&#xff0c;小编经常在问答中&#xff0c;看到一些网友提问&#xff0c;3dmax渲染太亮怎么办&#xff1f; 3dmax渲染太亮了怎么回事&…

pycharm的使用技巧

1.新建文件时,自动生成代码 settings->editor->file and code templates,选择python script ${NAME} 文件名 ${DATE} 日期 2.自动补齐自定义段落 settings->editor->live templates,在右侧点击+号,添加自定义的内容 完成之后,在下方勾选python 3.修改注释的…

就业难,程序员年纪大了怎么办?

程序员作为一项技术工种&#xff0c;年龄的确可能成为职业生涯发展的一大障碍。但年龄并不是决定职业生涯终点的唯一因素&#xff0c;只要保持对技术的热爱、不断学习提升&#xff0c;并积极调整心态&#xff0c;仍有许多出路可以选择。 1. 职业发展路线 随着年龄的增长&#…

系分备考计算机网络传输介质、通信方式和交换方式

文章目录 1、概述2、传输介质3、网络通信4、网络交换5、总结 1、概述 计算机网路是系统分析师考试的常考知识点&#xff0c;本篇主要记录了知识点&#xff1a;网络传输介质、网络通信和数据交换方式等。 2、传输介质 网络的传输最常见的就是网线&#xff0c;也就是双绞线&…

开源内容管理系统Wagtail本地安装运行并结合内网穿透实现公网访问

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS&#xff0c;建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&#xf…

Arduino| 开发板介绍、编程入门(引脚信号的输入输出)

Arduino开发板介绍、编程入门 开发板介绍编程入门setup和loop函数引脚信号输入输出数字信号模拟信号 开发板介绍 下面是一张Ardunio Uno R3的引脚图&#xff0c;包含14个数字引脚、6个模拟输入、电源插孔、USB连接和ICSP插头等。 14个数字引脚&#xff1a; Serial&#xff…

React项目搭建流程

第一步 利用脚手架创建ts类型的react项目&#xff1a; 执行如下的命令&#xff1a;create-react-app myDemo --template typescript &#xff1b; 第二步 清理项目目录结构&#xff1a; src/ index.tsx, app.txs, react-app-env.d.ts public/index.ht…

基于树莓派5(Raspberry Pi 5)的高性能工业平板电脑升级版!

​ 上海晶珩继推出首个搭载 Raspberry Pi 5 的平板电脑ED-HMI3010系列后&#xff0c;又推出了具备高性能和多功能特性的 Raspberry Pi 5 的平板电脑ED-HMI3020系列。ED-HMI3020支持选择7英寸和10.1英寸两种尺寸的触摸屏&#xff0c;可选配 M.2 NVMe SSD 存储扩展&#xff0c;提…

CSS实现元素水平垂直居中几种方案

方案一&#xff1a;利用 display: inline-block; vertical-align: middle; <div class"box"> <div></div> <span></span> </div> .box { width: 500px; height: 500px; background-color: red; text-align: center; } .box div …

修改vscode内置Vue VSCode Snippets(代码片段)

打开插件文件夹 文件夹名是 "作者名.vscode-插件名-版本号"组成的. C:\Users\Administrator\.vscode\extensions\sdras.vue-vscode-snippets-3.1.1\snippets 打开vue.json "prefix": "vbase" 就是代码块的关键词,输入vbase就会提示代码块 …

调试ad5245的总结

调试ad5245的总结 这个ad5245是通过IIC与FPGA进行通信的&#xff0c;首先要理解IIC协议。 经验总结&#xff1a; 1、SCL和SDA端的要有上拉电阻&#xff0c;且上拉电阻能正常工作&#xff1b; 2、要往SDA数据线上写三个字节才能调节ad5245的电阻值&#xff0c;第三个字节就是…