【数据库】数据库事务原理

devtools/2024/9/24 5:32:41/

事务特性

https://blog.csdn.net/zxcyxg123/article/details/132020499

MVCC

MVCC(Multi-Version Concurrency Control),即多版本并发控制,是一种并发控制的方法,主要用于数据库管理系统中,以实现对数据库的并发访问。以下是对MVCC的详细解释:

  1. 目的MVCC的主要目的是允许多个用户同时访问数据库,而不会导致数据冲突和不一致性。它通过在系统中维护多个版本的数据来实现这一目的。

  2. 工作原理

    • 当每个事务启动时,系统会为其分配一个唯一的事务ID。
    • 当一个事务要访问数据库中的某个数据时,系统会检查该数据的版本号和事务的启动时间。如果该数据的版本号早于该事务的启动时间,则该事务可以访问该数据;否则,该事务需要等待其他事务完成对该数据的访问。
    • 当一个事务修改某个数据时,系统会为该数据创建一个新版本号,并将修改后的数据存储在一个新的位置。同时,旧版本的数据仍然可用供其他事务访问。
    • 当一个事务提交时,系统会将其所做的所有修改操作都合并到数据库中,同时删除旧版本的数据。
  3. 优点

    • 提高并发访问数据库的效率。
    • 减少数据冲突和不一致性的发生。
    • 避免了在写操作进行时锁定整个表或记录,从而提高了系统的吞吐量和性能。
    • 使得事务可以看到一个一致的数据视图,不管它们需要运行多久。
  4. 使用场景

    • 读多写少的系统:在这种系统中,冲突的可能性较小,因此MVCC能提供较高的并发性能。
    • 实时系统:在实时系统中,读取的延迟需要尽可能地小。MVCC能通过读取旧的数据版本,避免由于等待写操作而产生的延迟。
    • 分布式系统:在分布式系统中,因为网络延迟和节点故障的存在,事务可能需要较长的时间才能完成。MVCC能使得这些长时间的事务不会阻塞其他的读或写操作。
  5. 实现方式:不同的数据库系统对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';// 100select 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';// 100select 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';// 100select 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';// 100select 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';// 100select 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';// 100select 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)

排他锁,又称为写锁或独占锁,是一种基本的锁类型。当某个事务对数据对象(如表、行等)加上排他锁后,其他事务将无法再对该数据对象加任何类型的锁,直到持有排他锁的事务释放该锁。这就意味着持有排他锁的事务在锁释放前可以独占地读取和修改数据,而其他事务在此期间无法访问该数据。

排他锁的主要特点包括:

  1. 独占性:持有排他锁的事务可以独占地读取和修改数据,其他事务无法再对该数据加任何类型的锁。
  2. 阻塞性:如果其他事务请求对已被加排他锁的数据进行访问,将会被阻塞,直到持有排他锁的事务释放该锁。

二、共享锁(Shared Lock)

共享锁,又称为读锁,是一种允许其他事务并发读取数据的锁类型。当某个事务对数据对象加上共享锁后,其他事务可以并发地读取该数据,但任何事务都不能获取数据上的排他锁,直到已释放所有共享锁。

共享锁的主要特点包括:

  1. 并发读取:多个事务可以同时持有同一数据对象的共享锁,从而并发地读取数据。
  2. 非独占性:持有共享锁的事务不能修改数据,也不能阻止其他事务获取该数据的共享锁。但如果有事务请求对该数据加排他锁,将会被阻塞,直到所有共享锁都被释放。

http://www.ppmy.cn/devtools/40764.html

相关文章

如何使用 await-to-js 库优雅的处理 async await 错误

通过阅读优秀的源码并从中学习如何写出让人觉得赏心悦目的代码最后再写文章进行总结对整个学习的过程进行一个梳理同时分享给其他人。 JS 异步编程进化之路 回调地狱阶段 在正式介绍 await-to-js 这个库之前,让我们先简单的回顾一下有关于在 JavaScript 这门语言…

Java 集合-List

集合主要分为两组(单列集合, 双列集合) Connection 接口有两个重要的子接口LIst 和 Set, 它们的实现子类都是单列集合, Map 接口的实现子类是双列集合, 存放的是 K-V Connection 接口 Collection 接口和常用方法 下面以 ArrayList 演示一下 add: 添加单个元素remove: 删除指…

watch侦听器

在 Vue.js 中,watch 侦听器用于观察和响应 Vue 实例上的数据变动。当你想在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。与计算属性不同,watch 侦听器允许你执行更复杂的逻辑,包括异步操作,并且只有当观…

工厂自动化升级改造参考(01)--设备通信协议详解及选型

以下是整合了通信协议的特点、应用场景、优缺点以及常用接口方式的描述: 以太网/IP: 来历: 以太网是一种局域网技术,由罗伯特梅特卡夫和大卫博格在1973年开发。IP是网络层协议,负责在网络中的设备间传输数据。特点:基于标准的以太网技术,使用TCP/IP协议栈,支持高速数据传…

bat xcopy 解析

echo off set source_folder"C:\path\to\source" set destination_folder"C:\path\to\destination" set exclude_file"C:\path\to\excluded_folders.txt"REM 创建目标文件夹(如果不存在) mkdir %destination_folder% 2>…

git:分支删除

删除本地分支: git branch -d branch_name其中,branch_name 是你要删除的本地分支的名称。如果分支上有未合并的更改,使用 -d 选项会提示你确认删除。 如果要强制删除未合并的分支,可以使用 -D 选项: git branch -D…

web server apache tomcat11-33-CDI

前言 整理这个官方翻译的系列,原因是网上大部分的 tomcat 版本比较旧,此版本为 v11 最新的版本。 开源项目 从零手写实现 tomcat minicat 别称【嗅虎】心有猛虎,轻嗅蔷薇。 系列文章 web server apache tomcat11-01-官方文档入门介绍 web…

Vue创建todolist

电子书 第三章: https://www.dedao.cn/ebook/reader?idV5R16yPmaYOMqGRAv82jkX4KDe175w7xRQ0rbx6pNgznl9VZPLJQyEBodb89mqoO 没有使用VUE CLI创建项目。 创建步骤: 1, 用Vite 创建项目 2, npm run dev 运行程序 参照之前的文…