【数据库】数据库事务原理
事务特性
https://blog.csdn.net/zxcyxg123/article/details/132020499
MVCC
MVCC(Multi-Version Concurrency Control),即多版本并发控制,是一种并发控制的方法,主要用于数据库管理系统中,以实现对数据库的并发访问。以下是对MVCC的详细解释:
-
目的:MVCC的主要目的是允许多个用户同时访问数据库,而不会导致数据冲突和不一致性。它通过在系统中维护多个版本的数据来实现这一目的。
-
工作原理:
- 当每个事务启动时,系统会为其分配一个唯一的事务ID。
- 当一个事务要访问数据库中的某个数据时,系统会检查该数据的版本号和事务的启动时间。如果该数据的版本号早于该事务的启动时间,则该事务可以访问该数据;否则,该事务需要等待其他事务完成对该数据的访问。
- 当一个事务修改某个数据时,系统会为该数据创建一个新版本号,并将修改后的数据存储在一个新的位置。同时,旧版本的数据仍然可用供其他事务访问。
- 当一个事务提交时,系统会将其所做的所有修改操作都合并到数据库中,同时删除旧版本的数据。
-
优点:
- 提高并发访问数据库的效率。
- 减少数据冲突和不一致性的发生。
- 避免了在写操作进行时锁定整个表或记录,从而提高了系统的吞吐量和性能。
- 使得事务可以看到一个一致的数据视图,不管它们需要运行多久。
-
使用场景:
- 读多写少的系统:在这种系统中,冲突的可能性较小,因此MVCC能提供较高的并发性能。
- 实时系统:在实时系统中,读取的延迟需要尽可能地小。MVCC能通过读取旧的数据版本,避免由于等待写操作而产生的延迟。
- 分布式系统:在分布式系统中,因为网络延迟和节点故障的存在,事务可能需要较长的时间才能完成。MVCC能使得这些长时间的事务不会阻塞其他的读或写操作。
-
实现方式:不同的数据库系统对MVCC的实现方式可能有所不同。例如,在MySQL的InnoDB存储引擎中,MVCC(多版本并发控制)的实现方式独特而高效。InnoDB通过为每一行记录添加两个额外的隐藏字段来实现MVCC,这两个字段并不直接存储数据被创建或删除的实际时间,而是存储了与这些事件相关联的系统版本号(通常称为“trx_id”和“roll_ptr”)。
“trx_id”字段用于表示最近一次修改该行记录的事务ID。每当一个事务修改某一行数据时,该行的“trx_id”字段就会被更新为该事务的ID。
“roll_ptr”字段是一个指向回滚段(undo log)中旧版本数据的指针。当事务修改数据时,旧的数据版本会被保存在回滚段中,并通过“roll_ptr”与新版本的数据相关联。这样,其他事务在需要读取该行数据的旧版本时,就可以通过“roll_ptr”找到相应的回滚段记录。
通过这种方式,InnoDB能够同时支持多个事务并发访问同一行数据,而无需进行加锁操作。每个事务都可以读取到该行数据的一个“快照”,这个“快照”是该事务开始时刻该行数据的版本。即使其他事务在此期间修改了该行数据,也不会影响到当前事务读取的数据版本。
例子
老袁的账户余额100元,老张转了100元给老袁,老袁消费了50元,同时发生
Oracle
默认隔离级别:读已提交
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 | |
select balance from user_account where user_name = 'oldYuan';// 100 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 200 | |
提交事务 |
看这个例子(错误)
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 | |
update user_account set balance = balance - 50 where user_name = 'oldYuan';// 50 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 200 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 50 |
正确的如下
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 写锁 | |
select balance from user_account where user_name = 'oldYuan';// 100 | |
update user_account set balance = balance - 50 where user_name = 'oldYuan';// 阻塞 | |
提交事务 释放写锁 | …… |
update user_account set balance = balance - 50 where user_name = 'oldYuan';// 200 - 50 = 150 | |
提交事务 |
MySql
默认隔离级别:可重复读
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 100 | |
提交事务 |
看这个例子(错误)
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 100 | |
update user_account set balance = balance - 50 where user_name = 'oldYuan'; // 100 - 50 = 50? | |
提交事务 |
正确如下
事务A | 事务B |
开启事务 | 开启事务 |
select balance from user_account where user_name = 'oldYuan';// 100 | select balance from user_account where user_name = 'oldYuan';// 100 |
update user_account set balance = balance + 100 where user_name = 'oldYuan';// 200 | |
提交事务 | |
select balance from user_account where user_name = 'oldYuan';// 100 | |
update user_account set balance = balance - 50 where user_name = 'oldYuan';// update执行时,会使用最新版本的数据,结果是150,正确 | |
提交事务 |
数据库锁
在数据库中,排他锁(Exclusive Lock)和共享锁(Shared Lock)是两种常见的锁类型,它们用于控制多个事务对同一资源的并发访问,以保证数据的一致性和完整性。
一、排他锁(Exclusive Lock)
排他锁,又称为写锁或独占锁,是一种基本的锁类型。当某个事务对数据对象(如表、行等)加上排他锁后,其他事务将无法再对该数据对象加任何类型的锁,直到持有排他锁的事务释放该锁。这就意味着持有排他锁的事务在锁释放前可以独占地读取和修改数据,而其他事务在此期间无法访问该数据。
排他锁的主要特点包括:
- 独占性:持有排他锁的事务可以独占地读取和修改数据,其他事务无法再对该数据加任何类型的锁。
- 阻塞性:如果其他事务请求对已被加排他锁的数据进行访问,将会被阻塞,直到持有排他锁的事务释放该锁。
二、共享锁(Shared Lock)
共享锁,又称为读锁,是一种允许其他事务并发读取数据的锁类型。当某个事务对数据对象加上共享锁后,其他事务可以并发地读取该数据,但任何事务都不能获取数据上的排他锁,直到已释放所有共享锁。
共享锁的主要特点包括:
- 并发读取:多个事务可以同时持有同一数据对象的共享锁,从而并发地读取数据。
- 非独占性:持有共享锁的事务不能修改数据,也不能阻止其他事务获取该数据的共享锁。但如果有事务请求对该数据加排他锁,将会被阻塞,直到所有共享锁都被释放。
相关文章:

【数据库】数据库事务原理
事务特性 https://blog.csdn.net/zxcyxg123/article/details/132020499 MVCC MVCC(Multi-Version Concurrency Control),即多版本并发控制,是一种并发控制的方法,主要用于数据库管理系统中,以实现对数据库…...

LeetCode 106.从中序与后序遍历序列构造二叉树
LeetCode 106.从中序与后序遍历序列构造二叉树 1、题目 题目链接:106. 从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并…...

Python中的compile()函数,动态编译代码的艺术
关注公众号【一点sir】,领取编程资料。 简介 在Python编程中,compile()函数是一个强大的工具,它允许开发者将字符串形式的Python代码动态编译成字节码。这为执行动态生成或从外部源接收的代码提供了极大的灵活性。这些字节码随后可以被Pytho…...

【考研数学】汤家凤“免单“数学题被吐槽‘太难’,老汤回应「怎么还有脸笑」,网友:这些题有毒!
我看了汤家凤老师出的几道题,实际上对于考研的同学来说,确实是送分题 第一个是三角函数变换中的万能公式;第二个e^x的泰勒展开公式;第三个是第一类重要极限。只要复习过,那基本上都能正常做出来。 至于汤家凤老师说「…...

在另外一个页面,让另外一个页面弹框显示操作(调佣公共的弹框)
大概意思是,登录弹框在另外一个页面中,而当前页面不存在,在当前页面中判断如果token不存在,就弹框出登录的弹框 最后一行 window.location.href … 如果当前用户已登录,则执行后续操作(注意此处,可不要)...

