pg事务:隔离级别历史与SSI

news2024/12/23 17:26:23

事务隔离级别的历史

ANSI SQL-92定义的隔离级别和异常现象确实对数据库行业影响深远,甚至30年后的今天,绝大部分工程师对事务隔离级别的概念还停留在此,甚至很多真实的数据库隔离级别实现也停留在此。但后ANSI92时代对事物隔离有许多讨论甚至批评,针对隔离级别和异常现象的论文、博客、文章、讨论非常多,这里概况一下事务的比较重要发展历史:

  • 1992年,由于数据库行业处于混沌的事务状态,美国国家标准学会定义ANSI SQL-92标准。也就是广泛流传的4种隔离级别和4种异常现象

  • 1995年,snapshot isolation等隔离级别提出和更多的异常现象。微软工程师等提出snapshot isolation隔离级别,并对ANSI SQL-92做出批判,92标准定义模糊,而且有许多隔离级别和异常现象未定义。参考《对ANSI SQL隔离级别的批判》.

    此时隔离级别已不止4个,异常现象也更多,其中也包括写偏序异常。

  • 1999年 ,由于锁模式的不同发展出过多的隔离级别,Atul Adya的论文整理了这些现象,并根据异常现象和功能将众多隔离级别回溯到ANSI SQL92标准进行对应。

  • 2005年 ,由于绝大部分数据库声称他们是可串行化的,但他们实际上是快照隔离, Alan Fekete et al 提出“使快照隔离可序列化”。在snapshot isolation级别基础上实现可序列化,消除快照隔离的异象。

  • 2008年 ,Fekete 扩展了可序列化,并提出数据库层面实现“使快照隔离可序列化”,称之为快照隔离可序列化SSI (Serializable Snapshot Isolation)

  • 2012年 ,postgresql第一个在数据库中实现SSI ,参考postgresql数据库实现SSI的论文

其中,95年《对ANSI SQL隔离级别的批判》中的隔离级别和异常现象
在这里插入图片描述

各种数据库支持的隔离级别

很多数据库的声称他们”完全支持ACID“特性,但是没有可串行化是不能完全实现ACID的(特别是一致性)。然而许多数据库在不支持可串行化级别下声称他们支持ACID。其实他们绝大部分都没有完全实现,包括数据库老大哥oracle。

在这里插入图片描述

可串行化

人们对可串行化存在许多误解。

可串行化的含义:如果每个事务本身是正确的,即满足某些完整性条件,那么包括这些事务的任何串行执行的时间表是正确的(其事务仍然满足其条件):“串行”意味着事务在时间上不重叠,并且不能相互干扰,即彼此之间存在完全隔离。

1970年代可串行化(serializable)通过严格两阶段锁(SS2PL)实现,读写相互阻塞,直到事务结束。SS2PL丢失高可用性但消除了异常现象。

除了SS2PL实现可串行化,还有其他方式,比如可串行化快照隔离(SSI)。

为了保证没有异常,可串行化会丢失一些并发性(不同实现方式有所不同),但可以真正保证数据的一致性(ACID中的consistency)。也就是说没有实现串行化的数据库,其实没有完全支持ACID特性

可串行化在数学上已经证明可以实现,但是真实的数据库世界有点”不正常“。实际上,可串行化是事务隔离级别中最高级的,也是所有学者和大佬强力推荐的隔离级别,不过绝大部分数据库在RC或快照隔离级别上运行

为什么弱隔离级别在学术上有问题,实际上没出现严重问题?

1.非可串行化隔离级别的异常现象,一般都需要再高并发情况下才会发生,一般低并发数据库不太会出现问题

2.异常现象真的发生的时候,有些应用可能没发现异常现象或没检查到异常对他们不重要。

3.有可能数据异常了,但应用只是返回报错,并进入数据异常处理程序。

4.成本过高。不仅是数据库序列化隔离级别开发成本高,应用对可序列化也需要适应成本。光是理解这部分复杂的理论就不是一件容易的事

5.高级别的隔离会丢失一些性能。大量的改造工作可能是吃力不讨好的,应用需要在“高并发”和“无异常现象”间做抉择

6.业务基于机制开发,而不是规则开发。业务多少有点适应弱隔离级别的异常现象,特别是RC或快照隔离级别

快照隔离

ANSI SQL92并未定义快照隔离snapshot isolation(SI),这个隔离级别随着数据库行业发展才出现。

