数据库迁移现场有一种问题很磨人:SQL 不报错。数据也不是完全不对,只是偶尔查不到。
拿到开发工具里重跑,结果又出来了。多跑几遍还是正常,于是大家开始怀疑连接池、网络,或者怀疑金仓数据库执行计划不稳定。折腾一圈,真正的问题可能只是 WHERE 里放了两个函数。而且后一个函数要等前一个函数执行完才能正常工作。
代码大致是这个样子:
SELECT id1,name1
FROM my_table
WHERE pkg_abc.set_id =
AND id1 = pkg_abc.get_id;怎么说呢,
写这段代码的人想得很顺:先用 set_id 把值存起来再由 get_id 取出来。两行条件从上往下排着,似乎已经把步骤交代清楚了。
可 WHERE 不是流程图。
-
"测试时没问题但生产环境偶尔出错": 应用端连接池重用导致包变量状态保留问题;
-
"一样的SQL为什么不同环境结果不同": 数据库调整器可能改变执行顺序;
-
"为什么我明明有数据却查不到": 函数执行顺序假设不成立导致逻辑错误;
老实说,
-
"为何相同参数不同时间结果不同": 函数对会话状态依赖导致非确定性行为.
有人会把条件上下交换:
SELECT id1。name1
FROM my_table
WHERE id1 = pkg_abc.get_id
AND pkg_abc.set_id =;其实,
这样更糟!新会话里《get_id》读到的可能是初始值,查询直接返回空集.偏偏它又不是每次都错.如果当前连接以前调用过《set_id》。包变量还留着旧值,这条SQL可能正常返回.
“前面已经拦住了”,这句话也靠不住!
你需要警惕这些隐患:
-
不可靠的流程控制: SQL中的AND条件并非严格按照书写顺序执行;说起来,
-
隐式依赖风险: 函数间存在隐含依赖关系但未显式管理;
-
环境敏感性: 结果受会话状态、连接池行为影响;
-
边界案例盲区: 测试时未覆盖特殊输入情况.
-
迁移风险: 传统DB与国产DB在调整策略上存在差异.
国产DB迁移中常见误区及方法!
| 误区类型th/th/td/tr/tr/
函数依赖顺序方法 |
"先"和"后"语义
使用绑定参数替换包变量:
SELECTidnameFROMmy_tableWHEREd=:currentiddatacode=/datacode=/datacode=/data-/lili预处理转换敏感字段:
INSERTINTOpaymentVALUES)ONERRORSKIPROWscodestyle=>...=
/datapre>=
/datapre>=
/datapredatalipreb=bdatastyle=>强制使用安全转换函数:
SELECT*FROMordersWHERESAFE_CONVERT=to_number_amount_text);codedatastyle=codestylestylestyledatastrong>/datalistrong>/datalistrong>/datalistrong>/datalistrong>/datalistrong>/datalistrong>/datalistrong=/ul/data-listrong=/div/data-div=data-tddivdata-tddivdata-trdata-trbgcolor='#ffffff'>data-trbgcolor='#ffffff'<>data-trbgcolor='#ffffff'<>data-trbgcolor='#ffffff'>
'WHERE'中的表达式位置假象/td>td>
data-btddiv>
lisdatastrong>lisdatastrong>lisdatastrong>lisdatastrong>lis>
>resultstypedata-typelitype>>type>>typetypedatatype>>type>>typedatatype>>type>>type>>type>>typedatatype>>type>>typesystem/systemsystemsystem/systemsystem/systemsystem/systemsystem/systemsystem/typesystem/typesystem/type<
/bdatadiv===
如何正确处理带转换的字符列?h3===
|
|
| 传统Oracle环境 |
国产金仓环境 |
| 稳定调整器行为 |
更灵活的调整策略 |
| 较宽松的语法兼容性 |
严格语法检查 |
| 成熟连接池实现 |
新开发连接池特性 |
| =TDALIGNLEFTDATA-VALIGNMIDDLELEFTDATA-VALIGNMIDDLELEFTDATA-VALIGNMIDDLELEFTDATA-VALIGNMIDDLELEFTDATA-VALIGNMIDDLELEFTDATA-VALIGNDATA-TRVALIGNMIDDLEREFDATA-TRVALIGNMIDDLEREFDATA-TRVALIGNMIDDLEREFDATA-TRVALIGNMIDDLEREFDATA-TRVALIGNMIDDLEREFTRTRTRTRTRTRTDTDTDTDTDTDTDTDDATATDDATATDDATATDDATADATADATADATADATA/DIVTABLE/TABLE/DIV/DIV/H3/H3/H3/H3/ |
排查这类问题我会先换一个新会话/h2=
分析方法分析方法分析方法分析方法analysisanalysisanalysisanalysisanalysisanalysisanalysisanalysismethodmethodmethodmethodmethodmethodmethods==
-
创建干净测试环境a/a/a/a/list-li/item-li/item-li/item-li/item-li/item-li/item-li/olioliolementlementslistslistslistslistslistslsitlsitlsitslitlsitlsitlsitslitlsitslitlstlitstsllistslstllistslstllistslstllistslstllistslstllistslstllsitstsilstslsitstsiltslistsltsltslisststsiltstsilsitsilstsilsilstsilsilstsilsilstsilsiltsiltsiltsilstsiltsilstsiltsiltsiltsiltsillistsllislistsltsslitssitssiltstslsitstilttsitstilttsitstilttstitstilttstitstilttstitstilttstitstilttstitstilttstitstilttstitstilttstitstilttsiltstsliltssitsslitsiltsslitsilitsslitsilitsslitsilitsslitsilitsslitsilitsslitsilitsslitsilitsslfitsillitsshfitsillitsshfitsilishfitsilishfitsshfitsilishfitsshfitsilishfitsshfitsilishfitsshfittshiftshiftshiftshiftshiftshiftshiftshiftshiftshiftshiftiftiftishiftifishifishiftifishiftifishiftifishifishiftifishiftifi/shifthiftshiftfi/shifthiftshiftfi/shifthiftshiftfi/shifthiftshiftfi/shifthiftshiftfi/shifthiftshifi/shifthiftifi/si/hthithithithithithithithithththhtihihihihihihihtihtihtihtihtihtihtihitihtiihtiihtiihtiihihtiiihtiiihtihtihtihtiiihttiihtiiihttiiihttiiihttiihttiihttiiihttiihttiiihttiiihttitttitttitttittttiittiittiitiittiitiittiitiittiitiittiittiitiittiitiitiitiffffffffffffffffafafafafafffafffafffafffffafffaaaaaaaaaaafaafaafaafaafaafaaaafaaaafaafaafaaaafaaaafffaaaaafffaaaaafffaaaaafaaaaaaaaaaaaaaaa===========
+++++ 国产DB迁移.md