如何利用IPIDEA代理IP优化数据采集效率?
一、 前言二、 IPIDEA介绍三、体验步骤四、实战训练五、结语 一、 前言 在全球化与信息化交织的当代社会,数据已成为驱动商业智慧与技术革新的核心引擎。网络,作为信息汇聚与交流的枢纽,不仅是人们获取知识的窗口,更是商业活动与技…...

Rpcx (一):详解【介绍、基础示例 demo】
一.rpcx介绍 1.1 rpc是什么 远程过程调用的通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程。如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用。简单地说就是能使应用像调用本地…...

对数据进行标准化和归一化
数据的形式:保存在CSV中,第一列为姓名,第二列之后为特征。 标准化 输入文件的路径,设置保存转化后的文件路径 import pandas as pd from sklearn.preprocessing import StandardScaler# 读取CSV文件 data pd.read_csv(rC:\User…...

【从零开始学架构 架构基础】二 架构设计的复杂度来源:高性能复杂度来源
架构设计的复杂度来源其实就是架构设计要解决的问题,主要有如下几个:高性能、高可用、可扩展、低成本、安全、规模。复杂度的关键,就是新旧技术之间不是完全的替代关系,有交叉,有各自的特点,所以才需要具体…...

OpenHarmony 实战开发——3.1 Release + Linux 原厂内核Launcher起不来问题分析报告
1、关键字 Launcher 无法启动;原厂内核;Access Token ID; 2、问题描述 芯片:rk3566;rk3399 内核版本:Linux 4.19,是 RK 芯片原厂发布的 rk356x 4.19 稳定版内核 OH 版本:OpenHa…...

小猫咪邮件在线发送系统源码,支持添加附件
一款免登录发送邮件,支持发送附件,后台可添加邮箱,前台可选择发送邮箱 网站数据采取本地保存,所以使用前请给网站修改权限,否则很多功能将无法使用 安装教程: 1.上传服务器或者主机 2.登录后台,添加发送…...

Django REST framework(DRF)是什么?
Django REST framework(DRF)是什么? Django REST framework(简称DRF)是一个强大且灵活的工具包,用于构建Web API。它是基于Django(一个高级Python Web框架)构建的,提供了…...

用hMailServer+roundcubemail+宝塔安装配置一个自己的邮箱服务
用hMailServerroundcubemail安装配置一个自己的邮箱服务 1、准备工具与资料: 云服务器一台 基础配置就行 2核4G。域名一个 以下用lizipro.cn示例。hMailServer安装包roundcubemail安装包异常处理插件补丁: libmysql.zip 2、hMailServer服务安装&#…...

ctfshow 框架复现
文章目录 web 466web 467web 468web469web 470web 471web 472web 473web 474web 475web 476 web 466 Laravel5.4版本 ,提交数据需要base64编码 代码审计学习—Laravel5.4 - 先知社区 (aliyun.com) 用第二条链子 反序列化格式 /admin/序列化串base64<?php na…...

【Linux-IMX6ULL-DDR3简介测试-RGBLCD控制原理】
目录 1. DDR3 简介1.1 前要基本概念RAM & ROM 2. DDR3测试及初始化3. RGBLCD简介及控制原理3.1 RGBLCD简介3.2.1 RGB LCD时序3.2.2 像素时钟(800*400分辨率)3.2.2 显存(800*400分辨率) 3.3 RGBLCD的控制3.3.1 DOTCLK 硬件接口…...

贪心算法-----柠檬水找零
今日题目:leetcode860 题目链接:点击跳转题目 分析: 顾客只会给三种面值:5、10、20,先分类讨论 当收到5美元时:不用找零,面值5张数1当收到10美元时:找零5美元,面值5张数…...

MySQL技能树学习
在MySQL中,DDL(数据定义语言)用于定义数据库对象(如表、索引、视图等),DML(数据操纵语言)用于操作数据库中的数据(如插入、更新、删除数据),DQL&a…...