引自wiki定义:在快照隔离下执行的事务是在事务开始时拍摄的数据库的快照上操作的。当事务结束时,只有当事务更新的值自快照拍摄以来没有外部更改时,它才会成功提交。这样写冲突将导致事务中止。

快照隔离级别顾名思义就是就是使用了快照,存在于使用了MVCC的数据库中,多版本并发机制支持用户并发执行事务。

1992年 ANSI SQL92标准基于数据库的锁而定义,所以没有快照隔离级别这个定义。直到1995年《批判》的出现才被提出。

快照隔离串行化

由于快照隔离的广泛应用,而可序列化是学术上的数据库需要达到的隔离级别目标,可序列化快照隔离Serializable Snapshot Isolation (SSI) 随即产生。顾名思义,在快照隔离的基础上实现可序列化。

由于ANSI92标准的模糊性,虽然没有定义快照隔离,但许多数据库实际上就是使用的快照隔离。而快照隔离同样存在一些异常现象(包括写偏序),SSI的出现就是为了解决这些异常现象。

主流数据库通过基于S2PL或MVCC实现并发控制。在S2PL下写操作会阻塞其他事务读写,因此不会有写偏序异常问题。而MVCC实现了读写互不阻塞,只有写写冲突。在并发RW模式模式下会导致写偏序问题。SSI在pg9.1开始已经嵌入快照隔离SI中(pg只有快照隔离,哪怕是在可序列化级别下),解决了写偏序等异常。

写偏序

由于某些冲突构成环,会出现串行化异常**。**其中比较容易理解的一个就是写偏序(write skew)。

写偏序只发生在rw模型,ww、wr均不会发生写偏序,并且事务必须在并发条件下才会出现。前一个事务写入依赖后一个事务写入才会形成依赖环。

在这里插入图片描述

有许多现实案例可以出现写偏序异常,我们用一个经典的黑白球问题来理解写偏序

袋中有10个球,5个白球和5个黑球。此时有两个事务,P和Q。P将所有黑球改成白球,Q将所有白球改成黑球。此时可以有两个串行执行,P,Q或Q,P。在这两种情况下,最终结果是袋中有10个白球或者10个黑球。但是,快照隔离允许另一种结果:

  • 事务 P 拿出5个黑球
  • 事务 Q 拿出5个白球
  • 事务 P 将手中所有黑球改成白球,放回袋中
  • 事务 Q 将手中所有白球改成黑球,放回袋中

此时袋中还是5个黑球和5个白球,这在任何一个串行执行中都是不可能的。但这在快照隔离中是有效:每个事务都维护数据库的一致视图,并且其写集不与任何并发事务的写集重叠,如此白球黑球发生交换。

黑白球问题说明:快照隔离执行结果与串行化执行结果不一致,快照隔离下发生写偏序异常,数据结果与预期不一致。

pg中的SSI

postgresql数据库是首个在数据库中实现SSI的数据库。

引用wiki的黑白球代码示例

create table dots
  (
   id int not null primary key,
   color text not null
  );
 insert into dots
  with x(id) as (select generate_series(1,10))
  select id, case when id % 2 = 1 then 'black'
   else 'white' end from x;
set default_transaction_isolation = ‘serializable’;set default_transaction_isolation = ‘serializable’;
begin;
update dots set color = ‘black’ where color = ‘white’;
begin;
update dots set color = ‘white’ where color = ‘black’;
commit
commit
(pg SSI先提交者成功提交,后提交者抛出报错 )ERROR: could not serialize access due to read/write dependencies among transactions DETAIL: Reason code: Canceled on identification as a pivot, during commit attempt. HINT: The transaction might succeed if retried.

(已提交读和可重复读级别,均不会出现报错,黑白球颜色交换,不再展示测试结果)

严格两阶段提交(S2PL)也可以实现可串行化,但S2PL需要很重的读写锁,直到事务提交为止。S2PL会极大的影响并发性能,而且用户一般不会接受读写互相阻塞的情况,所以pg没有采用S2PL。

SSI是可序列化的另一种方案。它仍然会使用快照隔离,只是会额外检查是否有异常现象发生。

两个方案的处理方式也不同:在异常现象发生时,S2PL会阻塞事务,而SSI会中断事务以打破循环。

人们没有使用可串行化,原因之一有可串行化会降低数据库性能。这其实可以理解,因为有”检查异常现象“的SSI必定比什么检查都没有的弱隔离级别性能低。不过经过SSI实现理论的发展和pg本身对只读事务的优化,SSI的性能已于SI相差无几。

