数据库系统概论:事务与并发一致性问题
随着网络应用的普及,数据库并发问题变得越来越重要。数据库并发指的是多个用户或进程同时访问和操作数据库的能力。它是数据库系统性能优化的重要方面,旨在提高系统的吞吐量和响应时间,以满足多用户同时访问数据库的需求。然而,这种能力也带来了数据一致性
、隔离性
和性能
等方面的挑战。
事务
事务(Transaction)是指一系列数据库操作组成的逻辑单元,是并发控制的基本单位。事务具有(ACID特性)原子性、一致性、隔离性和持久性等属性,是保证数据一致性和事务并发控制的重要手段。
在关系数据库中,一个事务可以是一条 SQL 语句、一组 SQL 语句或整个程序。事务和程序是两个概念。一般地讲,一个程序中包含多个事务。事务的开始与结束可以由用户显式控制。如果用户没有显式地定义事务,则由数据库管理系统按默认规定自动划分事务。
ACID
ACID
是指数据库事务的四个特性:
原子性
(Atomicity)一致性
(Consistency)隔离性
(Isolation)持久性
(Durability)。
这些特性保证了在事务中,所有操作要么全部成功提交(COMMIT),要么全部撤销回滚(ROLLBACK),不允许只部分执行,并且数据库始终处于一致性状态,即使系统故障或者其他异常情况也不会破坏数据的完整性。
-
原子性
(Atomicity):确保了事务中的所有操作不可分割,要么全部提交成功,要么全部失败回滚。回滚可以用日志来实现,日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可
-
一致性
(Consistency):表示事务必须把数据库从一个一致状态转变为另一个一致状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。-
当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。
-
如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态(不一致的状态)。
-
-
隔离性
(Isolation):确保了多个事务并发执行时不会相互干扰,即一个事务所做的修改在最终提交前,对其他事务是不可见的。如果一项操作无法完成或出现了意外故障,整个事务就会失败,并且所有对数据库所做的修改都会被回滚。
-
持久性
(Durability):是指一旦事务提交,其执行的结果就会持久保存到数据库中,不会因系统故障、崩溃或其他错误导致执行数据丢失。可以通过数据库备份和恢复来实现,在系统发生崩溃时,使用备份的数据库进行数据恢复。
要保证事务的正确性和数据的一致性,需要在编写数据库操作时遵循一些基本的事务处理原则,例如保证事务的独立性、粒度合理、尽量减少锁竞争等。
事务特性的关系
ACID 的四个特性是相互关联和互相依赖的
-
只有满足一致性,事务的执行结果才是正确的。
-
在无并发的情况下,事务串行执行,隔离性一定能够满足。此时只要能满足原子性,就一定能满足一致性。
-
在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。
-
事务满足持久化是为了能应对数据库崩溃的情况。
事务运行方式
事务的运行方式主要分为两种方式:
-
串行:每个时刻只有一个事务运行
串行的优点是实现简单,容易保证事务的一致性;但缺点是效率低。
-
并行:同一时刻可以有多个事务同时运行
并行的优点是效率高,可提高整个系统的吞吐量,减少平均响应时间;但缺点是会导致数据库的不一致性。
在单处理系统中,所谓的并行实际上是宏观上的并行运行,微观上的串行运行,即交叉并发
允许多个用户同时使用同一个数据库的数据库系统称为多用户数据库系统,在这种系统中,同一时刻并发运行的事务数量相当庞大。
假设有两个事务 S S S 和 T T T,其中 S S S 有 m m m 条指令, T T T 有 n n n 条指令,且每个事务内部指令的相对顺序不能错乱,那么可能的执行顺序有 R R R 种: R = C m + n m = C m m + n = ( m + n ) ! m ! n ! R=C^m_{m+n} = C^{m+n}_m=\frac{(m+n)!}{m!n!} R=Cm+nm=Cmm+n=m!n!(m+n)!
调度
调度:事务的一次执行顺序称为一个调度,表示事务的指令在系统中执行的时间顺序,一组事务的调度必须保证:包含了所有事务的操作指令、一个事务中指令的顺序必须保持不变。
调度又分为串行调度和并行调度:
-
串行调度:属于同一事务的指令紧挨在一起执行,对于有 n n n 个事务的事务组,可以有 n ! n! n! 个有效调度
-
并发调度:来自不同事务的指令可以交叉执行。并发调度有可能会导致错误结果,仅当并发调度等价于某个串行调度时,则称该并发调度时可串行化的、正确的。
并发一致性问题
在并发环境下,可能会出现并发一致性问题,并发一致性问题是指在数据库或分布式系统中,当多个事务或操作并发执行时,由于事务的隔离性难以完全保证,导致数据的一致性和完整性受到破坏的现象。
这些问题主要包括 脏读
、不可重复读
、幻读
以及 丢失修改
等,可能导致数据库中的数据变得不一致。
读脏数据
脏读
(Dirty Read):通常情况下,读取数据的事务会等待修改数据的事务提交,以便确保数据的一致性。一个事务读取了另一个未提交的事务所做的修改,然后在另一个事务回滚时,读取的数据就变得无效、不一致。脏读可能导致不可靠的数据和错误的决策。
脏读可能导致严重的问题,它可能会使应用程序基于错误的数据做出错误的决策。例如,如果一个银行应用程序在脏数据的情况下对银行帐户余额进行计算,则可能会导致银行资金的混乱。
不可重复读
不可重复读
(Non-repeatable Read):一个事务在同一查询中多次读取同一行数据时,得到的结果不一致。在同一个事务,读取的过程中,由于其他事务修改了数据,同一查询可能返回不同的结果。
情况实例:
-
事务 A 开始并执行
SELECT
语句,读取了某一行的数据。 -
事务 B 修改了该行数据,并提交事务。
-
事务 A 再次执行相同的
SELECT
语句,读取同一行数据,但是此时得到的结果与之前读取的结果不一致。
不可重复读可能对应用程序逻辑造成困扰,可能导致数据的不一致,特别是对于需要多次读取数据并进行比较或计算的场景。
例如,一个订单系统中,一个事务读取了某个订单的金额,在执行过程中,另一个事务对订单金额进行了修改,导致两次读取的金额不一致,进而影响了订单的计算结果。
幻读
幻读
(Phantom Read):在同一个事务中,同一查询多次执行,得到的结果集不一致。这是因为在读取的过程中,其他事务插入或删除了符合查询条件的数据。导致再次执行同一查询时出现新的数据行或少了一些数据行。
可以理解为,幻读
是一种比 不可重复读
更严重的数据不一致情况。
-
事务A 开始并执行
SELECT
语句,读取了表中的某几行数据。 -
事务B 插入了符合查询条件的一行数据,并提交事务。
-
事务A 再次执行相同的
SELECT
语句,读取相同的几行数据,但是此时得到的结果集中出现了新的一行数据,事务A 读取到的就是脏数据。
幻读可能导致数据的不完整。在高并发环境下,串行化隔离级别可能导致性能问题。因此,需要根据具体的业务需求和性能考量选择合适的隔离级别,以避免幻读的问题。
与不可重复读相比,幻读主要是针对批量数据的插入和删除操作,不仅会导致对数据的读取不一致,还可以对其它业务操作造成一定的困扰。
例如,在一个网上商城系统中,一个事务读取某一类商品的所有库存,使用返回的结果更新了前端页面的销售数量,此时,客户来了几个下单,由不同的事务进行插入操作,导致前端页面展示的库存数量不一致,进而影响了用户体验和商城的信誉。
丢失更新
丢失更新
(Lost Update):由于并发事务的执行,两个事务同时对相同的数据执行更新操作,但是其中一个事务的更新结果被另一个事务覆盖,从而丢失了其中一个事务的更新。这可能导致数据的丢失和覆盖。
当多个事务同时对同一数据进行修改时,如果不采取适当的并发控制措施,就可能导致丢失更新的问题:
-
事务A 读取一行数据,并将其存储在本地缓存中。
-
事务B 读取同一行数据,也将其存储在本地缓存中。
-
事务A 修改了该行数据,并将其更新到数据库中。
-
事务B 修改相同行数据,此时使用的是之前读取到的旧值,然后将其更新到数据库中。
-
结果是事务B 的修改覆盖了事务A 的修改,事务A的更新操作被丢失。
这种情况下,事务B 覆盖了事务A 的更新,最终导致数据的一致性问题。
相关文章:

