当前位置: 首页 > news >正文

4.1 版本管理器——2PL与MVCC

2PL协议

2PL(Two-Phase Locking,两阶段锁协议)是数据库管理系统中用于确保事务调度正确性的常见并发控制协议。它通过锁机制来管理事务对数据库资源的访问,确保事务之间不会发生冲突。2PL协议可以分为以下两个阶段:

  1. 扩展阶段(Growing Phase):在这个阶段,事务可以请求获得锁定(如共享锁或排他锁),但不能释放任何锁。事务可以随着操作的进行逐步获取更多的锁,但一旦进入收缩阶段,便不能再获取新的锁。

  2. 收缩阶段(Shrinking Phase):在这个阶段,事务只能释放锁,不能再获得新的锁。一旦事务开始释放锁,就不能再请求新的锁。

2PL锁协议的重要特性是,事务必须在扩展阶段获取所有必要的锁,然后在收缩阶段释放这些锁。这个过程确保了在并发执行多个事务时,数据库的一致性和隔离性。 两阶段锁协议有两种变体

  • 严格两阶段锁协议(Strict 2PL):事务在提交或回滚之前不会释放任何锁,特别是排他锁。这种策略可以防止脏读的发生,确保了更高的隔离级别。

  • 严密两阶段锁协议(Rigorous 2PL):事务在整个生命周期内都不会释放任何锁,直到事务结束(提交或回滚)。这种策略比严格2PL更严格,防止了脏读、不可重复读和幻读。

2PL协议在数据库系统中广泛使用,是确保并发控制、避免死锁和保证数据一致性的重要方法之一。

以上定义来自GPT

数据库中的冲突操作

不考虑插入操作,只考虑updateread操作,这两个操作满足以下三个条件即相互冲突:

  • 两个操作由不同事务执行

  • 两个操作操作同一个数据项

  • 至少有一个update操作

那么对同一个数据项的操作发生冲突的条件其实如下:

  • 两个不同事务的update冲突

  • 两个不同事务的updateread冲突

2PL和解决冲突操作有什么关系?

2PL(两阶段锁协议)在解决数据库中的操作冲突时具有以下重要意义:

1. 确保事务的隔离性

2PL的核心目标是确保多个事务并发执行时保持隔离性,防止事务之间的操作互相干扰。隔离性是ACID(原子性、一致性、隔离性、持久性)原则的重要组成部分,特别是避免以下常见问题:

  • 脏读:一个事务读取了另一个未提交事务修改的数据,导致数据不一致。

  • 不可重复读:一个事务两次读取相同的数据,但在两次读取之间,另一个事务修改了数据。

  • 幻读:一个事务在多次查询时,发现有额外的数据行被另一个事务插入,导致查询结果不一致。

通过2PL协议,事务可以通过锁机制避免这些问题,从而保持数据的一致性和隔离性。

2. 预防操作冲突(重点在这一条)

在并发场景下,不同事务可能对同一资源(如数据库记录)进行操作。如果不加控制,事务间的冲突可能导致数据不一致或事务失败。2PL通过锁来管理资源的访问,避免以下类型的冲突:

  • 读-写冲突:一个事务正在读取数据,另一个事务想要修改该数据。

  • 写-写冲突:多个事务同时尝试修改同一数据。

2PL协议要求事务在扩展阶段获取所需的锁,并保证在释放锁前,其他事务无法访问已被锁定的资源,从而避免了操作冲突。

3. 保证调度的可串行化

串行化调度(Serializable Scheduling)是指事务的并发执行结果与按顺序执行的结果一致。2PL协议是确保调度可串行化的重要手段。根据2PL,事务的锁获取和释放顺序符合两个阶段的规则,这就保证了事务不会相互交错,导致不一致的状态。

4. 避免不安全的调度

如果不使用锁协议,事务调度可能导致不安全的执行。例如,一个事务读取了另一个事务修改的未提交数据,这可能导致数据污染。2PL通过锁定资源,确保每个事务只能在资源安全的状态下执行,从而避免出现不安全的调度情况。

5. 防止死锁(结合其他技术)

虽然2PL本身不能完全避免死锁,但它为死锁检测提供了基础。在2PL中,由于事务可能在扩展阶段请求多个锁,有可能发生死锁(即两个或多个事务相互等待彼此释放锁)。通过结合死锁检测机制或采用诸如超时机制,数据库系统可以检测并解除死锁,恢复正常执行。 上面来自GPT

在MySQL中,两阶段锁协议的含义是:当一个事务获取到了某一个数据库对象的锁之后,并不是当前事务不需要操作它了之后,这个说就会马上释放掉,这个锁会一直被这个事务持有,直到这个事务被提交或回滚后,这个锁才会被释放掉。所以,在当前事务还没有结束的时候,任何其他事务尝试获取这个锁的时候,都会被阻塞。知道当前事务提交或回滚后,前提事务才可以获取到这把锁 这就是MySQL中2PL两阶段锁协议的含义。它在事务并发的时候,为数据的一致性提供有力的保障 源自网络

MYDB中解决冲突的方法

SimpleDB采用2PL来实现调度序列的可串行化。如果某个事务i已经对x加锁,且另一个事务j也想操作x,但是这个操作与事务i之前的操作相互冲突,那么事务j会被阻塞。 使用2PL虽然保证了调度序列的可串行化,但是不可避免地导致了事务间的相互阻塞乃至死锁

MVCC

什么是MVCC

MVCC(Multiversion Concurrency Control,多版本并发控制)是一种数据库并发控制机制,用于解决数据库中多个事务并发执行时的读写冲突问题。MVCC通过维护数据的多个版本,允许并发的读操作和写操作更有效地进行,从而提高数据库的并发性能和系统吞吐量。