在这里插入图片描述

可序列化能极大的简化应用对一致性的担心,而pg9.1已实现ssi并加以优化。期待应用有一天真的能使用可串行化隔离级别。

事务隔离级别参考

https://wiki.postgresql.org/wiki/SSI

https://en.wikipedia.org/wiki/Serializability

https://en.wikipedia.org/wiki/Snapshot_isolation

https://justinjaffray.com/what-does-write-skew-look-like/

http://www.bailis.org/blog/when-is-acid-acid-rarely/

https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf 95年SI隔离级别以及对SQL92标准的批评

https://www.cse.iitb.ac.in/infolab/Data/Courses/CS632/2009/Papers/p492-fekete.pdf SSI论文

https://drkp.net/papers/ssi-vldb12.pdf postgresql实现SSI

https://ristret.com/s/f643zk/history_transaction_histories 事务隔离级别的历史

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

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

相关文章

队列的实现(附含两道经典例题)

🍉文章主页:阿博历练记 📖文章专栏:数据结构与算法 🚍代码仓库:阿博编程日记 🍥欢迎关注:欢迎友友们点赞收藏关注哦🌹 文章目录 🌾前言🎬队列&…

探索Windows CMD命令的经典应用:实用技巧大揭秘,值得收藏

文章目录 导语:第一部分:CMD命令基础1. ipconfig:获取网络配置信息2. ping:测试网络连接3. dir:查看目录内容4. telnet:远程登录和测试网络服务 第二部分:进程管理5. tasklist:查看正…

10-Docker发布微服务

文章目录 搭建SpringBoot项目发布微服务项目到Docker容器 搭建SpringBoot项目 搭建一个简单的SpringBoot项目&#xff1a; 创建maven工程&#xff0c;pom为&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://m…

【Java多线程案例】单例模式

本期讲解单例模式的饿汉模式与懒汉模式&#xff0c;以及如何解决懒汉模式造成线程的不安全问题。 目录 什么是单例模式&#xff1f; 1. 饿汉模式 2. 懒汉模式 2.1 懒汉模式单线程版 2.2 懒汉模式多线程版 3. 解决懒汉模式不安全问题 3.1 保证原子性 3.2 防止指令重排序…

MAC移动硬盘无法识别解决方案(超详细图文教程)

目录 步骤1&#xff1a;先找到外接移动硬盘&#xff0c;在 Mac “终端”执行命令 步骤2&#xff1a;加载移动硬盘&#xff0c;可以在终端执行以下两个命令之一 步骤3&#xff1a;终止后台自动执行的“磁盘修复进程” 步骤4&#xff1a;手动执行磁盘修复命令 步骤5&#xf…

lwIP更新记01:全局互斥锁替代消息机制

从 lwIP-2.0.0 开始&#xff0c;在 opt.h 中多了一个宏开关 LWIP_TCPIP_CORE_LOCKING&#xff0c;默认使能。这个宏用于启用 内核锁定 功能&#xff0c;使用 全局互斥锁 实现。在之前&#xff0c;lwIP 使用 消息机制 解决 lwIP 内核线程安全问题。消息机制易于实现&#xff0c;…

基于Linux安装Docker

Docker官网&#xff1a;Docker Docs: How to build, share, and run applications | Docker Documentation 学习任何技术&#xff0c;一定要参考相应的官网学习&#xff0c;一定要参考官网学习&#xff01;&#xff01;&#xff01; 目录 一、环境准备 1.1 配置源 1.1.1 下载…

Vue+uniapp桃源婚恋交友APP 安卓小程序 nodejs java python

小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 开发模式&#xff1a;混合开发本文先提出了开发基于小程序的桃源婚恋交友APP系统的背景意义&#xff0c;然后通过功能性和非功能性分析阐述本系统的需求&#xff0c;然后进行系统设计。技术实现部分选择Jav…

c++ 11标准模板(STL) std::set(九)

