PG系、Oracle、MySQL数据库在特定场景下结果差异分析

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 本文主要介绍以PolarDB O引擎、ADB PG为代表的PG系数据库在某种特定事务场景下,其事务结果与Oracle、MySQL不同的现象,并分析该现象出现的原因。

本文主要介绍以PolarDB O引擎、ADB PG为代表的PG系数据库在某种特定事务场景下,其事务结果与Oracle、MySQL不同的现象,并分析该现象出现的原因。

一、数据初始化

Create table test(id int,money int);
insert into testtable values(1,80);
insert into testtable values(1,90);
insert into testtable values(1,100);
insert into testtable values(1,110);
insert into testtable values(1,120);

二、测试过程

1)事务A显式开启事务执行,暂不提交:

delete  from testtable where id = 1;
insert into testtable values (1,100);
select * from testtable;

2)事务B自动提交执行:

delete  from testtable where id = 1;
insert into testtable values(2,110);
select * from testtable;

3)由于事务A未提交导致事务B delete等锁,间隔几秒后提交事务A,之后事务B自动提交完成

三、测试结果

PS:经过验证,事务B的Delete操作无论在事务A的insert操作前后发起,对最终事务结果无影响

Oracle(Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production)

MySQL (5.7.32-log)

ADBPG(PostgreSQL 9.4.24 (Greenplum Database 6.3.0 build dev) on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 6.5.1 20190307 (Alibaba 6.5.1-1 2.17), 64-bit compiled on Oct 25 2021 20:00:34)

PostgrelSQL(PostgreSQL 10.14)

PolarDB O引擎(PostgreSQL 11.9 (POLARDB Database Compatible with Oracle 11.9.18)

四、测试结论

该场景下MySQL处理逻辑和Oracle一致,PG系数据库均会出现数据冗余情况,类似Oracle业务场景做PG系替换有数据不一致风险,需要重点关注。

五、原因分析

  1. 分析原因前我们先介绍下事务型(TP)数据库常用的几种事务隔离级别:
  • Read Uncommitted:读未提交(脏读),一个事务可以读到另外一个事务未提交的数据,大多数关系型数据库不支持。
  • Read Committed:读已提交,一个事务可以读到其他事务已经提交的数据,大多数数据库的缺省模式。
  • Repeatable Read:可重复读,一个事务执行过程中访问的数据是一致的,也就是一个事务中多次读到的数据不会变化。
  • Serializable:序列化(串行化),事务串行化执行,避免不一致。代价很大,OLTP系统中很少使用。
  1. Oracle、MySQL、PG系事务数据库目前都是读已提交(read committed)的隔离级别。
  2. 其次再介绍下数据库的MVCC、当前读、快照读等概念:
  • MVCC:Multi-version Concurrency Control (多版本并发控制),维持一个数据的多个版本,使得读写操作没有冲突
  • 当前读:像select lock in share mode( 共享锁), select for update ; update, insert ,delete( 排他锁)这些操作都是一种当前读,为什么叫 当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁
  • 快照读:像 不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

基于上面的概念我们再来看Oracle/MySQL和PG系TP数据库在该事务场景下的差别时就可以作出如下的推测:

对于Oracle/MySQL结果只有事务B的新插入行:Oracle/MySQL的RC隔离级别下除了select操作都是当前读,因此当事务A对应行上X锁释放后,事务B重新获取X锁时发现行消失会重新索引扫描获取当前读状态,因而直接获取到事务A新插入的行并删除

从MySQL的官方文档我们也可以得到相应的佐证信息:

If you want to see the “freshest” state of the database, use either the READ COMMITTED isolation level or a locking read

原文如上,翻译过来就是如果始终希望获取数据的最新状态,建议使用Read Committed 的隔离级别或者使用带锁的读取操作(如select lock in share mode/delete隐式读/update隐式读等 );也就是MySQL/Oracle除了普通的select操作,其他操作时都会去获取数据的最新当前读状态

对于PG系结果同时含有事务A、B新插入的行:可能存在如下两种原因

  • Case1:PG内核逻辑可能是发现之前的行不存在时就判断事务不用执行直接提交了,不会去走重新索引扫描获取当前读状态,因此事务A新插入的那条数据会依旧存在,出现冗余。
  • Case2:PG内核在事务B发现行消失时也会重新索引扫描,但是PG系内核对于Delete的查询操作也使用了快照读,因此并不会读取到事务A 新插入的这行数据,因而事务B并不会删除该行数据,出现冗余

那么确切的原因什么,我们可以从PG的官方文档找到答案,如下图:

If the first updater commits, the second updater will ignore the row if the first updater deleted it, otherwise it will attempt to apply its operation to the updated version of the row.

前述这段英文是其中最关键的信息,简而言之就是如果事务A Delete了对应行,事务B提交时会直接忽略对应行,而不是重新获取当前读状态;而如果事务A Update了对应行,则此时事务B才会去重新获取当前读状态并基于该状态继续做更新操作。即我们推断的Case1是符合真实情况的

综上分析,PG系和Oracle/MySQL内核在Delete锁冲突时一点细微的处理逻辑差异,导致了在特定的事务场景下出现了数据不一致的情况。

六、参考文档

PostgreSQL官方文档:Read Committed Isolation Level

MySQL官方文档:Consistent Nonlocking Reads

一文读懂PostgreSQL事务隔离级别:链接

正确的理解MySQL的MVCC及实现原理:链接

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
18天前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
65 11
|
1月前
|
架构师 数据库
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
数据库乐观锁是必知必会的技术栈,也是大厂面试高频,十分重要,本文解析数据库乐观锁。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
|
1月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
1月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
24天前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。
|
1月前
|
SQL Oracle 关系型数据库
Oracle数据库优化方法
【10月更文挑战第25天】Oracle数据库优化方法
56 7
|
1月前
|
存储 Oracle 关系型数据库
Oracle数据库优化策略
【10月更文挑战第25天】Oracle数据库优化策略
34 5
|
1月前
|
SQL Oracle 关系型数据库
Oracle与GreatSQL差异:更改唯一索引列
【11月更文挑战第11天】本文介绍了在 Oracle 和 GreatSQL 中修改唯一索引列的操作。Oracle 需要先删除索引、修改列值,再重新创建索引,步骤较为繁琐。而 GreatSQL 在满足一定条件下支持在线 DDL 操作,可以直接修改列值,操作相对简单。两者都需要考虑数据完整性和表上的其他约束条件。
|
4月前
|
监控 Oracle 关系型数据库
"深度剖析:Oracle SGA大小调整策略——从组件解析到动态优化,打造高效数据库性能"
【8月更文挑战第9天】在Oracle数据库性能优化中,系统全局区(SGA)的大小调整至关重要。SGA作为一组共享内存区域,直接影响数据库处理能力和响应速度。本文通过问答形式介绍SGA调整策略:包括SGA的组成(如数据缓冲区、共享池等),如何根据负载与物理内存确定初始大小,手动调整SGA的方法(如使用`ALTER SYSTEM`命令),以及利用自动内存管理(AMM)特性实现智能调整。调整过程中需注意监控与测试,确保稳定性和性能。
396 2
|
5月前
|
存储 缓存 Oracle
Oracle数据库可扩展性和性能
【7月更文挑战第6天】
98 7

推荐镜像

更多