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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 本文主要介绍以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及实现原理:链接

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
13天前
|
安全 关系型数据库 MySQL
MySQL数据库高效秘籍:10个小技巧,让你轻松应对各种场景!
【8月更文挑战第25天】本文介绍了十个提升MySQL数据库效率与安全性的实用技巧。涵盖查询性能分析、索引优化、慢查询日志利用、图形化工具如MySQL Workbench的应用、性能分析工具、主从复制实现、备份与恢复策略、数据库迁移方法及安全性保障等多个方面。通过具体的示例代码展示每个技巧的实际操作方式,帮助读者深入理解并有效运用MySQL数据库。
50 0
|
16天前
|
SQL NoSQL 关系型数据库
实时数仓Hologres发展问题之实时数仓的类数据库化与HTAP数据库的差异如何解决
实时数仓Hologres发展问题之实时数仓的类数据库化与HTAP数据库的差异如何解决
34 2
|
22天前
|
存储 自然语言处理 Oracle
Oracle数据库字符集概述及修改方式
【8月更文挑战第15天】Oracle 数据库字符集定义了数据的编码方案,决定可存储的字符类型及其表示方式。主要作用包括数据存储、检索及跨系统传输时的正确表示。常见字符集如 AL32UTF8 支持多语言,而 WE8MSWIN1252 主用于西欧语言。修改字符集风险高,可能导致数据问题,需事先备份并评估兼容性。可通过 ALTER DATABASE 语句直接修改或采用导出-导入数据的方式进行。完成后应验证数据完整性。此操作复杂,须谨慎处理。
|
12天前
|
Cloud Native 数据管理 数据挖掘
核心系统转型问题之阿里云数据库用户需求的通用性和差异性如何平衡
核心系统转型问题之阿里云数据库用户需求的通用性和差异性如何平衡
|
19天前
|
数据采集 Oracle 关系型数据库
实时计算 Flink版产品使用问题之怎么实现从Oracle数据库读取多个表并将数据写入到Iceberg表
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6天前
|
存储 Oracle 关系型数据库
Oracle同一台服务器创建多个数据库
【8月更文挑战第30天】在 Oracle 中,可在同一服务器上创建多个数据库。首先确保已安装 Oracle 软件并具有足够资源,然后使用 DBCA 工具按步骤创建,包括选择模板、配置存储及字符集等。重复此过程可创建多个数据库,需确保名称、SID 和存储位置唯一。创建后,可通过 Oracle Enterprise Manager 进行管理,注意服务器资源分配与规划。
18 10
|
12天前
|
存储 JSON 关系型数据库
MySQL与JSON的邂逅:开启大数据分析新纪元
MySQL与JSON的邂逅:开启大数据分析新纪元
|
15天前
|
存储 Oracle 关系型数据库
分享几个Oracle数据库日常维护中常见的问题
分享几个Oracle数据库日常维护中常见的问题
55 1
|
18天前
|
缓存 关系型数据库 MySQL
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
在Linux中,如何优化MySQL性能,包括索引优化和查询分析?
|
7天前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
63 0

热门文章

最新文章

推荐镜像

更多
下一篇
DDNS