定义于头文件 <set> template< class Key, class Compare std::less<Key>, class Allocator std::allocator<Key> > class set;(1)namespace pmr { template <class Key, class Compare std::less<Key>> using se…

vue参照企业微信日程写一个小组件

今天公司要求做日程 这体的话 和企业微信的日程功能挺想的 也没有找到特别好的工具 就直接自己手敲了一个 先看效果 因为样式使用 sass 写的 所以 项目中要引入 sass 感兴趣的 可以把代码拿去二开一下 <template><section class "skeletonPositioning"…

Java线程概述 (一)线程介绍

文章目录 &#x1f412;个人主页&#x1f3c5;JavaSE系列专栏&#x1f4d6;前言&#xff1a;&#x1fa85;什么是程序 、进程、线程&#xff1f;&#x1fa85;线程的生命周期&#x1fa85;多线程&#x1fa85;守护者线程&#x1fa85;线程并行与并发&#x1fa85;死锁&#x1f…

机器学习项目实战-能源利用率 Part-4(模型构建)

博主前期相关的博客可见下&#xff1a; 机器学习项目实战-能源利用率 Part-1&#xff08;数据清洗&#xff09; 机器学习项目实战-能源利用率 Part-2&#xff08;探索性数据分析&#xff09; 机器学习项目实战-能源利用率 Part-3&#xff08;特征工程与特征筛选&#xff09; 这…

AList挂载工具安装搭建使用教程,快速访问多个网盘的资源(保姆级图文)

目录 1. 下载AList2. 命令行启动快速启动小技巧 3. 用户登录4. 添加阿里云网盘帐号5. 添加百度云网盘资源总结 欢迎关注 『发现你走远了』 博客&#xff0c;持续更新中 欢迎关注 『发现你走远了』 博客&#xff0c;持续更新中 软件功能&#xff1a;将多个网盘的资源聚合在一起&…

本地部署 privateGPT

本地部署 privateGPT 1. 什么是 privateGPT2. Github 地址3. 创建虚拟环境4. 部署 privateGPT5. 配置 .env6. 下载模型7. 将文件放入 source_documents 目录中8. 摄取所有数据9. 向本地文档提问 1. 什么是 privateGPT 利用 GPT 的强大功能&#xff0c;私密地与您的文档交互&am…

Flutter 笔记 | Flutter 中的路由、包、资源、异常和调试

路由管理 Flutter中的路由通俗的讲就是页面跳转。在Flutter中通过Navigator组件管理路由导航。并提供了管理堆栈的方法。如&#xff1a;Navigator.push和Navigator.pop Flutter中给我们提供了两种配置路由跳转的方式&#xff1a;1、基本路由&#xff0c; 2、命名路由 普通路…

详解c++STL—函数对象

目录 1、函数对象 1.1、函数对象概念 1.2、函数对象的使用 2、谓词 2.1、谓词概念 2.2、一元谓词 2.3、二元谓词 3、内建函数对象 3.1、理解内建函数对象 3.2、算术仿函数 3.3、关系仿函数 3.4、逻辑仿函数 1、函数对象 1.1、函数对象概念 概念&#xff1a; 重载…

数据结构第三天 【二叉搜索树】

这道题真是写的我想吐了&#xff0c;主要是函数太多&#xff0c;排错太难了&#xff0c;搞了两个小时&#xff0c;基本就是在排错&#xff0c;排了一个小时&#xff0c;后面自己心态也有点崩溃了&#xff0c;其实不是一道很难的题&#xff0c;但是是一个非常麻烦的题目&#xf…

使用Serv-U搭建FTP服务器并公网访问

文章目录 1. 前言2. 本地FTP搭建2.1 Serv-U下载和安装2.2 Serv-U共享网页测试2.3 Cpolar下载和安装 3. 本地FTP发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 转载自内网穿透工具的文章&#xff1a;使用Serv-U搭建FTP服务器并公网访问【内网穿透】_ 1. 前言…

linux专题:GDB详细调试方法与实现

系列文章目录 例如&#xff1a;第一章 Linux-GDB 调试实验的使用 文章目录 目录 系列文章目录 文章目录 一、实验目的 二、实验现象 三、实验准备 四、Linux GDB调试实验流程 五、Linux GDB 调试器 总结 一、实验目的 掌握使用 gcc 分步编译 c 代码为可执行程序步骤以及 gc…

【数学建模】步长的选择(优化建模)

人们每天都在行走&#xff0c;排除以运动健身为目的的走路方式&#xff0c;而仅仅考虑距离固定&#xff0c;以节省体力为最终目的的行走&#xff0c;那么选择多大的步长才最省力&#xff1f; 人在走路时所做的功等于抬高人体重心所需的势能与两腿运动所需的动能之和。在给定速度…