【ORACLE】记录一些ORACLE的merge into语句的BUG

【ORACLE】记录一些ORACLE的merge into语句的BUG

一、自相矛盾-DML重启动行为差异,违反acid原则

发现版本:10g ~ 23ai
这个用例在我之前的文章里有提过,ORACLE和PG系关于并发事务行为有一个非常大的差异,就是ORACLE在某些并发冲突的场景下会进行DML重启动,但是对比下面两个例子,可以发现无论采取何种事务一致性实现逻辑,在read commit下,最终的结果无外乎得到(1,‘Alice’)、(10,‘Alice’)、(1,‘Tom’)三种其一,但ORACLE的merge into 却得到了(10,‘Tom’)这一理论不应该存在的记录。
用例一:

drop table test_dml_restart;create table test_dml_restart(id number ,name varchar2(10));
insert into test_dml_restart values (1,'Alice');
commit;--会话一,执行后不提交
update test_dml_restart set id=10 where name='Alice';--会话二执行,被锁
update test_dml_restart set name='Tom' where id=1;--会话一提交,会话二自动解锁,更新0行,会话2根据id=1进行了重启动,找不到id=1的记录
commit;--会话二查询
select * from test_dml_restart;10,Alice

用例二:

drop table test_dml_restart;create table test_dml_restart(id number ,name varchar2(10));
insert into test_dml_restart values (1,'Alice');
commit;--会话一,执行后不提交
update test_dml_restart set id=10 where name='Alice';--会话二执行,被锁
merge into test_dml_restart t1
using (select * from dual) t2
on (t1.id=1)
when matched then 
update set t1.name='Tom';--会话一提交,会话二自动解锁,更新1行,会话2仍然按旧的id找到了数据进行更新
commit;--会话二查询
select * from test_dml_restart;10,Tom

在asktom上也有人发现过,但从10g到目前最新的23ai,这个问题一直未修复
https://asktom.oracle.com/ords/f?p=100:11:::NO::P11_QUESTION_ID:61865893444475

merge and write consistency
Andrey N. Edemsky, May 04, 2006 - 3:51 pm UTC

其实这个问题在ORACLE里通过改写SQL规避,就是把on里的条件,复制一份到update后面的where里

merge into test_dml_restart t1
using (select * from dual) t2
on (t1.id=1)
when matched then 
update set t1.name='Tom' where t1.id=1;

二、百密一疏-触发ORA600的外关联

发现版本:11g 12c 18c 19c

 create table test1 (col1 number,col2 number);create table test2 (col1 number,col2 number);insert into test1 values (1,1);merge into test2
using test1 on (test1.col1=test2.col1(+))
when matched thenupdate set test2.col2=test1.col2;ORA-00600: 内部错误代码, 参数: [25027], [3], [3], [0], [0], [0], [1], [1], [], [], [], []

虽然这个sql本身的确不对,但是ORACLE报错却是ORA-600这个ORACLE自己没有估计到的报错。
19.20及最新的23ai版本已修复这个问题,在23ai中该SQL执行结果是merge 0行。

三、自欺欺人-不能更新on中引用的列

版本:9i ~ 23ai

详见这篇 【ORACLE】你以为的真的是你以为的么?–ORA-38104: Columns referenced in the ON Clause cannot be updated

这个是个ORACLE故意做的限制,本身可以说不算BUG,但是通过特殊方式能绕过这个限制,就可以算个BUG了。所以ORACLE要么承认这个设计是BUG,要么承认开发遗漏了场景也还是BUG,总归有一边是BUG。

merge into test_merge_a a
using test_merge_b b
on (a.id=b.id)
when matched thenupdate set id=2;ORA-38104: 无法更新 ON 子句中引用的列: "A"."ID"--改写
merge into test_merge_a a
using test_merge_b b
on ((a.id=b.id or 1=2) and (a.id=b.id or 1=2 ))
when matched thenupdate set a.id=2;Plan Hash Value  : 4101543598 --------------------------------------------------------------------------------
| Id  | Operation              | Name         | Rows | Bytes | Cost | Time     |
--------------------------------------------------------------------------------
|   0 | MERGE STATEMENT        |              |    1 |    13 |    4 | 00:00:01 |
|   1 |   MERGE                | TEST_MERGE_A |      |       |      |          |
|   2 |    VIEW                |              |      |       |      |          |
| * 3 |     HASH JOIN          |              |    1 |    76 |    4 | 00:00:01 |
|   4 |      TABLE ACCESS FULL | TEST_MERGE_B |    1 |    32 |    2 | 00:00:01 |
|   5 |      TABLE ACCESS FULL | TEST_MERGE_A |    1 |    44 |    2 | 00:00:01 |
--------------------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 3 - access("A"."ID"="B"."ID")