数据库系统概论:事务与并发一致性问题
随着网络应用的普及,数据库并发问题变得越来越重要。数据库并发指的是多个用户或进程同时访问和操作数据库的能力。它是数据库系统性能优化的重要方面,旨在提高系统的吞吐量和响应时间,以满足多用户同时访问数据库的需求。然而,这…...
Python编程基础:元组类型、字典类型、集合类型
目录 元组类型创建/删除元组访问/操作元组元组生成式字典类型创建/删除字典访问/操作字典字典相关函数集合类型创建/删除集合集合相关操作符访问/操作集合元组类型 元组是Python中内置的不可变序列,这是它跟列表的不同之处,它没有一系列增删改等操作,只可以使用索引和for循环…...

day2 单机并发缓存
文章目录 1 sync.Mutex2 支持并发读写3 主体结构 Group3.1 回调 Getter3.2 Group 的定义3.3 Group 的 Get 方法 4 测试 本文代码地址: https://gitee.com/lymgoforIT/gee-cache/tree/master/day2-single-node 本文是7天用Go从零实现分布式缓存GeeCache的第二篇。 …...

ECMP等价多路由机制,大模型训练负载均衡流量极化冲突原因,万卡(大规模)集群语言模型(LLM)训练流量拥塞特点
大规模集群,大语言模型(LLM)训练流量特点,ECMP(Equal-Cost Multi-Path Routing)流量极化拥塞原因。 视频分享在这: 2.1 ECMP等价多路由,大模型训练流量特点,拥塞冲突极化产生原因_哔哩哔哩_bi…...