java 动态代理详解
cglib 动态代理 介绍 CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB 是一…...

Web路径专题
文章目录 Web路径专题什么是路径?绝对路径相对路径 如何使用路径?使用base标签 注意事项小结 Web路径专题 在Web开发中,路径是一个非常重要的概念。路径用来定位资源的位置,包括文件、目录、网页等。在本文中,我们将介…...

解决vue3项目打包后部署后某些静态资源图片不加载问题
目录 问题 原因 解决方案 问题 开发完项目打包并部署 然后访问时发现导航栏背景图片没加载 打开浏览器控制台发现这张图片报错404 原因 可能是因为在部署后的服务器环境中对中文文件名的支持不完善。服务器在解析 URL 时可能无法正确识别或编码中文字符,导致无…...

传感网应用开发教程--AT指令访问新大陆云平台(ESP8266模块+物联网云+TCP)
实现目标 1、熟悉AT指令 2、熟悉新大陆云平台新建项目 3、具体目标:(1)注册新大陆云平台;(2)新建一个联网方案为WIFI的项目;(3)ESP8266模块,通过AT指令访问…...

项目提交到空的git仓库流程
流程: # 初始化 Git 仓库 git init # 如果遇到 "detected dubious ownership" 的错误,可以添加 safe.directory 配置以解决 git config --global --add safe.directory T:/project/xxx # 将当前目录下的所有文件添加到 Git 暂存区 git add . …...

【Python】在Windows Server上部署Flask后端服务器
想要在Windows Server上部署flask应用,当然不能只下一个anaconda配完环境之后直接启动py文件,这样的话后台会有一段警告: * Serving Flask app app* Debug mode: off WARNING: This is a development server. Do not use it in a production …...

机器学习作业4——朴素贝叶斯分类器
目录 一、理论 一个例子: 二、代码 对于代码的解释: 1.fit函数: 2.predict函数: 三、实验结果 原因分析: 一、理论 朴素贝叶斯分类器基于贝叶斯定理进行分类,通过后验概率来判断将新数据归为哪一类。通过利用贝…...

BUU-[GXYCTF2019]Ping Ping Ping
考察点 命令执行 题目 解题 简单测试 ?ip应该是一个提示,那么就测试一下?ip127.0.0.1 http://0c02a46a-5ac2-45f5-99da-3d1b0b951307.node4.buuoj.cn:81/?ip127.0.0.1发现正常回显 列出文件 那么猜测一下可能会有命令执行漏洞,测试?ip127.0.…...

代码随想录Day 41|Leetcode|Python|198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
198.打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个…...

【吴恩达机器学习-week2】多个变量的特征缩放和学习率问题
特征缩放和学习率(多变量) 目标 利用上一个实验中开发的多变量例程在具有多个特征的数据集上运行梯度下降探索学习率对梯度下降的影响通过 Z 分数归一化进行特征缩放,提高梯度下降的性能 import numpy as np np.set_printoptions(precisio…...

C#字符串的拼接
在C#中有多种拼接字符串的方式,今天小编就分享一些比较常用的。 方法1 string str "123"; str str "456"; 运行结果: "123456" 方法2 字符串与数字拼接 会将数字默认为字符串进行拼接 string str "123"; str str 1;…...

哈希表Hash table
哈希表是根据关键码的值而直接进行访问的数据结构。 数组就是⼀张哈希表。 哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示: 那么哈希表能解决什么问题呢,一般哈希表都是用来快速判断⼀个元素是…...

jdk8新特性----Lambda表达式
一、介绍 1、简介 Java的Lambda表达式是Java 8引入的一个特性,它支持函数式编程,允许将函数作为方法的参数或返回值,从而简化了匿名内部类的使用,并提供了对并行编程的更好支持。 2、语法 Lambda表达式的使用前提是存在一…...