以上是较新版本中需要注意一些问题。

在早期版本中已经修复过的就不全部列举了,MOS上搜merge into的BUG大把大把的,翻了N页没见底,什么更新视图、分区表、并行、并发、行归档、dblink、压缩表等等有一堆功能和merge into组合使用有问题的,这里只写几个简单的merge into语句有问题的场景

四、无中生有-源数据为空的结果集也能匹配上

版本:11.2.0.2.0
https://asktom.oracle.com/ords/f?p=100:11:0::::P11_QUESTION_ID:9537112000346374938
https://asktom.oracle.com/ords/f?p=100:11:::NO::P11_QUESTION_ID:61865893444475

Same guy - Correction
GPU, August 26, 2013 - 5:11 pm UTC

create table test_merge_null(col1 varchar2(20) not null);MERGE INTO test_merge_null
USING (SELECT dummy
FROM DUAL
WHERE 1 = 2) s
ON (1 = 2)
WHEN NOT MATCHED
THEN
INSERT (col1)
VALUES (s.dummy);

这是11.2.0.2.0 中的 bug,已在 11.2.0.3.0 中修复。还好,11.2.0.2.0这个版本用得少。

五、一山能容二虎-突破主键唯一限制

发现版本:10.2.0.1.0
通过direct path write,能突破主键限制进行插入,使表中数据违反有效的唯一约束,案例来自:
https://blog.csdn.net/jackpk/article/details/3788143

create table KL_TEST
(a           NUMBER(15) not null,b           NUMBER(15) not null,c           NUMBER(15) not null,d           NUMBER(15) not null,e           NUMBER(15) not null,f           NUMBER(15) not null
);10   ;Table created.alter table KL_TESTadd constraint KL_TEST_PK primary key (A, B, C, D)3      ;Table altered.CREATE TABLE KL_TEST_1 NOLOGGING PCTFREE 0 ASSELECT * FROM KL_TEST3   WHERE 1=2;Table created.SYS@ora10g> INSERT INTO KL_TEST_1 VALUES (1,1,1,1,1,1);1 row created.SYS@ora10g> INSERT INTO KL_TEST_1 VALUES (1,2,1,2,1,2);1 row created.SYS@ora10g> INSERT INTO KL_TEST_1 VALUES (1,1,1,1,1,1);1 row created.SYS@ora10g> commit;Commit complete.MERGE /*+ APPEND */ INTO KL_TEST trgt
USING
(select fct.a,fct.b,fct.c,fct.d,fct.e,fct.f from KL_TEST_1 fct) tmp
ON
(tmp.a = trgt.aand tmp.b = trgt.band tmp.c = trgt.cand tmp.d = trgt.dand tmp.e = trgt.eand tmp.f = trgt.f)WHEN NOT MATCHED THENINSERT (a,b,c,d,e,f)13   VALUES (tmp.a,tmp.b,tmp.c,tmp.d,tmp.e,tmp.f);3 rows merged.SYS@ora10g>  commit;Commit complete.SYS@ora10g> SELECT COUNT(*) FROM KL_TEST;COUNT(*)
----------0SYS@ora10g> SELECT /*+ FULL (KL_TEST)*/ COUNT(*) FROM KL_TEST;COUNT(*)
----------3SYS@ora10g> select * from kl_test;A          B          C          D          E          F
---------- ---------- ---------- ---------- ---------- ----------1          1          1          1          1          11          1          1          1          1          11          2          1          2          1          2SYS@ora10g> select CONSTRAINT_NAME,CONSTRAINT_TYPE, STATUS from dba_constraints where table_name ='KL_TEST';CONSTRAINT_NAME                C STATUS
------------------------------ - --------
SYS_C005398                    C ENABLED
SYS_C005397                    C ENABLED
SYS_C005396                    C ENABLED
SYS_C005395                    C ENABLED
SYS_C005394                    C ENABLED
SYS_C005393                    C ENABLED
KL_TEST_PK                     P ENABLED7 rows selected.SYS@ora10g> insert into kl_test values (1,1,1,1,1,1);1 row created.SYS@ora10g> select * from kl_test;A          B          C          D          E          F
---------- ---------- ---------- ---------- ---------- ----------1          1          1          1          1          11          1          1          1          1          11          2          1          2          1          21          1          1          1          1          1