Linux 注意事项
Linux 与 Windows 是两个相互独立的操作系统,两者有较大差距: 1.1 Linux 严格区分大小写(Windows不严格区分大小写); 1.2 Linux 中所有内容,硬件设备都以文件形式保存在 /dev 目录下(万物皆文件…...

力扣SQL50 指定日期的产品价格 双重子查询 coalesce
Problem: 1164. 指定日期的产品价格 coalesce 的使用 简洁版 👨🏫 参考题解 select distinct p1.product_id,coalesce((select p2.new_pricefrom Products p2where p2.product_id p1.product_id and p2.change_date < 2019-08-16order by p2.…...
MySQL8的备份方案——全量(完全)备份(CentOS)
MySQL8的全量备份 一、安装备份工具二、备份数据三、恢复备份 点击跳转增量备份 点击跳转差异备份 点击跳转压缩备份 一、安装备份工具 官网 下载地址 备份所用工具为percona-xtrabackup 如果下方安装工具的教程失效,请点击上方下载地址转到官方文档查看 下载该工…...

JVM监控及诊断工具-命令行篇--jcmd命令介绍
JVM监控及诊断工具-命令行篇5-jcmd:多功能命令行 一 基本情况二 基本语法jcmd -ljcmd pid helpjcmd pid 具体命令 一 基本情况 在JDK 1.7以后,新增了一个命令行工具jcmd。它是一个多功能的工具,可以用来实现前面除了jstat之外所有命令的功能…...

c++信号和槽机制的轻量级实现,sigslot 库介绍及使用
Qt中的信号与槽机制很好用,然而只在Qt环境中。在现代 C 编程中,对象间的通信是一个核心问题。为了解决这个问题,许多库提供了信号和槽(Signals and Slots)机制。今天推荐分享一个轻量级的实现:sigslot 库。…...
云原生项目纪事系列 - 项目管理的鲜活事例
大规模云原生系统的新颖性、建设性和挑战性,吸引着许多有数学思想、哲学意识和美学观念的系统架构师,老模也是其中一员。 老模即是文史家庭出身,又有理工学业背景,他基于平时记录的翔实细节,秉持客观原则,使…...

【Vite】快速入门及其配置
概述 Vite是前端构建工具。vite 相较于webpack,vite采用了不同的运行方式: 开发时,并不对代码打包,而是直接采用ESM的方式来运行项目在项目打包部署时,使用 rollup 对项目进行打包除了速度外,vite使用起来也更加方便…...

Armv8/Armv9架构的学习大纲-学习方法-自学路线-付费学习路线
本文给大家列出了Arm架构的学习大纲、学习方法、自学路线、付费学习路线。有兴趣的可以关注,希望对您有帮助。 如果大家有需要的,欢迎关注我的CSDN课程:https://edu.csdn.net/lecturer/6964 ARM 64位架构介绍 ARM 64位架构介绍 ARM架构概况…...
vue 中 ui 组件二次封装后 ref 怎么穿透到子组件里
情景:element-ui 二次封装了 el-table 组件,使用封装组件时,想要调用 el-table 组件内置的一些方法。只在封装组件上定义 ref 是拿不到 el-table 内置方法的。解决方法如下。 1. vue2 封装组件 <template><el-table ref"inn…...

sourcetree中常用功能使用方法及gitlab冲突解决
添加至缓存:等于git add 提交:等于git commit 拉取/获取:等于git pull ,在每次要新增代码或者提交代码前需要先拉取一遍服务器中最新的代码,防止服务器有其他人更新了代码,但我们自己本地的代码在我们更新前跟服务器不…...
SQL Server分布式查询:跨数据库的无缝数据探索
SQL Server分布式查询:跨数据库的无缝数据探索 在当今的企业环境中,数据往往分散在不同的数据库和服务器上。SQL Server的分布式查询功能提供了一种强大的手段,允许用户编写单一的查询来访问和操作分散在不同SQL Server实例中的数据。本文将…...

【字少图多剖析微服务】深入理解Eureka核心原理
深入理解Eureka核心原理 Eureka整体设计Eureka服务端启动Eureka三级缓存Eureka客户端启动 Eureka整体设计 Eureka是一个经典的注册中心,通过http接收客户端的服务发现和服务注册请求,使用内存注册表保存客户端注册上来的实例信息。 Eureka服务端接收的…...
如何在 Linux 中解压 ZIP 文件
ZIP 是一种常用的压缩文件格式,用于存储和传输多个文件。在 Linux 系统中,解压 ZIP 文件非常简单。 使用 unzip 命令 unzip 是一个专用于解压 ZIP 文件的命令行工具。要使用它,请打开终端并输入以下命令: 例如,要解…...
IDEA的APIPost接口测试插件详解
APIPOST官方网址 一、安装APIPost插件 打开IntelliJ IDEA: 启动您的IntelliJ IDEA开发环境。 导航到插件设置: 在Windows或Linux上,点击 File > Settings。在macOS上,点击 IntelliJ IDEA > Preferences。 搜索并安装APIPo…...

[经验] 驰这个汉字的拼音是什么 #学习方法#其他#媒体
驰这个汉字的拼音是什么 驰,是一个常见的汉字,其拼音为“ch”,音调为第四声。它既可以表示动词,也可以表示形容词或副词,意义广泛,经常出现在生活和工作中。下面就让我们一起来了解一下“驰”的含义和用法。…...

生成式人工智能落地校园与课堂的15个场景
生成式人工智能正在重塑教育行业,为传统教学模式带来了革命性的变化。随着AI的不断演进,更多令人兴奋的应用场景将逐一显现,为学生提供更加丰富和多元的学习体验。 尽管AI在教学中的应用越来越广泛,但教师们也不必担心会被完全替代…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...