核心概念
  1. 版本控制:每个数据项都有多个版本,每个版本对应于数据库在某个时间点的状态。当事务对数据进行修改时,系统不会直接覆盖旧版本的数据,而是创建一个新版本。旧版本的数据仍然保留,以供其他事务读取。

  2. 事务标识:每个事务在开始时都会获得一个唯一的时间戳或事务ID。这个时间戳用于决定事务可以访问哪些数据版本,从而确保数据的一致性和隔离性。

  3. 快照隔离:MVCC提供了一个时间点的数据库“快照”,即事务在开始时看到的是数据的一个一致快照,即使其他事务在此后提交了修改。这个机制确保了读取操作的可重复性,避免了脏读和不可重复读的问题。

MVCC 的工作机制
  • 读取操作:事务在读取数据时,根据自身的时间戳,只能看到在该时间戳之前提交的版本数据。这意味着事务读取的数据版本是相对于其开始时间点的一致快照,而不是实时的最新数据。

  • 写入操作:当事务要修改数据时,系统会创建该数据项的一个新版本,并将该版本标记为该事务的写入。这个新版本在事务提交前,对其他事务是不可见的。

  • 提交和回滚:当事务提交时,系统会将新版本标记为可见,同时其他事务将能够看到这个新版本。如果事务回滚,则新版本会被丢弃,其他事务继续访问旧版本。

优点
  1. 高并发性:MVCC允许多个事务同时读取数据,而不需要加锁。这减少了读写操作之间的冲突,从而提高了并发性。

  2. 避免读写冲突:通过维护数据的多个版本,读操作不会被写操作阻塞,反之亦然。这大大减少了死锁和等待时间。

  3. 一致性保证:MVCC通过时间戳和数据版本管理,确保事务看到的是一致的数据库状态,避免了脏读、不可重复读和幻读问题。

缺点
  1. 存储开销:由于需要维护多个版本的数据,MVCC增加了存储空间的需求。过多的版本还可能需要额外的机制来清理和回收空间。

  2. 版本管理复杂性:随着时间的推移,系统可能产生大量数据版本,管理这些版本及其对应的事务状态会增加系统的复杂性。

使用场景

MVCC广泛应用于现代关系型数据库系统,如PostgreSQL、MySQL(InnoDB引擎)和Oracle,以及一些NoSQL数据库,如Cassandra。它尤其适用于读操作频繁的场景,通过减少锁冲突来提高并发性能。

所以说,MVCC其实是一种思想,在不同的数据库中有不同的具体实现方式

MYDB中的MVCC

之前的实现中,我们知道数据管理器(DM)通过操作持久化的db文件,并通过封装,向上提供的抽象数据是DataItem,也就是说,上层看到的数据都是DataItem的形式 而本章讨论的版本管理器(VM)会进一步封装,给VM之上的模块提供一种抽象数据,即“记录”(Entry)。VM之上的模块看到的数据以及操作的数据都是Entry的形式 VM在内部,为每个Entry维护了多个版本(Version)。当上层模块对某个“记录”(Entry)修改时,VM就创建一个新的版本 如上的MVCC策略能够降低不同操作之间互相阻塞的概率,例如实现可重复读等隔离级别

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【CVPR‘24】DeCoTR:使用 2D 和 3D 注意力增强深度补全
  • 【web开发】Spring Boot 快速搭建Web项目(二)
  • ElasticSearch学习笔记(四)分页、高亮、RestClient查询文档
  • openGuass之CTE Reuse
  • 数据仓库系列17:元数据管理在数据仓库中的作用是什么?
  • 实用好软-----电脑端 开源的视频无损剪切与合并工具
  • Linux——性能调优工具一览
  • 数据资产目录中的主数据划分(汽车制造行业)
  • Go语言设计与实现 学习笔记 第六章 并发编程(2)
  • Ubuntu/Linux 配置 locale
  • 【AI学习笔记】AIGC,AI绘画 ComfyUI+ComfyUI Manager安装
  • [服务器_1]rpc框架收集
  • 入行「游戏策划」,该从何处下手?
  • django外键表查询
  • 黑马程序员Python数据挖掘|1Jupyter Notebook的使用
  • iOS小技巧之UIImagePickerController实现头像选择
  • k8s如何管理Pod
  • Vim 折腾记
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 产品三维模型在线预览
  • 理解在java “”i=i++;”所发生的事情
  • 浅谈web中前端模板引擎的使用
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • ​ubuntu下安装kvm虚拟机
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​如何使用QGIS制作三维建筑
  • # Panda3d 碰撞检测系统介绍
  • #07【面试问题整理】嵌入式软件工程师
  • ${factoryList }后面有空格不影响
  • (8)STL算法之替换
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (libusb) usb口自动刷新
  • (pytorch进阶之路)扩散概率模型
  • (第27天)Oracle 数据泵转换分区表
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (十)c52学习之旅-定时器实验
  • (五)Python 垃圾回收机制
  • (转) RFS+AutoItLibrary测试web对话框
  • .net 7和core版 SignalR
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .net与java建立WebService再互相调用
  • .net中应用SQL缓存(实例使用)
  • @JsonFormat与@DateTimeFormat注解的使用
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • []T 还是 []*T, 这是一个问题
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [AHK] WinHttpRequest.5.1报错 0x80092004 找不到对象或属性
  • [Android]一个简单使用Handler做Timer的例子
  • [Cloud Networking] Layer 2
  • [GN] DP学习笔记板子
  • [GPT]Andrej Karpathy微软Build大会GPT演讲(上)--GPT如何训练
  • [hdu 3746] Cyclic Nacklace [kmp]