在10.2.0.5.0和11.2.0.4版本中已经没这个问题了

总结

ORACLE从很早的版本就增加了merge into这一语法,虽然给开发人员带来了很大的便利性,但是其BUG数之多非常恐怖,很多BUG从发现到修复跨越了数十年的好几个大版本,甚至还有些BUG一直延续到了最新的23ai版本。国产数据库的开发人员远没有ORACLE那么多,ORACLE都做成这样了,国产数据库要是说merge into里没有BUG我是不相信的。

  • 本文作者: DarkAthena
  • 本文链接: https://www.darkathena.top/archives/oracle-merge-into-some-bug
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处

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

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

相关文章

2025上海车展:光峰科技全球首发“灵境”智能车载光学系统

当AI为光赋予思想,汽车将会变成什么样?深圳光峰科技为您揭晓答案。 2025年4月23日,在刚刚开幕的“2025上海车展”上,全球领先的激光核心器件公司光峰科技举办了主题为“AI光影盛宴,智享未来出行”的媒体发布会&#x…

密码学的hash函数,哈希碰撞, collision resistance, BTC用到的SHA-256简介

密码学中的哈希函数、哈希碰撞、抗碰撞性(collision resistance)以及比特币中使用的 SHA-256 的简明介绍: 🧩 一、哈希函数(Hash Function) 定义: 哈希函数是一种将任意长度的输入(…

unity TEngine学习4

上一篇我们学习了UI部分,这一篇我们学习其他部分,按照老规矩还是先打开官方文档 ResourceModule 在官方文档里介绍了当前加载的设置,但是我们是小白看不懂,那就不管他内部怎么实现的,我们主要看下面的代码给的方法&am…

【AI训练环境搭建】在IDE(Pycharm或VSCode)上使用WSL2+Ubuntu22.04+Conda+Tensorflow+GPU进行机器学习训练

本次实践将在IDE(Pycharm或VSCode)上使用WSL2Ubuntu22.04TensorflowGPU进行机器学习训练。基本原理是在IDE中拉起WSL2中的Python解释器,并运行Python程序。要运行CondaTensorflowGPU你可能需要进行以下准备工作。 1. 此示例中将使用一个mnis…

【华为OD机试真题E卷】521、 机器人可活动的最大网格点数目 | 机试真题+思路参考+代码解析(E卷复用)(C++)

文章目录 一、题目题目描述输入输出样例1 一、代码与思路🧠C语言思路✅C代码 一、题目 参考链接:https://sars2025.blog.csdn.net/article/details/141748083 题目描述 现有一个机器人口,可放置于MxN的网格中任意位置,每个网格包…

windows端远程控制ubuntu运行脚本程序并转发ubuntu端脚本输出的网页

背景 对于一些只能在ubuntu上运行的脚本,并且这个脚本会在ubuntu上通过网页展示运行结果。我们希望可以使用windows远程操控ubuntu,在windows上查看网页内容。 方法 start cmd.exe /k "sshpass -p passwd ssh namexxx.xxx.xxx.xxx "cd /hom…

Vue3集成浏览器API实时语音识别

效果示例 用法 <!-- 浏览器语音识别 --> <BrowserSpeechRecognitionModal v-if"showModal" :isOpen"showModal" close"showModal false" confirm"handleRecognitionResult" />const showModal ref(false); const input…

k8s 手动续订证书

注意:如果是高可用环境,本文的操作需要在所有控制节点都执行。 查看证书是否过期 kubeadm certs check-expirationkubeadm certs renew可以续订任何特定证书,或者使用子命令all可以续订所有证书: kubeadm certs renew all使用 kubeadm 构建的集群通常会将admin.conf证书复…

每日一道leetcode(补充版)

1679. K 和数对的最大数目 - 力扣&#xff08;LeetCode&#xff09; 题目 给你一个整数数组 nums 和一个整数 k 。 每一步操作中&#xff0c;你需要从数组中选出和为 k 的两个整数&#xff0c;并将它们移出数组。 返回你可以对数组执行的最大操作数。 示例 1&#xff1a; …

基于Keras3.x使用CNN实现简单的猫狗分类

使用CNN实现简单的猫狗分类 完整代码见&#xff1a;基于Keras3.x使用CNN实现简单的猫狗分类&#xff0c;置信度约为&#xff1a;85% 文章目录 概述项目整体目录环境版本注意 环境准备下载miniconda新建虚拟环境基于conda虚拟环境新建Pycharm项目下载分类需要用到的依赖 数据准备…

中介者模式:解耦对象间复杂交互的设计模式

中介者模式&#xff1a;解耦对象间复杂交互的设计模式 一、模式核心&#xff1a;用中介者统一管理对象交互&#xff0c;避免两两直接依赖 当系统中多个对象之间存在复杂的网状交互时&#xff08;如 GUI 界面中按钮、文本框、下拉框的联动&#xff09;&#xff0c;对象间直接调…

豆包桌面版 1.47.4 可做浏览器,免安装绿色版

自己动手升级更新办法&#xff1a; 下载新版本后安装&#xff0c;把 C:\Users\用户名\AppData\Local\Doubao\Application 文件夹的文件&#xff0c;拷贝替换 DoubaoPortable\App\Doubao 文件夹的文件&#xff0c;就升级成功了。 再把安装的豆包彻底卸载就可以。 桌面版比网页版…

Android PackageManagerService(PMS)框架深度解析

目录 一、概念与核心作用 二、技术架构与模块组成 1. 分层架构 1.1 应用层架构细节 1.2 Binder接口层实现 1.3 PMS核心服务层 1.4 底层支持层实现 2. 核心模块技术要点与工作流程 2.1 PackageParser 2.2 Settings 2.3 PermissionManager 2.4 Installer 2.5 ComponentM…

TensorFlow深度学习实战(14)——循环神经网络详解

TensorFlow深度学习实战(14)——循环神经网络详解 0. 前言1. 基本循环神经网络单元1.1 循环神经网络工作原理1.2 时间反向传播1.3 梯度消失和梯度爆炸问题2. RNN 单元变体2.1 长短期记忆2.2 门控循环单元2.3 Peephole LSTM3. RNN 变体3.1 双向 RNN3.2 状态 RNN4. RNN 拓扑结构…

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类矩阵QRectF)

