zoukankan      html  css  js  c++  java
  • 升级到Oracle 19c:你不可不知的十大SQL问题(上)

    众所周知,自 Oracle 18c开始,Oracle将数据库的版本发布变更为年度发布,以践行敏捷迭代的研发理念。所谓年度发布也就是按照年份,每年发布一个版本。2018年发布了Oracle 18c,2019年是Oracle 19c,2020年发布Oracle 20c(20c 云上版本已经在2月14日发布,按照官方计划公众发布是在4月)。


    这其中,18c = 12.2.0.2,19c = 12.2.0.3,这两个年度版本仍然处于 12c 的发布序列中,19c 属于 12c 体系的最后一个版本。由于 11g 已经退出了官方支持序列,越来越多的用户开始升级到 19c 。

    随着版本号的变化,补丁策略也随之改变,自18c开始,Oracle推出RU策略(Release Update),每个季度发布一个RU,所以对应18c,我们看到的RU系列版本号就是18.1,18.2等等,RU是一个累积的增量补丁,也就是说后发布的包含之前RU的内容,如果我们从18.1开始,可以直接应用18.4,跳过其间的18.2和18.3版本。

    由于每个季度的间隔事实上很大,如果期间用户报告了安全问题或严重的Bug,那么针对每个RU,Oracle还可能发布最多两个RUR(Release Update Revision)修订版本,其中主要包含安全补丁和重要的回归修复。

    下图是新策略下的Oracle数据库版本发布计划表:

    这个图,可能会让大多数人看得头晕,但是升级路径有一个原则,记住这个原则就一目了然了。这个原则就是:主版本号后面的2个数字之和要小于等于目标版本。例如 18.8.2 的低位 8+2 =10,这个版本可以升级到 18.10.0 ,但是不可以升级到 18.9.0,因为 9+0 < 10 。

    当然,在非特殊情况下,官方推荐采取 RU 路线的更新策略,这看起来就简化多了:

    当我们进行大版本升级时,总是建议用户通过SPA(SQL Performance Analyzer),对源环境和目标版本之间的测试,以避免出现SQL的兼容性问题或者性能问题,通过在源库进行SQL捕获,在目标库(通常是升级的高版本)进行重演,并生成性能对比报告,以指导用户的升级变更:

    而对于小版本的升级,往往无法进行如此详尽的测试准备工作,这就需要我们能够预先收集已知问题并做出防范。

    在进行数据库升级时,SQL 是最容易受到影响的部分,这些影响包括:

    1. SQL 语法发生改变:原应用SQL出错无法正确执行或执行结果发生改变;

    2. 内部函数改变:函数返回值或返回值类型发生变化,导致SQL结果出错或异常;

    3. 执行计划改变:因为算法调整,SQL的执行计划发生改变,一部分执行计划变坏,影响性能;

    4. 新特性的BUG:往往新特性引入,会带来相应的新BUG,影响系统性能或者稳定性;

    5. 次生BUG:因为修复某些BUG,而引入的新BUG,导致SQL可能出现不兼容或其他错误和异常;

    本文针对SQL方面的几个 19c 中典型案例,作为范例,希望能够为即将升级到 19c的朋友们提供一些经验借鉴。考虑到这些内容是DBA们知识储备的一部分,所以在一些知识点上做了介绍和扩展。

    1. Oracle 19.3 中优化器问题导致的执行结果错误

    在 Oracle 数据库跨版本升级时,很多SQL的新特性被引入到数据库中来,不可避免的,一些BUG会潜移默化的发生。而我们认为,最让人困扰的是那些SQL不出异常,但是查询结果出错的语句,这类SQL很难通过测试发现,只能在人们注意到查询结果出错时,才会追究并发现问题。

    以下就是这样一个问题,在 19.3 版本中广泛存在。创建简单的测试表和测试数据:

    SQL> CREATE TABLE ENMO AS SELECT * FROM DBA_OBJECTS;SQL> UPDATE ENMO SET EDITION_NAME = 'ORA$BASE' WHERE MOD(ROWNUM, 10000) = 0;SQL> CREATE TABLE TECH AS SELECT ROWNUM ID FROM ENMO;SQL> analyze table ENMO compute statistics;
    

    此时执行如下查询,可以从结果看到返回了2个零值,这个结果显然是错误的:

    SQL> set autotrace onSQL> SELECT COUNT(OBJECT_NAME || ‘, ‘ || OBJECT_TYPE), COUNT(EDITION_NAME) FROM ENMO, TECH WHERE ID = OBJECT_ID;
    COUNT(OBJECT_NAME||’,’||OBJECT_TYPE) COUNT(EDITION_NAME)------------------------------------ -------------------0                         0
    

    在以下执行计划中,可以看出执行计划的错误出现在第三个步骤,在这个步骤中,通过Filter增加了一个 NOT NULL 的过滤,这就使得大部分数据被抛弃了,进一步向上的查询连接自然就出现了结果集的错误:

    那么正常的情况应该是如何呢?去掉第二个输出,可以获得以下结果:

    SQL> SELECT COUNT(OBJECT_NAME || ', ' || OBJECT_TYPE) FROM ENMO, TECH WHERE ID = OBJECT_ID;
    COUNT(OBJECT_NAME||','||OBJECT_TYPE)------------------------------------             71789
    

    经过确认,这是一个因为修复BUG而引入的BUG。Oracle最为强大的地方是,几乎为每一个修正都加入了一个开关,如果发现某个修正引起了新的问题,那么通过开关就可以恢复原有的工作方式。

    以下语句就关闭了这个修复:

    SQL> alter session set "_fix_control"='24761824:OFF';
    Session altered.
    

    再来看现在的执行计划,去掉了 NOT NULL 的过滤,SQL执行结果恢复了正常:

     

    那么这个BUG是如何发生的呢

  • 相关阅读:
    LeetCode题解之Flipping an Image
    LeetCode 之Find Minimum in Rotated Sorted Array
    LeetCode题解Transpose Matrix
    LeetCode 题解之Minimum Index Sum of Two Lists
    LeetCode题解之Intersection of Two Linked Lists
    LeetCode 题解之Add Two Numbers II
    LeetCode题解之Add two numbers
    href="#"与href="javascript:void(0)"的区别
    有关ie9 以下不支持placeholder属性以及获得焦点placeholder的移除
    ie7下属性书写不规范造成的easyui 弹窗布局紊乱
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13311718.html
Copyright © 2011-2022 走看看