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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 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
目录
相关文章
|
19天前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
2天前
|
关系型数据库 MySQL 数据库
mysql慢查询每日汇报与分析
通过启用慢查询日志、提取和分析慢查询日志,可以有效识别和优化数据库中的性能瓶颈。结合适当的自动化工具和优化措施,可以显著提高MySQL数据库的性能和稳定性。希望本文的详解和示例能够为数据库管理人员提供有价值的参考,帮助实现高效的数据库管理。
28 11
|
7天前
|
关系型数据库 分布式数据库 数据库
瑶池数据库大讲堂|PolarDB HTAP:为在线业务插上实时分析的翅膀
瑶池数据库大讲堂介绍PolarDB HTAP,为在线业务提供实时分析能力。内容涵盖MySQL在线业务的分析需求与现有解决方案、PolarDB HTAP架构优化、针对分析型负载的优化(如向量化执行、多核并行处理)及近期性能改进和用户体验提升。通过这些优化,PolarDB HTAP实现了高效的数据处理和查询加速,帮助用户更好地应对复杂业务场景。
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
80 11
|
1月前
|
存储 Oracle 关系型数据库
数据库数据恢复—ORACLE常见故障的数据恢复方案
Oracle数据库常见故障表现: 1、ORACLE数据库无法启动或无法正常工作。 2、ORACLE ASM存储破坏。 3、ORACLE数据文件丢失。 4、ORACLE数据文件部分损坏。 5、ORACLE DUMP文件损坏。
121 11
|
2月前
|
架构师 数据库
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
数据库乐观锁是必知必会的技术栈,也是大厂面试高频,十分重要,本文解析数据库乐观锁。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试高频:数据库乐观锁的实现原理、以及应用场景
|
2月前
|
存储 SQL Apache
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
Apache Doris 是一个基于 MPP 架构的高性能实时分析数据库,以其极高的速度和易用性著称。它支持高并发点查询和复杂分析场景,适用于报表分析、即席查询、数据仓库和数据湖查询加速等。最新发布的 2.0.2 版本在性能、稳定性和多租户支持方面有显著提升。社区活跃,已广泛应用于电商、广告、用户行为分析等领域。
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
|
2月前
|
Oracle 关系型数据库 数据库
Oracle数据恢复—Oracle数据库文件有坏快损坏的数据恢复案例
一台Oracle数据库打开报错,报错信息: “system01.dbf需要更多的恢复来保持一致性,数据库无法打开”。管理员联系我们数据恢复中心寻求帮助,并提供了Oracle_Home目录的所有文件。用户方要求恢复zxfg用户下的数据。 由于数据库没有备份,无法通过备份去恢复数据库。
|
2月前
|
存储 Oracle 关系型数据库
oracle数据恢复—Oracle数据库文件大小变为0kb的数据恢复案例
存储掉盘超过上限,lun无法识别。管理员重组存储的位图信息并导出lun,发现linux操作系统上部署的oracle数据库中有上百个数据文件的大小变为0kb。数据库的大小缩水了80%以上。 取出&并分析oracle数据库的控制文件。重组存储位图信息,重新导出控制文件中记录的数据文件,发现这些文件的大小依然为0kb。
|
1月前
|
存储 Oracle 关系型数据库
服务器数据恢复—华为S5300存储Oracle数据库恢复案例
服务器存储数据恢复环境: 华为S5300存储中有12块FC硬盘,其中11块硬盘作为数据盘组建了一组RAID5阵列,剩下的1块硬盘作为热备盘使用。基于RAID的LUN分配给linux操作系统使用,存放的数据主要是Oracle数据库。 服务器存储故障: RAID5阵列中1块硬盘出现故障离线,热备盘自动激活开始同步数据,在同步数据的过程中又一块硬盘离线,RAID5阵列瘫痪,上层LUN无法使用。

推荐镜像

更多