文章目录 类描述构造方法主要方法1. 基础属性2. 边界操作3. 几何运算4. 坐标调整5. 转换方法6. 状态判断 类特点总结1. 浮点精度&#xff1a;2. 坐标系统&#xff1a;3. 有效性判断&#xff1a;4. 几何运算&#xff1a;5. 类型转换&#xff1a;6. 特殊处理&#xff1a; 典型应用…

Electron主进程渲染进程间通信的方式

在 Electron 中&#xff0c;主进程和渲染进程之间的通信主要通过 IPC&#xff08;进程间通信&#xff09;机制实现。以下是几种常见的通信方式&#xff1a; 1. 渲染进程向主进程发送消息&#xff08;单向&#xff09; 渲染进程可以通过 ipcRenderer.send 向主进程发送消息&am…

【C++基础知识】C++类型特征组合:`disjunction_v` 和 `conjunction_v` 深度解析

这两个模板是C17引入的类型特征组合工具&#xff0c;用于构建更复杂的类型判断逻辑。下面我将从技术实现到实际应用进行全面剖析&#xff1a; 一、基本概念与C引入版本 1. std::disjunction_v (逻辑OR) 引入版本&#xff1a;C17功能&#xff1a;对多个类型特征进行逻辑或运算…

私有知识库 Coco AI 实战(二):摄入 MongoDB 数据

在之前的文章中&#xff0c;我们介绍过如何使用《 Logstash 迁移 MongoDB 数据到 Easyseach》&#xff0c;既然 Coco AI 后台数据存储也使用 Easysearch&#xff0c;我们能否直接把 MongoDB 的数据迁移到 Coco AI 的 Easysearch&#xff0c;使用 Coco AI 对数据进行检索呢&…

sql server 与navicat测试后,连接qt

先用Navicat测试和sql的连通性&#xff0c;Navicat和sql连通之后&#xff0c;qt也能和sql连通了。 Navicat和Sqlserver Management 能连上&#xff0c;项目无法连接本地 Navicat 连接SQLServer 数据库 QT国内镜像网站 Navicat连接SqlServer的问题点 Sql Server的基本配置以及使…

2025年3月电子学会青少年机器人技术(六级)等级考试试卷-理论综合

青少年机器人技术等级考试理论综合试卷&#xff08;六级&#xff09; 分数&#xff1a;100 题数&#xff1a;30 一、单选题(共20题&#xff0c;共80分) 1. 2025年初&#xff0c;中国科技初创公司深度求索在大模型领域迅速崛起&#xff0c;其开源的大模型成为全球AI领域的焦…