Quantcast
Channel: ANBOB
Viewing all 693 articles
Browse latest View live

Row source statistics执行计划的统计信息

$
0
0

在Oracle SQL优化时获取SQL执行计划每步的时间是很棒的方法,在11g 以后可以使用SQL monitor report 工具,但是需要DIAGNOSTIC+TUNING License, 但是Row source statistics并不需要。

Row source statistics是在执行 rowsource(执行计划的一个步骤)期间花费的时间、返回的行数、缓冲区获取数和物理读取和写入以及工作区使用情况的一些统计数据。当启用统计信息收集时,这些统计信息填充在V$SQL_PLAN_STATISTICS和V$SQL_PLAN_STATISTICS_ALL(基于X$QESRSTAT和X$QESRSTATALL)中。此外,如果启用了 sql_trace(10046 事件),那么这些统计信息将作为“STAT #”行内的详细信息记录跟踪文件中,并且可以在 tkprof 报告中作为执行计划查看。

仅当在查询执行之前打开统计信息收集时,才会为查询启用统计信息收集,并且只有在查询完成(有错误的事件)或取消时才能看到该统计信息收集。

Oracle 9i 中引入了Row source statistics,但没有有用的界面以方便的形式查看它们。在 10g 中引入了非常重要的工具 – 函数DBMS_XPLAN.DISPLAY_CURSOR具有许多有用的选项。该工具已成为SQL调优不可或缺的工具。

如何使用
可以通过以下选项之一启用行源统计信息的收集:

1. 将参数statistics_level设置为all(在会话或系统级别)
2. 使用hint gather_plan_statistics运行查询
3. 启用 SQL trace,及event++

采样频率
如果想计算统计信息,必定会涉及到一个采样频率,如果采样过多就会增加SQL的运行时间 。与rowsource statistic采样相关的,Oracle 中有一个隐藏参数 (_rowsource_statistics_sampfreq),默认为 128。这个参数必须始终设置为 2 的幂。
1, 如果此参数设置为 0,则rowsource statistics中没有时间计算。函数qerstSnapStats() / qerstUpdateStats()不获取时间戳.
2, 如果此参数设置为 1,则始终计算时间。每对qerstSnapStats() / qerstUpdateStats()都获得时间戳
3, 如果此参数设置为 N(默认值为 128),则每 N 个元组将获取时间戳。这意味着只有在某个行源级别上调用qerstSnapStats() / qerstUpdateStats()才会获得时间戳。
4, 有一个特殊值 3 可以只收集行数。

三种方式的使用
1, SQL trace是生成trace文件,在这种情况下只使用_rowsource_statistics_sampfreq。

而对于gather_plan_statistics和statistics_level这两个选项实际上是有区别的。

2, 每当您使用 /*+ gather_plan_statistics */ 提示时,Oracle 都会使用 _rowsource_statistics_sampfreq 参数确定采样计时信息的频率。 _rowsource_statistics_sampfreq 参数默认为 128。将其设置为更高的值将导致 Oracle 的采样次数更少。将其设置为较低的值将导致 Oracle 更频繁地进行采样。

3, 在会话或系统级别将参数statistics_level 设置为“all”,会将另一个隐藏参数参数 _rowsource_execution_statistics 设置为 TRUE,在这种情况下,_rowsource_statistics_sampfreq仅在参数已显示设置时使用,否则会忽略_rowsource_statistics_sampfreq 参数,而使用值为 1。

 

SQL> show parameter statistics_level

PARAMETER_NAME                TYPE        VALUE          
----------------------------  ----------- -------------- 
client_statistics_level       string      TYPICAL        
statistics_level              string      TYPICAL        

SQL> @pd rowsource
Show all parameters and session values from x$ksppi/x$ksppcv...                                                                                                     
																																								    
       NUM N_HEX NAME                                  VALUE                          DESCRIPTION                                                                   
---------- ----- ----------------------------------- - ------------------------------ ----------------------------------------------------------------------------- -
      3907   F43 _rowsource_execution_statistics       FALSE                          if TRUE, Oracle will collect rowsource statistics                             
      3908   F44 _rowsource_profiling_statistics       TRUE                           if TRUE, Oracle will capture active row sources in v$active_session_history   
      3909   F45 _rowsource_statistics_sampfreq        128                            frequency of rowsource statistic sampling (must be a power of 2)              
      4703  125F _olap_adv_comp_stats_max_rows         100000                         do additional predicate stats analysis for AW rowsource                       
      4704  1260 _olap_adv_comp_stats_cc_precomp       20                             do additional predicate stats analysis for AW rowsource                       

SQL>  alter session set statistics_level=all;
Session altered.

SQL> @pd rowsource
Show all parameters and session values from x$ksppi/x$ksppcv...

       NUM N_HEX NAME                                    VALUE        DESCRIPTION                                                                   
---------- ----- --------------------------------------  ---------- - ----------------------------------------------------------------------------- 
      3907   F43 _rowsource_execution_statistics         TRUE         if TRUE, Oracle will collect rowsource statistics                             
      3908   F44 _rowsource_profiling_statistics         TRUE         if TRUE, Oracle will capture active row sources in v$active_session_history   
      3909   F45 _rowsource_statistics_sampfreq          128          frequency of rowsource statistic sampling (must be a power of 2)              
      4703  125F _olap_adv_comp_stats_max_rows           100000       do additional predicate stats analysis for AW rowsource                       
      4704  1260 _olap_adv_comp_stats_cc_precomp         20           do additional predicate stats analysis for AW rowsource                       
																									   

Alexander Anokhin做了一个测试在10G 11g不同频率的一个SQL全表扫时,使用sql trace资源消耗。

freq 10g 11g
cpu timer calls cpu timer calls
default (128) 0,66 234 392 0,65 156 262
0 0,59 5 0,57 5
128 0,66 234 392 0,64 156 262
16 1,13 1 875 017 1,02 1 250 015
8 1,64 3 750 020 1,32 2 500 017
4 2,50 7 500 019 2,02 5 000 019
2 4,44 15 000 026 3,41 10 000 025
1 8,18 30 000 027 6,28 20 000 033

如果判断这一频率行为可以使用Digger (Dtrace)跟踪call 的调用。函数qer*( query execute rowsource)与此相关。可能在不同的版本不同的环境会有所不同,下面是在19c on linux 使用pstack简单的看一下函数调用

[oracle@oel7db1 ~]$ ora

SQL*Plus: Release 19.0.0.0.0 - Production on Sat Jul 17 08:20:56 2021
Version 19.3.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0


USERNAME             INST_NAME            HOST_NAME                  I# SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- --- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
SYS                  CDB$ROOT-anbob19c    oel7db1                     1 1     13017    19.0.0.0.0 20210717 10643      33    10642           0000000078081028 0000000078CF7F48


SQL> select count(*) from dba_objects, dba_objects,dba_objects;
                     *
# session 2
[root@oel7db1 oracle]# pstack 13321
#0  0x0000000012565858 in smbget ()
#1  0x0000000012560502 in sorgetqbf ()
#2  0x00000000126dee4e in qersoFetchSimple ()
#3  0x00000000126db192 in qersoFetch ()
#4  0x0000000003cd80ba in qerjoCartesianFetch ()
#5  0x00000000126e56e3 in qergsFetch ()
#6  0x00000000124042a6 in opifch2 ()
#7  0x0000000002d64d98 in kpoal8 ()
#8  0x000000001240ad02 in opiodr ()
#9  0x00000000127bdb56 in ttcpip ()
#10 0x00000000026d7987 in opitsk ()
#11 0x00000000026dc1c8 in opiino ()
#12 0x000000001240ad02 in opiodr ()
#13 0x00000000026d3466 in opidrv ()
#14 0x0000000003185685 in sou2o ()
#15 0x0000000000daa016 in opimai_real ()
#16 0x0000000003191821 in ssthrdmain ()
#17 0x0000000000da9e40 in main ()

SQL> select /*+gather_plan_statistics*/ count(*) from dba_objects, dba_objects,dba_objects;

# session 2
[root@oel7db1 oracle]# pstack 13321
#0  0x00000000126def1e in qersoFetchSimple ()
#1  0x00000000126db192 in qersoFetch ()
#2  0x0000000008c327b1 in qerstFetch ()
#3  0x0000000003cd80ba in qerjoCartesianFetch ()
#4  0x0000000008c327b1 in qerstFetch ()
#5  0x00000000126e56e3 in qergsFetch ()
#6  0x0000000008c327b1 in qerstFetch ()
#7  0x00000000124042a6 in opifch2 ()
#8  0x0000000002d64d98 in kpoal8 ()
#9  0x000000001240ad02 in opiodr ()
#10 0x00000000127bdb56 in ttcpip ()
#11 0x00000000026d7987 in opitsk ()
#12 0x00000000026dc1c8 in opiino ()
#13 0x000000001240ad02 in opiodr ()
#14 0x00000000026d3466 in opidrv ()
#15 0x0000000003185685 in sou2o ()
#16 0x0000000000daa016 in opimai_real ()
#17 0x0000000003191821 in ssthrdmain ()
#18 0x0000000000da9e40 in main ()
[root@oel7db1 oracle]# pstack 13321
#0  0x0000000008c313d4 in qerstSnapStats ()
#1  0x0000000008c324a9 in qerstRowP ()
#2  0x00000000126def0c in qersoFetchSimple ()
#3  0x00000000126db192 in qersoFetch ()
#4  0x0000000008c327b1 in qerstFetch ()
#5  0x0000000003cd80ba in qerjoCartesianFetch ()
#6  0x0000000008c327b1 in qerstFetch ()
#7  0x00000000126e56e3 in qergsFetch ()
#8  0x0000000008c327b1 in qerstFetch ()
#9  0x00000000124042a6 in opifch2 ()
#10 0x0000000002d64d98 in kpoal8 ()
#11 0x000000001240ad02 in opiodr ()
#12 0x00000000127bdb56 in ttcpip ()
#13 0x00000000026d7987 in opitsk ()
#14 0x00000000026dc1c8 in opiino ()
#15 0x000000001240ad02 in opiodr ()
#16 0x00000000026d3466 in opidrv ()
#17 0x0000000003185685 in sou2o ()
#18 0x0000000000daa016 in opimai_real ()
#19 0x0000000003191821 in ssthrdmain ()
#20 0x0000000000da9e40 in main ()

[root@oel7db1 oracle]# pstack 13321
#0  0x0000000008c3148a in qerstUpdateStats ()
#1  0x0000000008c32230 in qerstRowP ()
#2  0x00000000126def0c in qersoFetchSimple ()
#3  0x00000000126db192 in qersoFetch ()
#4  0x0000000008c327b1 in qerstFetch ()
#5  0x0000000003cd80ba in qerjoCartesianFetch ()
#6  0x0000000008c327b1 in qerstFetch ()
#7  0x00000000126e56e3 in qergsFetch ()
#8  0x0000000008c327b1 in qerstFetch ()
#9  0x00000000124042a6 in opifch2 ()
#10 0x0000000002d64d98 in kpoal8 ()
#11 0x000000001240ad02 in opiodr ()
#12 0x00000000127bdb56 in ttcpip ()
#13 0x00000000026d7987 in opitsk ()
#14 0x00000000026dc1c8 in opiino ()
#15 0x000000001240ad02 in opiodr ()
#16 0x00000000026d3466 in opidrv ()
#17 0x0000000003185685 in sou2o ()
#18 0x0000000000daa016 in opimai_real ()
#19 0x0000000003191821 in ssthrdmain ()
#20 0x0000000000da9e40 in main ()

[root@oel7db1 oracle]# pstack 13321|sh os_explain.sh
   kpoal8
    SELECT FETCH:
     QUERY EXECUTION STATISTICS: Fetch
      GROUP BY SORT: Fetch
       QUERY EXECUTION STATISTICS: Fetch
        NESTED LOOP OUTER: CartesianFetch
         QUERY EXECUTION STATISTICS: Fetch
          SORT: Fetch
           SORT: FetchSimple
            QUERY EXECUTION STATISTICS: RowP
             QUERY EXECUTION STATISTICS: RowP
              QUERY EXECUTION STATISTICS: SnapStats

SQL> alter session set statistics_level=all;
Session altered.

SQL> select count(*) from dba_objects, dba_objects,dba_objects;

# session 2
[root@oel7db1 oracle]# pstack 17757
#0  0x0000000012723398 in sltrgftime64 ()
#1  0x0000000008c3134a in qerstSnapStats ()
#2  0x0000000008c324a9 in qerstRowP ()
#3  0x0000000008c32461 in qerstRowP ()
#4  0x00000000126def0c in qersoFetchSimple ()
#5  0x00000000126db192 in qersoFetch ()
#6  0x0000000008c327b1 in qerstFetch ()
#7  0x0000000003cd80ba in qerjoCartesianFetch ()
#8  0x0000000008c327b1 in qerstFetch ()
#9  0x00000000126e56e3 in qergsFetch ()
#10 0x0000000008c327b1 in qerstFetch ()
#11 0x00000000124042a6 in opifch2 ()
#12 0x0000000002d64d98 in kpoal8 ()
#13 0x000000001240ad02 in opiodr ()
#14 0x00000000127bdb56 in ttcpip ()
#15 0x00000000026d7987 in opitsk ()
#16 0x00000000026dc1c8 in opiino ()
#17 0x000000001240ad02 in opiodr ()
#18 0x00000000026d3466 in opidrv ()
#19 0x0000000003185685 in sou2o ()
#20 0x0000000000daa016 in opimai_real ()
#21 0x0000000003191821 in ssthrdmain ()
#22 0x0000000000da9e40 in main ()
[root@oel7db1 oracle]# pstack 17757
#0  0x0000000008c31470 in qerstUpdateStats ()
#1  0x0000000008c32230 in qerstRowP ()
#2  0x0000000008c32461 in qerstRowP ()
#3  0x00000000126def0c in qersoFetchSimple ()
#4  0x00000000126db192 in qersoFetch ()
#5  0x0000000008c327b1 in qerstFetch ()
#6  0x0000000003cd80ba in qerjoCartesianFetch ()
#7  0x0000000008c327b1 in qerstFetch ()
#8  0x00000000126e56e3 in qergsFetch ()
#9  0x0000000008c327b1 in qerstFetch ()
#10 0x00000000124042a6 in opifch2 ()
#11 0x0000000002d64d98 in kpoal8 ()
#12 0x000000001240ad02 in opiodr ()
#13 0x00000000127bdb56 in ttcpip ()
#14 0x00000000026d7987 in opitsk ()
#15 0x00000000026dc1c8 in opiino ()
#16 0x000000001240ad02 in opiodr ()
#17 0x00000000026d3466 in opidrv ()
#18 0x0000000003185685 in sou2o ()
#19 0x0000000000daa016 in opimai_real ()
#20 0x0000000003191821 in ssthrdmain ()
#21 0x0000000000da9e40 in main ()
[root@oel7db1 oracle]# pstack 17757
#0  0x00007fffc01b6bc6 in clock_gettime ()
#1  0x00007f17f01907ed in clock_gettime () from /lib64/libc.so.6
#2  0x0000000012723398 in sltrgftime64 ()
#3  0x0000000008c315ef in qerstUpdateStats ()
#4  0x0000000008c32230 in qerstRowP ()
#5  0x00000000126def0c in qersoFetchSimple ()
#6  0x00000000126db192 in qersoFetch ()
#7  0x0000000008c327b1 in qerstFetch ()
#8  0x0000000003cd80ba in qerjoCartesianFetch ()
#9  0x0000000008c327b1 in qerstFetch ()
#10 0x00000000126e56e3 in qergsFetch ()
#11 0x0000000008c327b1 in qerstFetch ()
#12 0x00000000124042a6 in opifch2 ()
#13 0x0000000002d64d98 in kpoal8 ()
#14 0x000000001240ad02 in opiodr ()
#15 0x00000000127bdb56 in ttcpip ()
#16 0x00000000026d7987 in opitsk ()
#17 0x00000000026dc1c8 in opiino ()
#18 0x000000001240ad02 in opiodr ()
#19 0x00000000026d3466 in opidrv ()
#20 0x0000000003185685 in sou2o ()
#21 0x0000000000daa016 in opimai_real ()
#22 0x0000000003191821 in ssthrdmain ()
#23 0x0000000000da9e40 in main ()

[root@oel7db1 oracle]#   for i in {1..10} ; do  pstack 17757 |awk '{print $4}' ; usleep 100000 ; done | sort -r | uniq -c
     10 ttcpip
     10 ssthrdmain
     10 sou2o
      1 sorgetqbf
      3 sltrgftime64
      1 rworupo
      4 qerstUpdateStats
      3 qerstSnapStats
     12 qerstRowP
     30 qerstFetch
     10 qersoFetchSimple
     10 qersoFetch
     10 qerjoCartesianFetch
     10 qergsFetch
     10 opitsk
     20 opiodr
     10 opimai_real
     10 opiino
     10 opifch2
     10 opidrv
     10 main
     10 kpoal8
      6 clock_gettime

— enjoy —


Troubleshooting LGWR waits for event ‘DLM cross inst call completion’案例

$
0
0

客户一套Oracle 19c Dataguard的数据库环境,standby 端的总是会间隔性出现较大GAP, 同时DB alert log日志出现LGWR (ospid: 105521) waits for event ‘DLM cross inst call completion’ for N secs. 的现象,Standby端并未对外提供查询,同时也禁用了多实例日志应用,同时系统资源空闲LMS进程个数正常, 如果关闭其它节点只留apply log节点并不存在该问题, DLM 是Distributed Lock Manager 属于RAC架构中核心机制,实现多节点资源共享调度。通过interconnect Network传递请求,下面简单记录一下这个案例。

db alert log

PR00 (PID:109603): Media Recovery Log +ARCH/anbob1/ARCHIVELOG/2021_07_12/thread_3_seq_13586.1479.1077669291
2021-07-12T20:25:29.643687+08:00
PR00 (PID:109603): Media Recovery Log +ARCH/anbob1/ARCHIVELOG/2021_07_12/thread_2_seq_14361.1072.1077669019
2021-07-12T20:29:38.183656+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 1 secs.
2021-07-12T20:29:48.137737+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 2 secs.
2021-07-12T20:31:21.952345+08:00
 rfs (PID:113884): Selected LNO:26 for T-2.S-14456 dbid 3902007743 branch 1037635587
2021-07-12T20:31:21.987333+08:00
 rfs (PID:114704): Error ORA-235 occurred during an un-locked control file
 rfs (PID:114704): transaction.  This error can be ignored.  The control
 rfs (PID:114704): file transaction will be retried.
2021-07-12T20:31:43.532600+08:00
ARC2 (PID:106404): Archived Log entry 9591 added for T-2.S-14455 ID 0xe894b1bf LAD:1
2021-07-12T20:31:47.151671+08:00
 rfs (PID:113882): Selected LNO:31 for T-3.S-13731 dbid 3902007743 branch 1037635587
2021-07-12T20:31:49.116049+08:00
 rfs (PID:113880): Selected LNO:22 for T-1.S-13006 dbid 3902007743 branch 1037635587
2021-07-12T20:31:53.393547+08:00
ARC3 (PID:106408): Archived Log entry 9592 added for T-1.S-13005 ID 0xe894b1bf LAD:1
2021-07-12T20:32:02.346585+08:00
ARC2 (PID:106404): Archived Log entry 9593 added for T-3.S-13730 ID 0xe894b1bf LAD:1
2021-07-12T20:33:13.805344+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 0 secs.
2021-07-12T20:33:13.805470+08:00
LGWR (ospid: 105521) is hung in an acceptable location (inwait 0x1.ffff).
2021-07-12T20:33:21.196764+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 2 secs.
2021-07-12T20:33:31.310737+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 0 secs.
2021-07-12T20:33:41.223781+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 1 secs.
2021-07-12T20:33:51.205776+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 2 secs.
2021-07-12T20:34:01.307770+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 0 secs.
2021-07-12T20:34:25.440231+08:00
PR00 (PID:109603): Media Recovery Log +ARCH/anbob1/ARCHIVELOG/2021_07_12/thread_2_seq_14362.1867.1077670807
2021-07-12T20:34:44.864009+08:00
PR00 (PID:109603): Media Recovery Log +ARCH/anbob1/ARCHIVELOG/2021_07_12/thread_3_seq_13587.691.1077670845
2021-07-12T20:34:45.204773+08:00
PR00 (PID:109603): Media Recovery Log +ARCH/anbob1/ARCHIVELOG/2021_07_12/thread_1_seq_12934.1156.1077670917
2021-07-12T20:36:09.378685+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 2 secs.
2021-07-12T20:36:19.341635+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 0 secs.
2021-07-12T20:36:28.416573+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 0 secs.
2021-07-12T20:36:38.375742+08:00
LGWR (ospid: 105521) waits for event 'DLM cross inst call completion' for 1 secs.

LGWR trace

*** 2021-07-12T20:33:43.793041+08:00 ((4))
Received ORADEBUG command (#235) 'dump KSTDUMPCURPROC 1' from process '105470'
-------------------------------------------------------------------------------
Trace Bucket Dump Begin: default bucket for process 47 (osid: 105521, LGWR)
CDB_NAME(CON_ID):CON_UID:TIME(*=approx):SEQ:COMPONENT:FILE@LINE:FUNCTION:SECT/DUMP:SID:SERIAL#: [EVENT#:PID] DATA
-------------------------------------------------------------------------------
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1957:kjci_complete():4466:40278: freeing request 0x20fd651e8 (inst|inc|reqid)=(1|88|823031) with opcode=146 and completion status [DONE]
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1089:kjci_initreq():4466:40278: request 0x20fd651e8 (inst|inc|reqid)=(1|88|823032) with group (type|id)=(1|1), opcode=146, flags=0x0, msglen=56, where=[kqlmClusterMessage] to target instances=
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1091:kjci_initreq():4466:40278:    1 2
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1618:kjci_processcrq():4466:40278: processing reply 0x2cff2d4e8 for request 0x20fd651e8 (inst|inc|reqid)=(1|88|823032) with opcode=146 from callee (inst|pid|psn)=(1|36|1)
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1618:kjci_processcrq():4466:40278: processing reply 0x2cff2d718 for request 0x20fd651e8 (inst|inc|reqid)=(1|88|823032) with opcode=146 from callee (inst|pid|psn)=(2|36|1)
IRMSDB(4):3247498417:2021-07-12 20:33:42.784 :KJCI:kjci.c@1957:kjci_complete():4466:40278: freeing request 0x20fd651e8 (inst|inc|reqid)=(1|88|823032) with opcode=146 and completion status [DONE]
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1089:kjci_initreq():4466:40278: request 0x20fd651e8 (inst|inc|reqid)=(1|88|823033) with group (type|id)=(1|1), opcode=146, flags=0x0, msglen=56, where=[kqlmClusterMessage] to target instances=
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1091:kjci_initreq():4466:40278:    1 2
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1618:kjci_processcrq():4466:40278: processing reply 0x2cff2d4e8 for request 0x20fd651e8 (inst|inc|reqid)=(1|88|823033) with opcode=146 from callee (inst|pid|psn)=(1|36|1)
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1618:kjci_processcrq():4466:40278: processing reply 0x2cff2d718 for request 0x20fd651e8 (inst|inc|reqid)=(1|88|823033) with opcode=146 from callee (inst|pid|psn)=(2|36|1)
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1957:kjci_complete():4466:40278: freeing request 0x20fd651e8 (inst|inc|reqid)=(1|88|823033) with opcode=146 and completion status [DONE]
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1089:kjci_initreq():4466:40278: request 0x20fd651e8 (inst|inc|reqid)=(1|88|823034) with group (type|id)=(1|1), opcode=146, flags=0x0, msglen=56, where=[kqlmClusterMessage] to target instances=
IRMSDB(4):3247498417:2021-07-12 20:33:42.785 :KJCI:kjci.c@1091:kjci_initreq():4466:40278:    1 2

KJCJ  ==> (kjci)_processcrq – kernel lock management communication cross instance call

跨节点的通信,MOS中不存在已知BUG, 那先分析网络问题,也可以从进程blocker 如做SSD或查看hangmgr Trace. Oracle 19c CRS中AHF框架自带了OSW。

OSW netstat data

zzz ***Tue Jul 13 00:59:51 CST 2021
...
#kernel
IpInReceives                    1456201695         0.0
IpInHdrErrors                   0                  0.0
IpInAddrErrors                  0                  0.0
IpForwDatagrams                 0                  0.0
IpInUnknownProtos               0                  0.0
IpInDiscards                    0                  0.0
IpInDelivers                    1085210966         0.0
IpOutRequests                   1007206469         0.0
IpOutDiscards                   5280               0.0
IpOutNoRoutes                   8                  0.0
IpReasmTimeout                  6333500            0.0
IpReasmReqds                    408470736          0.0
IpReasmOKs                      37504539           0.0
IpReasmFails                    8651478            0.0
IpFragOKs                       29029579           0.0

Note:
当前存在较高的ip 重组失败包,这是一个累计值,下面可以查看日常变化。

查看日常IP重组失败情况

 awk '/zzz/{d=$3"/"$4" "$5}/IpReasmFails/{curr=$2;diff=curr-prev;if(diff>5)print d,diff,prev,curr;prev=curr}' *.dat
Jul/13 00:00:16 8620039  8620039
Jul/13 00:00:46 185 8620039 8620224
Jul/13 00:01:16 242 8620224 8620466
Jul/13 00:01:46 324 8620466 8620790
Jul/13 00:02:16 279 8620790 8621069
Jul/13 00:02:46 325 8621069 8621394
Jul/13 00:03:16 325 8621394 8621719
Jul/13 00:03:46 247 8621719 8621966
Jul/13 00:04:16 246 8621966 8622212
Jul/13 00:04:46 210 8622212 8622422
Jul/13 00:05:16 327 8622422 8622749
Jul/13 00:05:46 247 8622749 8622996
Jul/13 00:06:16 238 8622996 8623234
Jul/13 00:06:46 219 8623234 8623453
Jul/13 00:07:16 262 8623453 8623715
Jul/13 00:07:46 254 8623715 8623969
Jul/13 00:08:16 179 8623969 8624148
Jul/13 00:08:46 294 8624148 8624442

Note:
可见平时也存在较高的IP重组失败,下面尝试使用ping验证网络

使用ping 验证
— on node1

ping -s 4000 {node2-privateIP}

Note:

这里忘了保留历史输出,是发现有12% package loss,说明当前和心跳网络并不健康,不过是使用的2个网卡的做BOND,当前是Active-Backup主备模式,可以尝试切换另一个网卡。

网卡切换

cat /proc/net/bonding/bond0
<、pre>
Note:
检查 当前主卡是ens9f0,切换到备卡ens9f1
ifenslave -c bond0 ens9f1

做了主备网卡切换后,ping 正常,IP重组失败消失,DLM cross inst call completion未在出现,DG同步正常,问题得到解决。

Troubleshooting 19C DG standby crash with ORA-07445 [kcbzwb()+2265] [SIGSEGV]

$
0
0

一套Oracle 19c (19.8)RAC dataguard环境,standby 总时自动crash, 报错提示是lms进程异常触发ora-7445 kcbzwb 在cache层的内部错误, 确认为oracle bug, 后期应该比较常见,记录一下。

Dump file /u02/app/oracle/diag/rdbms/stdanbob/anbob1/incident/incdir_280197/anbob1_lms0_119036_119054_i280197.trc
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.8.0.0.0
Build label: RDBMS_19.8.0.0.0DBRU_LINUX.X64_200702
ORACLE_HOME: /u02/app/oracle/product/19.0.0/db_1
System name: Linux
Node name: anbob_com1
Release: 3.10.0-957.el7.x86_64
Version: #1 SMP Thu Oct 4 20:48:51 UTC 2018
Machine: x86_64
Instance name: anbob1
Redo thread mounted by this instance: 1
Oracle process number: 24
Unix process pid: 119036, thread id: 119054, image: oracle@anbob_com1 (LMS0)

*** 2021-07-05T15:48:46.750428+08:00
*** SESSION ID:(2281.44449) 2021-07-05T15:48:46.750501+08:00
*** CLIENT ID:() 2021-07-05T15:48:46.750525+08:00
*** SERVICE NAME:() 2021-07-05T15:48:46.750544+08:00
*** MODULE NAME:() 2021-07-05T15:48:46.750572+08:00
*** ACTION NAME:() 2021-07-05T15:48:46.750591+08:00
*** CLIENT DRIVER:() 2021-07-05T15:48:46.750609+08:00
*** CONTAINER ID:(4) 2021-07-05T15:48:46.750632+08:00

[TOC00000]
Jump to table of contents
Dump continued from file: /u02/app/oracle/diag/rdbms/stdanbob/anbob1/trace/anbob1_lms0_119036_119054.trc
[TOC00001]
ORA-07445: exception encountered: core dump [kcbzwb()+2265] [SIGSEGV] [ADDR:0xCC] [PC:0x1D9E009] [Address not mapped to object] []

----- Call Stack Trace -----
calling              call     entry                argument values in hex      
location             type     point                (? means dubious value)     
-------------------- -------- -------------------- ----------------------------
ksedst1()+95         call     kgdsdst()            7FFFEF55A430 000000003
                                                   7FFFEF554760 ? 7FFFEF554878 ?
                                                   000000000 000000083 ?
ksedst()+58          call     ksedst1()            000000001 000000001
                                                   7FFFEF554760 ? 7FFFEF554878 ?
                                                   000000000 ? 000000083 ?
dbkedDefDump()+2344  call     ksedst()             000000001 000000001 ?
8                                                  7FFFEF554760 ? 7FFFEF554878 ?
                                                   000000000 ? 000000083 ?
ksedmp()+577         call     dbkedDefDump()       000000003 000000003
                                                   7FFFEF554760 ? 7FFFEF554878 ?
                                                   000000000 ? 000000083 ?
ssexhd()+2859        call     ksedmp()             00000044F 000000003 ?
                                                   7FFFEF554760 ? 7FFFEF554878 ?
                                                   000000000 ? 000000083 ?
sslssSynchHdlr()+40  call     ssexhd()             00000000B 000000000
1                                                  7FFFEF55BBF0 7FFFEF55BAC0
                                                   7FFFEF55BA28 000000083 ?
sslsshandler()+94    call     sslssSynchHdlr()     000002000 000000000 000000000
                                                   7FFFEF55BAC0 ? 7FFFEF55BA28 ?
                                                   000000083 ?
__sighandler()       call     sslsshandler()       00000000B 7FFFEF55BBF0
                                                   7FFFEF55BAC0 7FFFEF55BAC0 ?
                                                   7FFFEF55BA28 ? 000000083 ?
kcbzwb()+2265        signal   __sighandler()       0000004E3 000000000 001024181
                                                   624DD2F1A9FBE77 ? 000000000 ?
                                                   000029522 ?
kcbgtcr()+68032      call     kcbzwb()             424FEA8A0 ? 0000001A1 ?
                                                   41AA18970 7FFFF15F97E0
                                                   000000001 000000033 ?
kclgeneratecr()+785  call     kcbgtcr()            7FFFF15F9E90 000000000
5                                                  00000001C 000000000
                                                   000000001 ? 000000033 ?
kclgeneratecr_pdb()  call     kclgeneratecr()      400027B69548 7FFFF15FB0A0
+3924                                              7FFFF15FAE30 060000000
                                                   000000000 0000038B4
kclgcr()+334         call     kclgeneratecr_pdb()  400027B69548 7FFFF15FB0A0
                                                   7FFFF15FAE30 060000000
                                                   000000000 0000038B4
kclcrrf()+310        call     kclgcr()             400027B69548 7FFFF15FB0A0
                                                   7FFFF15FAE30 060000000
                                                   0000038B4 000000002
kjblcrcbk()+459      call     kclcrrf()            47FBCF340 400027B69548
                                                   000000098 060000000
                                                   7FFFF15FB0A0 000000000
kjbrscrping()+1695   call     kjblcrcbk()          00003F158 0000001A1
                                                   FFFFFFFFFFFFFFFF
                                                   FFFFFFFFE7FA0004 47FBCF340
                                                   400027B69548
kjbrcrcvt()+1525     call     kjbrscrping()        2F1AEDF48 41FD57948 000000000
                                                   47F53D540 000000B6D 000000001
kjbmpocr()+42072     call     kjbrcrcvt()          2F1AEDF48 41FD57948 000000000
                                                   47F53D540 000000B6D 000000B6D
kjmxmpm()+1174       call     kjbmpocr()           000000001 41FD57948 ?
                                                   000000000 ? 47F53D540 ?
                                                   400000B6D 000000B6D ?
kjmpmsgi()+708       call     kjmxmpm()            400027B694A0 7FFFF16089D0
                                                   0681EC1FC 000000001 000000000
                                                   000000000
kjmsm()+5040         call     kjmpmsgi()           400027B694A0 000000001
                                                   000000001 7FFFF16089D0
                                                   000000000 000000000 ?
ksbdispatch()+365    call     kjmsm()              3E3F9F3D0 000000001 ?
                                                   000000001 ? 7FFFF16089D0 ?
                                                   000000000 ? 000000000 ?
opirip()+522         call     ksbdispatch()        3E3F9F3D0 ? 000000001 ?

There is a valid scenario where LMS could serve a CR block even when that PDB is marked “closed”. In this case PDB SGA will remain uninitialized and hence wait stats will not be updated.

相关的2个BUG Bug 31796882和Bug 30647133

再续PGA 和max_map_count、_realfree_heap_pagesize

$
0
0

之前分享过《PGA 一点认识》《Know more about PGA_AGGREGATE_LIMIT 12c 19c》 看到限制PGA的参数有_PGA_MAX_SIZE、 _SMM_(PX)_MAX_SIZE、PGA_AGGREGATE_TARGET、PGA_AGGREGATE_LIMIT ,为了提高SQL性能手动增加_PGA_MAX_SIZE参数值,如在数据仓库环境可能更明显,最近看到一个案例在执行存储过程时,当把参数_PGA_MAX_SIZE 调到4GB以上时(default 2GB),依旧遇到了ora-4030 错误, trace 文件中显示上限达4GB的上限,Process Map Dump 达65537行。

在MOS中查找不难发现PLSQL Procedure Causing ORA-04030: (pga heap,control file i/o buffer) And ORA-04030: (koh-kghu sessi,pmuccst: adt/record) or ORA-04030: (koh-kghucall ,pmucalm coll) Errors (Doc ID 1325100.1) 匹配,提到了解决方案有2种
1,增加操作系统级page map的个数

more /proc/sys/vm/max_map_count
sysctl -w vm.max_map_count=262144 (for example)   -- add /etc/sysctl.conf
-- or --

2, 增加数据库级realfree heap pagesize大小,需要重启数据库
For versions 11.2.0.4 and lower:

_use_realfree_heap=TRUE
_realfree_heap_pagesize_hint = 262144

For 12.1 and higher:

_use_realfree_heap=TRUE
_realfree_heap_pagesize = 262144

检查默认配置

[oracle@oel7db1 ~]$ sysctl -a|grep max_map
vm.max_map_count = 65530

SQL> @pd realfree
Show all parameters and session values from x$ksppi/x$ksppcv...

       NUM N_HEX NAME                                                     VALUE                          DESCRIPTION
---------- ----- -------------------------------------------------------- ------------------------------ ---------------------------------------------------------------------------------------------------
       192    C0 _realfree_heap_max_size                                  32768                          minimum max total heap size, in Kbytes
       193    C1 _realfree_heap_pagesize                                  65536                          hint for real-free page size in bytes
       194    C2 _realfree_pq_heap_pagesize                               65536                          hint for pq real-free page size in bytes
       195    C3 _realfree_heap_mode                                      0                              mode flags for real-free heap
       196    C4 _use_realfree_heap                                       TRUE                           use real-free based allocator for PGA memory

[oracle@oel7db1 ~]$ echo 65536*65530/1024/1024|bc
4095

默认数据库realfree allocator pagesize 是 64 kB (65536), 操作系统vm.max_map_count默认是65530, 64*65530=4GB. 如果把realfree heap pagesize增加到256kB (262144) 上限就成了16GB.对于多租户修改CDB级参数即可,PDB继承。

解决问题一方面增加单个进程PGA上限,另一方面要检查为什么单个进程PGA使用这么高?是否是合理?当发现有些进程使用PGA或内存使用较高时,如11g, 12, 19c都存在的bug ASM的dia0/diag 进程内存较大时,检查方法:

column name format a25
column pname format a12
column "MegaBytes" format a10
set numwidth 6

select ss.sid, p.pid, p.pname, sn.name, round(ss.value/(1024 *1024))||'Mb' "MegaBytes"
from v$sesstat ss, v$statname sn, v$session s, v$process p
where s.paddr = p.addr
and sn.statistic# = ss.statistic#
and s.sid = ss.sid
and sn.name in ('session pga memory' , 'session pga memory max')
and p.pname='DIA0'
order by ss.value
/

oradebug setorapid xxx
oradebug unlimit
oradebug dump heapdump 1
oradebug tracefile_name

-- format trace file using heap.awk

查找内存使用相关的SQL和heap名称,查询是否有bug? 如上面提到的bug  diag/dia进程可以kill 自动重启进程释放内存。

在Linux系统中可以使用pmap查看Process Map 记录数,但是当我在RAC on  RHEL 7环境使用oracle用户用pmap查看server process(LOCAL=NO),提示无权限。如果使用strace跟踪是在read  /proc/PID/maps文件时. 查看文件系统权限时:

$ ls -l /proc/NNNN/
-r--r--r-- 1 root root 0 Aug  9 16:06 maps
-rw------- 1 root root 0 Aug  9 16:06 mem
...
-r--r--r-- 1 root root 0 Aug  9 16:06 smaps
-r--r--r-- 1 root root 0 Aug  9 16:06 stack
-r--r--r-- 1 root root 0 Aug  9 16:06 stat
-r--r--r-- 1 root root 0 Aug  9 16:06 statm
-r--r--r-- 1 root root 0 Aug  9 16:06 status

注意是-r-r-r的权限,单从文件权限看other是有read权限的,使用oracle用户cat maps文件无权限,如果尝cat status文件是可以,后来从官方《Permission denied when reading /proc/$PID/* owned by the user》 和stackoverflow 找到了答案。

It’s because the file permissions are not the only protection you’re encountering.

Those aren’t just regular text files on a file system, procfs is a window into process internals and you have to get past both the file permissions plus whatever other protections are in place.

The maps show potentially dangerous information about memory usage and where executable code is located within the process space. If you look into ASLR, you’ll see this was a method of preventing potential attackers from knowing where code was loaded and it wouldn’t make sense to reveal it in a world-readable entry in procfs.

This protection was added way back in 2007:

This change implements a check using “ptrace_may_attach” before allowing access to read the maps contents. To control this protection, the new knob /proc/sys/kernel/maps_protect has been added, with corresponding updates to the procfs documentation.

Within ptrace_may_attach() (actually within one of the functions it calls) lies the following code:

if (((current->uid != task->euid) ||
(current->uid != task->suid) ||
(current->uid != task->uid) ||
(current->gid != task->egid) ||
(current->gid != task->sgid) ||
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
return -EPERM;
so that, unless you have the same real user/group ID, saved user/group ID and effective user/group ID (i.e., no sneaky setuid stuff) and they’re the same as the user/group ID that owns the process, you’re not allowed to see inside that “file” (unless your process has the CAP_SYS_PTRACE capability of course).

文件权限只是控制文件读写的一方面,对于/proc文件系统中文件,出于安全原因,从其他进程内存读取有额外的权限检查, /proc/$PID/maps显示了有关内存使用情况,以及可执行代码在进程空间中的位置的潜在危险信息, 操作系统在内核级使用CAP(Capabilities)机制控制,对于内核调用时可以分类分别控制,如果文件没有相同的UID/GID,还要确保使用 $PID 的进程对核心转储功能没有限制,可以临时启用审计规则auditctl 调测。简而言之就是使用pmap跟踪程序时,尝试read  /proc/PID的文件时需要CAP_SYS_PTRACE Capabilities, oracle读取root owner的maps文件,可以通过以下方式授权:

su - root
# setcap cap_sys_ptrace=eip /usr/bin/pmap

12c 新特性rowsets(_rowsets_enabled=true) bug,19c bug ORA-00600 [qesrLoopOverSetRowP:rows]

$
0
0

最近在19C(19.8)的ORACLE数据库上遇到了ORA-00600 [qesrLoopOverSetRowP:rows]错误,解决方法中提到了禁用rowsets ,“rowsets”这是一个新的 Oracle 12c 特性, 是SQL层执行计划相关的内部优化,上周刚整理了Row source statistics执行计划的统计信息,关于rowsets的信息非常少,在Mike Dietrich’s Blog几年前描述过:

“Rowsets is a SQL execution performance enhancement introduced in Oracle RDBMS release 12.1 and further extended in a future release of the Oracle Database.

Prior to 12.1, data processing in the SQL layer were done on a row by row basis. That is, each row source in the row source tree performing a specific SQL operation (scan, join aggregation, window function, connect by etc) consume and produce one row at a time. Starting in 12.1, we introduced the concept of rowsets, where many row sources were enhanced to consume and produce rows in batches called rowsets. It is an internal performance optimization project. That is why there isn’t much documentation.

This is a fundamental change in the SQL layer row processing. The benefits of rowsets is not only instruction cache locality but it also enables other performance optimizations such as, vectorization and prefetch in row sources and expression evaluation.”

在12.1 中存在wrong result的bug,  解决办法同样是禁用rowsets或使用event 10055禁用特定的使用场景。如果在12.1中是建议禁用rowsets, 但毕竟是一个优化项,19c 版本也做了扩展建议保持启用,对于19c ORA-00600 [qesrLoopOverSetRowP:rows]解决方法是

Disable rowsets.
alter system set “_rowsets_enabled”=FALSE scope=both sid=’*’;

– OR –

A more targeted workaround that should have less/minimal performance impact is to set event 10123 to level 4.
“alter session set events ‘10123 trace name context forever, level 4’ ”

我尝试在19c中尝试一下,哪里体现rowsets。

SQL> set feedback on sql_id
SQL> set transaction read only;

Transaction set.

SQL_ID: 9hb4u1cj9x90h
SQL> set arraysize 4

SQL> select * from anbob.test1 t1 ,anbob.test1 t2 where t1.id=t2.id and  t1.id=1000;

        ID         ID
---------- ----------
      1000       1000

1 row selected.

SQL_ID: 9fz9rw2tt9zjh

SQL> select * from table(dbms_xplan.display_cursor('9fz9rw2tt9zjh',0,'-note +projection'));

PLAN_TABLE_OUTPUT
------------------------------------------------
SQL_ID  9fz9rw2tt9zjh, child number 0
-------------------------------------
select * from anbob.test1 t1 ,anbob.test1 t2 where t1.id=t2.id and
t1.id=1000

Plan hash value: 2587486242

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |       |       |    16 (100)|          |
|*  1 |  HASH JOIN         |       |     1 |     8 |    16   (0)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| TEST1 |     1 |     4 |     8   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| TEST1 |     1 |     4 |     8   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T1"."ID"="T2"."ID")
   2 - filter("T1"."ID"=1000)
   3 - filter("T2"."ID"=1000)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=1; rowset=256) "T1"."ID"[NUMBER,22], "T2"."ID"[NUMBER,22]
   2 - (rowset=256) "T1"."ID"[NUMBER,22]
   3 - (rowset=256) "T2"."ID"[NUMBER,22]

30 rows selected.
SQL_ID: 7c27fm7ck0hmc

注意:
在Column Projection Information信息中出现了rowset的关键字。

关闭该特性在12c中有event 10055, 对应不对的级别,18c增加了更多的级别,同时增加了新的event 10123.

[oracle@oel7db1 ~]$ oerr ora 10055
10055, 00000, "Rowsets: turn off rowsets for various operations"
// *Document: NO
// *Cause:    N/A
// *Action:   Turns off rowsets for various operations
//            Level:
//            0x00000001 - turn off for table scan
//            0x00000002 - turn off for hash join consume
//            0x00000004 - turn off for hash join produce
//            0x00000008 - turn off for group by
//            0x00000010 - turn off for sort
//            0x00000020 - turn off for table-queue out
//            0x00000040 - turn off for table-queue in
//            0x00000080 - turn off for identity
//            0x00000100 - turn off for granule iterator
//            0x00000200 - turn off for EVA functions
//            0x00000400 - turn off for PL/SQL
//            0x00000800 - turn off for upgrade
//            0x00001000 - turn off for database startup
//            0x00002000 - turn off for blobs and clobs
//            0x00004000 - turn off for tracing row source
//            0x00008000 - turn off rowset information in explain plan
//            0x00010000 - disable hash join rowsets fast path
//            0x00020000 - turn off for bloom create
//            0x00040000 - turn off for bloom use
//            0x00080000 - disable prefetch for hash join
//            0x00100000 - disable prefetch for bloom
//            0x00200000 - disable semi blocking hash join
//            0x00400000 - turn off rowset for fixed table
//  12.2 adds 2 new levels
//            0x00800000 - turn off rowset for view
//            0x01000000 - turn off rowset for filter
//  18.3 moves to event 10123 and adds 7 new levels 
//            0x02000000 - disable producing rowsets in scan with one-row eva
//            0x04000000 - turn off rowsets for non-inner hash join
//            0x08000000 - turn off rowsets for update
//            0x10000000 - turn off rowsets for delete
//            0x20000000 - disable prefetch for hash aggregation
//            0x40000000 - turn off rowsets for window function
//            0x80000000 - turn off rowsets for count

[oracle@oel7db1 ~]$ oerr ora 10123
10123, 00000, "Rowsets: turn off rowsets for various operations"
// *Document: NO
// *Cause:    N/A
// *Action:   Turns off rowsets for various operations
//            Level:
//            0x00000001 - turn off for top select
//

Alert: Oracle 19c ORA-30481 or ORA-7445 [qecgoc2()] _optimizer_aggr_groupby_elim

$
0
0

oracle升级是一项大工程,性能、语法、函数变化都可能导致应用无法使用,十几年前在记的在升级11g时因SQL语法修正了一个order by相关的bug, 使语法更加严格导致应用报错,导致应用和DBA争执最后大老板来平息, 最近几年升级19c的较多,一定要做足升级前测试,并不是只有wm_concat函数没了,再手动创建一个那么easy,  前几年升级12c是发过一个案例《Troubleshooting ORA-00979: not a GROUP BY expression after upgrade Oracle 12C》 ,也是同一个SQL在升级后提示语法错误。   这里演示一个19c 的另一个语法问题,后面会陆续在微信公众号分享 《oracle19c 避雷系列》。

USERNAME             INST_NAME            HOST_NAME                  I# SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- --- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
SYS                  CDB$ROOT-anbob19c    oel7db1                     1 96    596      19.0.0.0.0 20210802 4229       33    4228            000000007816DF40 0000000078CF7F48


select x,count(z), grouping(x)
  from
    (select x,count(y) z
    from
            (select 1 as x,2 as y,3 as z from dual
            union all
            select 4 as x,5 as y, 6 as z from dual)
    group by x) a
  9    group by x;
            (select 1 as x,2 as y,3 as z from dual
                                              *
ERROR at line 5:
ORA-30481: GROUPING function only supported with GROUP BY CUBE or ROLLUP

SQL> show parameter feature

PARAMETER_NAME                                               TYPE        VALUE
------------------------------------------------------------ ----------- ----------------------------------------------------------------------------------------------------
_exadata_feature_on                                          boolean     TRUE
disable_pdb_feature                                          big integer 0
optimizer_features_enable                                    string      19.1.0
SQL>

SQL> alter session set optimizer_features_enable='11.2.0.4';
Session altered.

select x,count(z), grouping(x)
  from
    (select x,count(y) z
    from
            (select 1 as x,2 as y,3 as z from dual
            union all
            select 4 as x,5 as y, 6 as z from dual)
    group by x) a
  9    group by x;

         X   COUNT(Z) GROUPING(X)
---------- ---------- -----------
         1          1           0
         4          1           0

SQL> alter session set optimizer_features_enable='12.1.0.2';
Session altered.

select x,count(z), grouping(x)
  from
    (select x,count(y) z
    from
            (select 1 as x,2 as y,3 as z from dual
            union all
            select 4 as x,5 as y, 6 as z from dual)
    group by x) a
  9    group by x;
            (select 1 as x,2 as y,3 as z from dual
                                              *
ERROR at line 5:
ORA-30481: GROUPING function only supported with GROUP BY CUBE or ROLLUP

Note:
这是使用了一个grouping 的SQL, 在11.2.0.4运行正常,但是在19c提示ora-30481, 不过也确实没有使用group by cube或rollup, 经过反复尝试发现在12.1就发生了改变。

对于11.2.0.4和12.1 的参数变化

SQL> @comp_ofe_params 11.2.0.4  12.1.0.2
Compare Optimizer_Features_Enable Parameter differences
for values 11.2.0.4 and 12.1.0.2

PARAMETER                                        '11.2.0.4'                     '12.1.0.2'                     DESCRIPTION
------------------------------------------------ ------------------------------ ------------------------------ ----------------------------------------------------------------------
_gby_vector_aggregation_enabled                  FALSE                          TRUE                           enable group-by and aggregation using vector scheme
_optimizer_unnest_scalar_sq                      FALSE                          TRUE                           enables unnesting of of scalar subquery
_optimizer_cluster_by_rowid_control              3                              129                            internal control for cluster by rowid feature mode
_optimizer_partial_join_eval                     FALSE                          TRUE                           partial join evaluation parameter
_optimizer_ansi_rearchitecture                   FALSE                          TRUE                           re-architecture of ANSI left, right, and full outer joins
_optimizer_use_gtt_session_stats                 FALSE                          TRUE                           use GTT session private statistics
_optimizer_proc_rate_level                       OFF                            BASIC                          control the level of processing rates
_distinct_agg_optimization_gsets                 OFF                            CHOOSE                         Use Distinct Aggregate Optimization for Grouping Sets
_optimizer_inmemory_autodop                      FALSE                          TRUE                           optimizer autoDOP costing for in-memory
_optimizer_nlj_hj_adaptive_join                  FALSE                          TRUE                           allow adaptive NL Hash joins
_optimizer_vector_transformation                 FALSE                          TRUE                           perform vector transform
optimizer_features_enable                        11.2.0.4                       12.1.0.2                       optimizer plan compatibility parameter
_optimizer_undo_cost_change                      11.2.0.4                       12.1.0.2                       optimizer undo cost change
_optimizer_ansi_join_lateral_enhance             FALSE                          TRUE                           optimization of left/full ansi-joins and lateral views
_optimizer_multi_table_outerjoin                 FALSE                          TRUE                           allows multiple tables on the left of outerjoin
_optimizer_aggr_groupby_elim                     FALSE                          TRUE                           group-by and aggregation elimination
_optimizer_cube_join_enabled                     FALSE                          TRUE                           enable cube join
_optimizer_gather_stats_on_load                  FALSE                          TRUE                           enable/disable online statistics gathering
_optimizer_batch_table_access_by_rowid           FALSE                          TRUE                           enable table access by ROWID IO batching
_optimizer_inmemory_table_expansion              FALSE                          TRUE                           optimizer in-memory awareness for table expansion
_optimizer_strans_adaptive_pruning               FALSE                          TRUE                           allow adaptive pruning of star transformation bitmap trees
_adaptive_window_consolidator_enabled            FALSE                          TRUE                           enable/disable adaptive window consolidator PX plan
_optimizer_cluster_by_rowid                      FALSE                          TRUE                           enable/disable the cluster by rowid feature
_optimizer_reduce_groupby_key                    FALSE                          TRUE                           group-by key reduction
_optimizer_inmemory_bloom_filter                 FALSE                          TRUE                           controls serial bloom filter for in-memory tables
_optimizer_null_accepting_semijoin               FALSE                          TRUE                           enables null-accepting semijoin
_optimizer_hybrid_fpwj_enabled                   FALSE                          TRUE                           enable hybrid full partition-wise join when TRUE
_optimizer_cluster_by_rowid_batched              FALSE                          TRUE                           enable/disable the cluster by rowid batching feature
_optimizer_inmemory_gen_pushable_preds           FALSE                          TRUE                           optimizer generate pushable predicates for in-memory
_optimizer_inmemory_access_path                  FALSE                          TRUE                           optimizer access path costing for in-memory
_optimizer_inmemory_cluster_aware_dop            FALSE                          TRUE                           Affinitize DOP for inmemory objects
_optimizer_inmemory_minmax_pruning               FALSE                          TRUE                           controls use of min/max pruning for costing in-memory tables

47 rows selected.

经过以上参数的回退操作

SQL> alter session set "_optimizer_aggr_groupby_elim"=false;

Session altered.

select x,count(z), grouping(x)
  from
    (select x,count(y) z
    from
            (select 1 as x,2 as y,3 as z from dual
            union all
            select 4 as x,5 as y, 6 as z from dual)
    group by x) a
       group by x;

         X   COUNT(Z) GROUPING(X)
---------- ---------- -----------
         1          1           0
         4          1           0

最终确认了修改set “_optimizer_aggr_groupby_elim”=false; 可以解决该问题。

当然如果修改语法也可以解决

select x,count(z), grouping(x)
  from
    (select x,count(y) z
    from
            (select 1 as x,2 as y,3 as z from dual
            union all
            select 4 as x,5 as y, 6 as z from dual)
    group by x) a
  9         group by CUBE(x);

         X   COUNT(Z) GROUPING(X)
---------- ---------- -----------
                    2           1
         1          1           0
         4          1           0

与_optimizer_aggr_groupby_elim参数相关在12c也有多个bug, 另外在19c中同样还可能遇到ORA-7445 [qecgoc2()] 错误,而不是ora-979语义错误,确认为已知Bug 30889723 影响19c多个版本。

qecgoc –> query execute edit checking group operand check

解决方法同样是Setting “_optimizer_aggr_groupby_elim”=false;

所以建议在19c中建议主动把 “_optimizer_aggr_groupby_elim”=false;规避问题。

 

Troubleshooting 19c ORA-00600 [kkpapDIPObjNum1] when split partition

$
0
0

之前分享过oracle split分区的内部检查方式《 oracle fast split partition 》,我们一个客户目前还是人肉拆分区模式,每月10余万的分区, 最近遇到一个Oracle 19c(19.9) 拆分区时ora-600 错误[kkpapDIPObjNum1]  , 问题是当split分区时递归的分区检索SQL, 分区列上只有全局分区,分区裁剪的分区未发现任何分区数据。

kkpapDIPObjNum1==> kernel compile compilation partitioning…

SQL:

[TOC00003]
----- Current SQL Statement for this session (sql_id=f19turzmr9u50) -----
select /*+ FIRST_ROWS(1) PARALLEL("xxxxx", 1) */ 1 from NO_CROSS_CONTAINER("xxx"."xxxxx") PARTITION ("PART_999_MAX") where ( ( ( ( "REGION" > 999 ) ) OR ( "REGION" = 999 AND ( "CREATEDATE" >= TO_DATE(' 2021-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') ) ) ) ) and rownum < 2
[TOC00003-END]

Call Stack:

kkpapDIPObjNum>> kkopBuildPnumPred >> kkoUpdateFroAnn>> kkoipt >> kkoqbc

Demo

SQL> create table ANBOB.torder
  2   (id int ,
  3   region number,
  4   timeid number,
  5   xxx number
  6   )
  7   partition by range (region,timeid)
  8   (
  9   partition p_110_2020 values less than(110,2021),
 10   partition p_110_2021 values less than(110,2022)
 11   );

Table created.

SQL> @seg ANBOB.torder

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         4 ANBOB                 TORDER                         P_110_2020                     TABLE PARTITION      IDX313                                512        683     971913
         4 ANBOB                 TORDER                         P_110_2021                     TABLE PARTITION      IDX313                                512        683     972425

SQL>  exec DBMS_STATS.GATHER_TABLE_STATS (ownname => '&TOWN' , tabname => '&TNAME' , cascade => true, estimate_percent => dbms_stats.auto_sample_size,method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE REPEAT',  degree => 8,no_invalidate=>false); 
Enter value for town: ANBOB
Enter value for tname: torder

PL/SQL procedure successfully completed.

SQL> select 1 from ANBOB.torder partition(p_110_2021) where (region>110) and rownum<2;
 no rows selected 

SQL> create index ANBOB.idx_torder on ANBOB.torder(id,region);

Index created.

SQL>  exec DBMS_STATS.GATHER_TABLE_STATS (ownname => '&TOWN' , tabname => '&TNAME' , cascade => true, estimate_percent => dbms_stats.auto_sample_size,method_opt=>'FOR TABLE FOR ALL COLUMNS SIZE REPEAT',  degree => 8,no_invalidate=>false); 
Enter value for town: ANBOB
Enter value for tname: torder

PL/SQL procedure successfully completed.

SQL> select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2; 
select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2
                   *
ERROR at line 1:
ORA-00600: internal error code, arguments: [kkpapDIPObjNum1], [], [], [], [], [], [], [], [], [], [], []

问题出在创建的全局索引后。

SQL> select /*+full(t)*/ 1 from ANBOB.torder partition(p_110_2020) t where (region>110) and rownum<2;
no rows selected

SQL> explain plan for select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2;
explain plan for select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [kkpapDIPObjNum1], [], [], [], [], [], [], [], [], [], [], []

SQL> create index ANBOB.idx_torder_l on ANBOB.torder(region) local;
Index created.

SQL> explain plan for select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2;
Explained.

SQL> @x2

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
Plan hash value: 2063533098

-------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |     4 |     1   (0)| 00:00:01 |       |       |
|*  1 |  COUNT STOPKEY         |              |       |       |            |          |       |       |
|   2 |   PARTITION RANGE EMPTY|              |     1 |     4 |     1   (0)| 00:00:01 |INVALID|INVALID|
|*  3 |    INDEX RANGE SCAN    | IDX_TORDER_L |     1 |     4 |     1   (0)| 00:00:01 |INVALID|INVALID|
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<2) 3 - access("REGION">110)

16 rows selected.

SQL> select 1 from ANBOB.torder partition(p_110_2020) where (region>110) and rownum<2;
no rows selected

Note:
这是oracle的已知Bug 31667096, 影响19.6 19.7 19.9版本, 在19.11 RU引入补丁。除了安装对应的补丁,发现创建索引列的local索引可以临时解决。

Oracle 12cR2 : DataGuard 、 ZDLRA、REDO_TRANSPORT_USERT

$
0
0

在 DataGuard 环境中,默认情况下,当使用密码文件时,SYS 用户的密码用于验证重做传输会话。但出于安全原因,您可能不希望仅将如此高特权的用户用于重做传输。为了克服这个问题,Oracle 实现了 REDO_TRANSPORT_USER 初始化参数。

REDO_TRANSPORT_USER是在DATAGUARD环境中用于 redo transport 远程密码认证指定数据库用户名, 指定的用户必须有SYSOPER角色,且本地和远程数据库的密码必须相同才能创建Redo transport 会话,并且该参数的值区分大小写,必须与 V$PWFILE_USERS 视图中 USERNAME 列的值完全匹配。默认该参数没有值,当该参数为空时表示使用SYS用户做为验证,也就是过去DataGuard常用的配置(使用“SYS”做为 Log Transport services的用户).

参数在11.1版本时引入,通常很少使用,但是对于使用ORACLE备份一体机(ZDLRA)时,需要配置一个Virtual Private Catalog (VPC)用户,并且REDO_TRANSPORT_USER指定此用户,这会导致其它的日志传输中断改为使用REDO_TRANSPORT_USER用户,对于已有Dataguard环境的数据库,为了避免这个问题需要在Primary创建相同的VPC用户,并且授予create session和SYSOER,SYSDG(12c)。

SQL> create user ravpc1 identified by ratest;
User created.

SQL> grant sysoper,create session to ravpc1;
Grant succeeded.

然后把密码文件从PRIMARY库复制到所有Standby数据库,在主库和备库同时检查密码文件 ,并重置主库的arch dest状态。

SQL> select * from v$pwfile_users;
USERNAME SYSDB SYSOP SYSAS SYSBA SYSDG SYSKM CON_ID
SYS TRUE TRUE FALSE FALSE FALSE FALSE 0
SYSDG FALSE FALSE FALSE FALSE TRUE FALSE 0
SYSBACKUP FALSE FALSE FALSE TRUE FALSE FALSE 0
SYSKM FALSE FALSE FALSE FALSE FALSE TRUE 0
RAVPC1 FALSE TRUE FALSE FALSE FALSE FALSE 0

SQL> alter system set log_archive_dest_state_X=defer scope=both sid='*'
SQL> alter system set log_archive_dest_state_X=enable scope=both sid='*'

这样才可以保证有DataGuard和 ZDLRA的共存。

如果主库更改此密码,因为 12cR2 新的“自动密码传播到Standby”功能,备库会自动同时更新, 使用操作系统命令ls和md5sum可以验证它们具有相同的时间戳,甚至 MD5 校验和也完全相同。


Oracle 19c新特性: Listener自动清理(Network Log File Segmentation)

$
0
0

19c以前的监听日志(listener log)无论是txt还是xml格式的文件都要手动清理,XML的文件是10M一个切换,但是txt格式的(listener.log)是持续增长,导致文件系统full或监听性能问题,多年前整理过一篇自动清理监听日志的Shell: To delete listener log file contains text and xml format (自动清理监听日志) 在我们的生产环境oracle 11g\12c on AIX\HPUX\LINUX都运行多年良好。

也可以使用以下shell 监控日志文件大小:

[oracle@oel7db1 ~]$ for i in `echo "show tracefile %.log"|adrci|grep tns`
> do
>  ls -ltr $ORACLE_BASE/$i|awk -F" " '{print "file: "$9" Size: "$5}'
> done
file: /u01/app/oracle/diag/tnslsnr/oel7db1/listener/trace/listener.log Size: 215450

在 Oracle 19c 上,Oracle 引入了两个有关listener管理的新参数。我们可以在Oracle内配置日志轮换,而无需在OS shell 脚本上进行任何额外配置,实现logrotate功能。该特性叫做“Oracle Network Log File Segmentation”

Oracle Network Log File Segmentation

The maximum size and number of text log files can be configured for Oracle Network components such as Oracle Net Listener, Oracle Connection Manager, and Global Service Manager. This feature allows better management of log files, particularly in Cloud environments.

Use below parameters to define number of files with defined size

LOG_FILE_NUM_listener_name
To specify the number of log file segments. At any point of time there can be only “n” log file segments where “n” is LOG_FILE_NUM_listener_name.
If the log grows beyond this number, then the older segments are deleted.

LOG_FILE_SIZE_listener_name
To specify the size of each log file segment. The size is in MB.

举例说明

 
[oracle@oel7db1 ~]$ cat /u01/app/oracle/product/19.2.0/db_1/network/admin/listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/19.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7db1)(PORT = 1521)(IP=FIRST))
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7db1)(PORT = 1521)(IP=V4_ONLY))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

USE_SID_AS_SERVICE_LISTENER=on

LOG_FILE_NUM_LISTENER=10
LOG_FILE_SIZE_LISTENER=100

[oracle@oel7db1 ~]$ lsnrctl stop
[oracle@oel7db1 ~]$ lsnrctl start

重启生效。

另外还有2个NO-ADR参数

Troubleshooting select ‘hang’/spin on 12C Active DataGuard

$
0
0

今天遇到一套oracle 12c RAC数据库,查询一个分区表的某一个分区,其实就1条记录,段大小也就4M,在primary查询秒出,但是在standby 查询十几分钟不出结果,注意性能问题hang和spin是两个类型,卡住不动是hang,死循环是spin, 通过v$session.seq也可以判断,当然也可以从call stack判断,下面记录一下这个问题。

SQL> select ACCOUNTID FROM "USR1"."TABLE_XX";
-- no feedback

SQL> @ase

USERNAME        SID EVENT                MACHINE    MODULE               STATUS          et SQL_ID          WAI_SECINW ROW_WAIT_OBJ# SQLTEXT                        BS          CH# OSUSER        SEQ# HEX
----------- ------- -------------------- ---------- -------------------- -------- --------- --------------- ---------- ------------- ------------------------------ ---------- ---- ---------- ------- ---------
PUBLIC        10645 Data Guard server op qdyye1     oracle               ACTIVE           0                 0:0                   -1                                :               oracle        3947
PUBLIC        25042 Data Guard server op qdyye2     oracle               ACTIVE           0                 0:0                   -1                                :               oracle       49019
SYS           13777 On CPU / runqueue    anbob1     sqlplus              ACTIVE          63 7jh8bdq9an4fg   -1:63                 -1 select ACCOUNTID FROM "USR1"." :             0 oracle         312   1000001


SQL> @snapper all 10 1 13777
Sampling SID 13777 with interval 10 seconds, taking 1 snapshots...

-- Session Snapper v4.14 BETA - by Tanel Poder ( http://blog.tanelpoder.com ) - Enjoy the Most Advanced Oracle Troubleshooting Script on the Planet! :)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 SID @INST, USERNAME  , TYPE, STATISTIC                                                 ,         DELTA, HDELTA/SEC,    %TIME, GRAPH       , NUM_WAITS,  WAITS/SEC,   AVERAGES
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 13777  @1, SYS       , STAT, session logical reads                                     ,       4877155,    366.35k,         ,             ,          ,           ,       6.5M total buffer visits
 13777  @1, SYS       , STAT, consistent gets                                           ,       4877128,    366.35k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, consistent gets from cache                                ,       4877128,    366.35k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, consistent gets pin                                       ,       3251418,    244.23k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, consistent gets examination                               ,       1625708,    122.12k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, logical read bytes from cache                             ,   39953399808,         3G,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, shared hash latch upgrades - no wait                      ,       1625721,    122.12k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, calls to kcmgcs                                           ,       3251438,    244.24k,         ,             ,          ,           ,          ~ per execution
 13777  @1, SYS       , STAT, buffer is pinned count                                    ,       1624527,    122.03k,         ,             ,          ,           ,      24.99 % buffer gets avoided thanks to buffer pin caching

--  End of Stats snap 1, end=2021-08-10 16:35:32, seconds=13.3


----------------------------------------------------------------------------------------------------
Active% | INST | SQL_ID          | SQL_CHILD | EVENT                               | WAIT_CLASS
----------------------------------------------------------------------------------------------------
   100% |    1 | 7jh8bdq9an4fg   | 0         | ON CPU                              | ON CPU

--  End of ASH snap 1, end=2021-08-10 16:35:32, seconds=10, samples_taken=87

PL/SQL procedure successfully completed.
 
SQL> @seg USR1.TABLE_XX

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
...
         4 USR1                 TABLE_XX                      PART_319                       TABLE PARTITION      DATA319                               512         15     308873
         4 USR1                 TABLE_XX                      PART_335                       TABLE PARTITION      DATA335                               512         16     308873
         4 USR1                 TABLE_XX                      PART_336                       TABLE PARTITION      DATA336                               512        987     317065

执行计划是Full Table SCAN.

SQL> oradebug setorapid 262
Oracle pid: 262, Unix process pid: 244, image: oracle@anbob1 (TNS V1-V3)
SQL> oradebug short_stack;
ksedsts()+592<-ksdxfstk()+64<-ksdxcb()+2000<-sspuser()+640<-<-kcbgtcr()+37169<-kcbgcurstdby()+160<-$cold_kcbgcur()+624<-ktuGetUsegHdr()+2160<-ktuGetExtTxnInfo()+2192<-ktugti()+96<-$cold_ktuxcm()+1072<-ktspgfb_adg()+3936<-$cold_ktspGetNextL1ForScan()+1312<-ktspGenExtentMap1()+672<-kteinmap0()+4880<-kteinmap1()+48<-kteinmap()+48<-kdselini()+128<-kdsirsf()+7200<-kdsirs_fco()+352<-qertbFetch()+7744<-qergiFetch()+1168<-opifch2()+7648<-opifch()+112<-opiodr()+2176<-ttcpip()+1760<-opitsk()+3936<-opiino()+1712<-opiodr()+2176<-opidrv()+1824<-sou2o()+288<-opimai_real()+608<-ssthrdmain()+864<-main()+336<-main_opd_entry()+80 SQL> oradebug short_stack;
ksedsts()+592<-ksdxfstk()+64<-ksdxcb()+2000<-sspuser()+640<-<-kteinscb()<-kcbgtcr()+30624<-ktspgfb_adg()+3392<-$cold_ktspGetNextL1ForScan()+1312<-ktspGenExtentMap1()+672<-kteinmap0()+4880<-kteinmap1()+48<-kteinmap()+48<-kdselini()+128<-kdsirsf()+7200<-kdsirs_fco()+352<-qertbFetch()+7744<-qergiFetch()+1168<-opifch2()+7648<-opifch()+112<-opiodr()+2176<-ttcpip()+1760<-opitsk()+3936<-opiino()+1712<-opiodr()+2176<-opidrv()+1824<-sou2o()+288<-opimai_real()+608<-ssthrdmain()+864<-main()+336<-main_opd_entry()+80 SQL>  oradebug short_stack;
ksedsts()+592<-ksdxfstk()+64<-ksdxcb()+2000<-sspuser()+640<-<-kcbgtcr()+33169<-ktspgfb_adg()+3392<-$cold_ktspGetNextL1ForScan()+1312<-ktspGenExtentMap1()+672<-kteinmap0()+4880<-kteinmap1()+48<-kteinmap()+48<-kdselini()+128<-kdsirsf()+7200<-kdsirs_fco()+352<-qertbFetch()+7744<-qergiFetch()+1168<-opifch2()+7648<-opifch()+112<-opiodr()+2176<-ttcpip()+1760<-opitsk()+3936<-opiino()+1712<-opiodr()+2176<-opidrv()+1824<-sou2o()+288<-opimai_real()+608<-ssthrdmain()+864<-main()+336<-main_opd_entry()+80 SQL>  oradebug short_stack;
ksedsts()+592<-ksdxfstk()+64<-ksdxcb()+2000<-sspuser()+640<-<-kcscu8()<-$cold_kcbgtcr()+60160<-ktspgfb_adg()+2272<-$cold_ktspGetNextL1ForScan()+1312<-ktspGenExtentMap1()+672<-kteinmap0()+4880<-kteinmap1()+48<-kteinmap()+48<-kdselini()+128<-kdsirsf()+7200<-kdsirs_fco()+352<-qertbFetch()+7744<-qergiFetch()+1168<-opifch2()+7648<-opifch()+112<-opiodr()+2176<-ttcpip()+1760<-opitsk()+3936<-opiino()+1712<-opiodr()+2176<-opidrv()+1824<-sou2o()+288<-opimai_real()+608<-ssthrdmain()+864<-main()+336<-main_opd_entry()+80 SQL>  oradebug short_stack;
ksedsts()+592<-ksdxfstk()+64<-ksdxcb()+2000<-sspuser()+640<-<-$cold_kcbgcur()+624<-ktuGetUsegHdr()+2160<-ktuGetExtTxnInfo()+2192<-ktugti()+96<-$cold_ktuxcm()+1072<-ktspgfb_adg()+3936<-$cold_ktspGetNextL1ForScan()+1312<-ktspGenExtentMap1()+672<-kteinmap0()+4880<-kteinmap1()+48<-kteinmap()+48<-kdselini()+128<-kdsirsf()+7200<-kdsirs_fco()+352<-qertbFetch()+7744<-qergiFetch()+1168<-opifch2()+7648<-opifch()+112<-opiodr()+2176<-ttcpip()+1760<-opitsk()+3936<-opiino()+1712<-opiodr()+2176<-opidrv()+1824<-sou2o()+288<-opimai_real()+608<-ssthrdmain()+864<-main()+336<-main_opd_entry()+80 SQL> 

Parsed short stack:
                                                    (?) 
kteinscb()                                         kernel transaction extent management information operations  [partial hit for: ktein ] 
kcbgtcr()+30624                                    kernel cache buffers get consistent read 
ktspgfb_adg()+3392<ktspGetNextL1ForScan()+1312     kernel transaction segment management segment pagetable  [partial hit for: ktsp ] 
ktspGenExtentMap1()+672                            kernel transaction segment management segment pagetable  [partial hit for: ktsp ] 
kteinmap0()+4880                                   kernel transaction extent management information operations return extent map  [partial hit for: kteinmap ] 
kteinmap1()+48                                     kernel transaction extent management information operations return extent map  [partial hit for: kteinmap ] 
kteinmap()+48                                      kernel transaction extent management information operations return extent map 
kdselini()+128                                     kernel data seek/scan extent list initialize 
kdsirsf()+7200                                     kernel data seek/scan  [partial hit for: kds ] 
kdsirs_fco()+352                                   kernel data seek/scan  [partial hit for: kds ] 
qertbFetch()+7744                                  query execute rowsource table access fetch 


 select region FROM "USR1"."TABLE_XX" partition(part_336);

    REGION
----------
       336
SQL> @x
Display execution plan for last statement for this session from library cache...

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  5yuc1gy6u09vf, child number 0
-------------------------------------
 select region FROM "USR1"."TABLE_XX" partition(part_336)

Plan hash value: 798915741

------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name                  | E-Rows |E-Bytes| Cost (%CPU)| Pstart| Pstop |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                       |        |       |     1 (100)|       |       |
|   1 |  PARTITION RANGE SINGLE|                       |      1 |     4 |     1   (0)|    12 |    12 |
|   2 |   INDEX FULL SCAN      | IDX_UNI_TABLE_XX_OID |      1 |     4 |     1   (0)|    12 |    12 |
------------------------------------------------------------------------------------------------------

Note:
使用索引扫描可以很快出结果,但是使用表扫描一直处于spin,  表段很小4m, 但是查询每秒有366k的consistent gets ,从call stack看似乎一直在读取segmeng L1获取extent Map,在MOS中去查询比较匹配Bug 30325407

原因:

spin是由 L1BMB 块的意外状态引起的。要清除此状态,使用dbms_space.space_usage指定段分区即可,通常这个package也用于查看段碎片。

SQL: 如何让一个查询SQL持续多少秒

$
0
0

像TanelPoder的snapper 工具一样,有时比如需要让一个SQL执行多少秒,当然不是为了应用代码里故意给后期应用优化留下点“小惊喜”,目前能想到的几种方式

1, snapper中使用的

define   snapper_sleep=10;
define   snapper_count=1;

declare
ash_date1 date:= sysdate; 
begin
if 1=1 then 
    while sysdate < (ash_date1 + (&snapper_sleep/86400)) loop
	     null;
        dbms_lock.sleep( greatest(0.1,(least(1,&snapper_sleep*&snapper_count/100))) );
    end loop;
else
    dbms_lock.sleep( ((ash_date1+(&snapper_sleep/86400)) - sysdate)*86400 ); 
    null;
end if;
end;

PL/SQL procedure successfully completed.

Elapsed: 00:00:09.15


2, sys.standard.current_timestamp

select count(*) from dual connect by sys.standard.current_timestamp - current_timestamp <= interval'3' second; COUNT(*) ---------- 812372 Elapsed: 00:00:03.05 SQL> select count(*) from dual connect by sys.standard.current_timestamp - curre                                                                              nt_timestamp <= interval'10'second;
select count(*) from dual connect by sys.standard.current_timestamp - current_ti                                                                              mestamp <= interval'10'second * ERROR at line 1: ORA-30009: Not enough memory for CONNECT BY operation Elapsed: 00:00:05.98 SQL> ho oerr ora 30009
30009, 0000, "Not enough memory for %s operation"
// *Cause: The memory size was not sufficient to process all the levels of the
//         hierarchy specified by the query.
// *Action: In WORKAREA_SIZE_POLICY=AUTO mode, set PGA_AGGREGATE_TARGET to
//          a reasonably larger value.
//          Or, in WORKAREA_SIZE_POLICY=MANUAL mode, set SORT_AREA_SIZE to a
//          reasonably larger value.

3, with function

SQL> var n number;
SQL> exec :n:=5;

PL/SQL procedure successfully completed.

SQL> print n

         N
----------
         5

SQL> with function sleep (ps number)return number 
is
begin 
dbms_lock.sleep(ps);
return ps;
end;
select sleep(:n)d from dual;

         D
----------
         5

Elapsed: 00:00:05.47

如何在Oracle 数据库内格式化SQL 或PL/SQL ?

$
0
0

有时在输理复杂的SQL或pl/sql代码逻辑时最好是格式化一下文本,当然我们有toad或plsql developer等其它第三方客户端程序,如果能在数据库内容可以格式化一下SQL更佳,当前数据库12C以后的的软件安装介质中已经包含了Oracle SqlCLOracle SQL Developer, 使用这两个自带的任一工具中的java lib的   dbtools-common.jar 中的 oracle.dbtools.app.Format 函数就可以实现。

下面是实际安装步骤,环境19.3

1, 加载java

19.3中自带的发现无法使用

[oracle@oel7db1 lib]$ loadjava -u anbob/anbob@cdb1pdb1 /u01/app/oracle/product/19.2.0/db_1/sqldeveloper/sqldeveloper/lib/dbtools-common.jar
[oracle@oel7db1 lib]$ sqlplus anbob/anbob@cdb1pdb1
创建3#的java函数时会提示下面的错误

Warning: Java created with compilation errors.

SSQL> show error
Errors for JAVA SOURCE "SQLFORMATTER":

LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0      Note: SQLFORMATTER uses or overrides a deprecated API.
0/0      ORA-29534: referenced object ANBOB.oracle/dbtools/app/Format
         could not be resolved

0/0      Note: Recompile with -Xlint:deprecation for details.


下载新版的SQLCL https://www.oracle.com/tools/downloads/sqlcl-downloads.html 使用目录里的dbtools-common.jar 可以解决。
我这里把sqlcl放到了$ORACLE_HOME下

loadjava -u anbob/anbob@cdb1pdb1 /u01/app/oracle/product/19.2.0/db_1/sqlcl/lib/dbtools-common.jar

2, JAVA授权

SQL> exec dbms_java.grant_permission( 'ANBOB', 'SYS:java.lang.RuntimePermission', 'oracle.DbmsJavaScriptUser', '' );

SQL> exec dbms_java.grant_permission( 'ANBOB', 'SYS:java.lang.RuntimePermission', 'accessClassInPackage.jdk.nashorn.internal.runtime', '' );

SQL> exec dbms_java.grant_permission( 'ANBOB', 'SYS:java.lang.reflect.ReflectPermission', 'suppressAccessChecks', '' );

SQL>exec dbms_java.grant_permission( 'ANBOB', 'SYS:java.util.PropertyPermission', 'polyglot.js.nashorn-compat', 'write' ) 

注意,如果不授权SYS:java.util.PropertyPermission 在后面执行时会提示无权限。

3, 创建JAVA函数

CREATE or replace AND COMPILE JAVA SOURCE NAMED SQLFormatter AS
/* Imports */
import oracle.dbtools.app.Format;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import oracle.sql.BLOB;
import oracle.sql.CLOB;
import java.io.StringWriter;
import java.io.PrintWriter;


public class SQLFormatter {

    private static String getStackTrace(Exception e) {
       StringWriter writer = new StringWriter();
       PrintWriter printWriter = new PrintWriter( writer );
       e.printStackTrace( printWriter );
       printWriter.flush();

       return writer.toString();
    }

    public static Format getFormat() {
        oracle.dbtools.app.Format format = new oracle.dbtools.app.Format();
        
        format.options.put("singleLineComments", Format.InlineComments.CommentsUnchanged);
        format.options.put("kwCase", Format.Case.UPPER);
        format.options.put("idCase", Format.Case.NoCaseChange);                             // default: Format.Case.lower
        format.options.put("adjustCaseOnly", false);                                        // default: false (set true to skip formatting)
        format.options.put("formatThreshold", 1);                                           // default: 1 (disables deprecated post-processing logic)
        // Alignment
        format.options.put("alignTabColAliases", false);                                    // default: true
        format.options.put("alignTypeDecl", true);
        format.options.put("alignNamedArgs", true);
        format.options.put("alignEquality", false);
        format.options.put("alignAssignments", true);                                       // default: false
        format.options.put("alignRight", false);                                            // default: false
        // Indentation
        format.options.put("identSpaces", 3);                                               // default: 4
        format.options.put("useTab", false);
        // Line Breaks
        format.options.put("breaksComma", Format.Breaks.Before);                            // default: Format.Breaks.After
        format.options.put("breaksProcArgs", false);
        format.options.put("breaksConcat", Format.Breaks.Before);
        format.options.put("breaksAroundLogicalConjunctions", Format.Breaks.Before);
        format.options.put("breaksAfterSelect", true);                                      // default: true
        format.options.put("commasPerLine", 1);                                             // default: 5
        format.options.put("breakOnSubqueries", true);
        format.options.put("breakAnsiiJoin", true);                                         // default: false
        format.options.put("breakParenCondition", true);                                    // default: false
        format.options.put("maxCharLineSize", 120);                                         // default: 128
        format.options.put("forceLinebreaksBeforeComment", false);                          // default: false
        format.options.put("extraLinesAfterSignificantStatements", Format.BreaksX2.Keep);   // default: Format.BreaksX2.X2
        format.options.put("flowControl", Format.FlowControl.IndentedActions);
        // White Space
        format.options.put("spaceAroundOperators", true);
        format.options.put("spaceAfterCommas", true);
        format.options.put("spaceAroundBrackets", Format.Space.Default);
        //format.options.put("formatProgramURL", "default");
        
        return format;
    }
    
  public static String format(String str) 
  {
    String res;
    try {
       //res = new Format().format(str);
       Format f = SQLFormatter.getFormat();
       res = f.format(str);
       }
    catch (Exception e){
       res = "Error: " + e.getMessage() + " [ " + SQLFormatter.getStackTrace(e) + " ]";
    }
    return res;
  }

  public static CLOB formatClob(oracle.sql.CLOB clob) 
  throws SQLException
  {
    String str = clob.getSubString(1, (int) clob.length());
    String res = SQLFormatter.format(str);
    Connection conn = DriverManager.getConnection("jdbc:default:connection:");
    CLOB resClob = CLOB.createTemporary(conn, false, BLOB.DURATION_SESSION);
    resClob.setString(1L, res);
    
    return resClob;
  }
}
/

注: 也可以从https://github.com/xtender/xt_scripts/blob/master/extra/SQLFormatte 下载最新版

4, 创建PL/SQL PACKAGE

create or replace package SQLFormatter as

  FUNCTION Format(str in varchar2) RETURN VARCHAR2
  AS LANGUAGE JAVA NAME 'SQLFormatter.format(java.lang.String) return java.lang.String';

  FUNCTION FormatClob(str in clob) RETURN CLOB
  AS LANGUAGE JAVA NAME 'SQLFormatter.formatClob(oracle.sql.CLOB) return oracle.sql.CLOB';
  
end;
/

 

5, 测试

SQL> select anbob.SQLFormatter.formatclob(to_clob('select 1 a from dual')) qtext from dual;

QTEXT
---------------------------------------------------------------------------------------
SELECT
   1 a
FROM
   dual


SQL> select anbob.SQLFormatter.format('select 1 a,2 /*123 */ b,3 c, d from dual, dual d2') qtext from dual;

QTEXT
----------------------------------------------------------------------------------------
SELECT
   1 a
 , 2 /*123 */ b
 , 3 c
 , d
FROM
   dual
 , dual d2

— enjob —

Oracle Audit write syslog(数据库审计写系统日志)

$
0
0

之前分享过如何把GoldenGate写入syslog的笔记 Oracle goldengate write syslog(ogg 写系统日志),今天有同事问如何把audit 日志记录syslog, 简单研究一下,syslog是操作系统级协议,oracle数据库没有直接把如alert,listener、audit log写入syslog的机制,但是可以通过DB或OS层的配置把audit日志写入, audit sys的日志默认是记录在audit_file_dest路径下的,当然DBA有权可以查看编辑。有时安全审计等要求希望在root用户可以保留一份防止DBA(e.g. oracle user)编辑,可能配置把audit日志写入syslog,如linux的messages.

从12c开始引入了新的Unified Auditing(统一审计), 开始支持2种审计模式:混合审计和纯统一审计, 混合模式是为了过渡到UA(统一审计),如要像之前的版本一样,只有混合模式时需要配置audit_trail参数,升级到纯UA后,原来的audit trail记录仍旧可以使用,你也可以归档或清除之前trail,清除audit trail 使用DBMS_AUDIT_MGMT。

  • 12c When using unified auditing, the audit records will be written to the unified audit trail and cannot be redirected to syslog. If you would like to redirect the audit records to syslog,then use Mixed Mode auditing.
  • Starting with 18c, you can write the unified audit trail records to SYSLOG or the Windows Event Viewer by setting the UNIFIED_AUDIT_SYSTEMLOG initialization parameter. (Doc ID 2623138.1)
  • unified audit entries to SYSLOG will not include imported columns due to SYSLOG size limit (Doc ID 2520613.1)

可见使用unified audit 从18c通过配置UNIFIED_AUDIT_SYSTEMLOG可以输出到syslog,但是一样会缺少一些重要信息,否则就还使用Mixed mode(混合)模式的审计。

下面是使用测试oracle 21c 混合模式记录audit到syslog.

SQL> select banner_full from v$version;

BANNER_FULL
------------------------------------------------------------------------------------
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0


SQL> alter system set audit_trail='OS' scope=spfile;
System altered.

SQL> alter system set audit_syslog_level = 'user.notice' scope=spfile;
System altered.

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

## OEL 7.8

[root@oel7db1 log]# service rsyslog stop

[root@oel7db1 log]# service rsyslog start

[root@oel7db1 log]# service rsyslog status
Redirecting to /bin/systemctl status rsyslog.service
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2021-08-26 22:51:34 EDT; 13min ago
     Docs: man:rsyslogd(8)
           http://www.rsyslog.com/doc/
 Main PID: 5851 (rsyslogd)
   CGroup: /system.slice/rsyslog.service
           └─5851 /usr/sbin/rsyslogd -n

Aug 26 22:51:34 oel7db1 systemd[1]: Starting System Logging Service...
Aug 26 22:51:34 oel7db1 rsyslogd[5851]:  [origin software="rsyslogd" swVersion="8.24.0-38.el7" x-pid="5851" x-info="http://www.rsyslog.com"] start
Aug 26 22:51:34 oel7db1 systemd[1]: Started System Logging Service.

测试sys和system

SQL> startup
ORACLE instance started.

Total System Global Area 1543503024 bytes
Fixed Size                  9686192 bytes
Variable Size             956301312 bytes
Database Buffers          570425344 bytes
Redo Buffers                7090176 bytes
Database mounted.
Database opened.

SQL> show parameter audit

PARAMETER_NAME                                               TYPE        VALUE
------------------------------------------------------------ ----------- ----------------------------------------------------------------------------------------------------
audit_file_dest                                              string      /u01/app/oracle/admin/orcl/adump
audit_sys_operations                                         boolean     TRUE
audit_syslog_level                                           string      USER.NOTICE
audit_trail                                                  string      OS
unified_audit_common_systemlog                               string
unified_audit_systemlog                                      string


SQL> create user c##a identified by a;
User created.

SQL> drop user c##a;
User dropped.

SQL> conn system/oracle
Connected.

USERNAME             INST_NAME            HOST_NAME                  I# SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- --- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
SYSTEM               CDB$ROOT-anbob21c    oel7db1                     1 1     55561    21.0.0.0.0 20210826 9757       43    9391            0000000073741858 00000000735910E0


SQL> create user c##a identified by a;
User created.

SQL> drop user c##a;
User dropped.

# tail -f /var/log/messages

Aug 26 23:36:25 oel7db1 journal: Oracle Audit[9658]: LENGTH : '281' ACTION :[32] 'create user c##a identified by *' DATABASE USER:[1] '/' PRIVILEGE :[6] 'SYSDBA' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/1' STATUS:[1] '0' DBID:[10] '1608557415' SESSIONID:[10] '4294967295' USERHOST:[7] 'oel7db1' CLIENT ADDRESS:[0] '' ACTION NUMBER:[2] '51'
Aug 26 23:36:29 oel7db1 journal: Oracle Audit[9658]: LENGTH : '311' ACTION :[60] 'BEGIN dbms_cmp_int.drop_cmp_by_cmpid(:sb1, :sb2, :sb3); END;' DATABASE USER:[3] 'SYS' PRIVILEGE :[6] 'SYSDBA' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/1' STATUS:[1] '0' DBID:[10] '1608557415' SESSIONID:[10] '4294967295' USERHOST:[7] 'oel7db1' CLIENT ADDRESS:[0] '' ACTION NUMBER:[2] '47'
Aug 26 23:36:29 oel7db1 journal: Oracle Audit[9658]: LENGTH : '263' ACTION :[14] 'drop user c##a' DATABASE USER:[1] '/' PRIVILEGE :[6] 'SYSDBA' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/1' STATUS:[1] '0' DBID:[10] '1608557415' SESSIONID:[10] '4294967295' USERHOST:[7] 'oel7db1' CLIENT ADDRESS:[0] '' ACTION NUMBER:[2] '53'
Aug 26 23:37:26 oel7db1 journal: Oracle Audit[9757]: LENGTH : '307' ACTION :[60] 'BEGIN dbms_cmp_int.drop_cmp_by_cmpid(:sb1, :sb2, :sb3); END;' DATABASE USER:[6] 'SYSTEM' PRIVILEGE :[4] 'NONE' CLIENT USER:[6] 'oracle' CLIENT TERMINAL:[5] 'pts/1' STATUS:[1] '0' DBID:[10] '1608557415' SESSIONID:[6] '170029' USERHOST:[7] 'oel7db1' CLIENT ADDRESS:[0] '' ACTION NUMBER:[2] '47'

记录了sys的创建、删除用户的操作,但是sys的查询一样会被审计,这样syslog的阅读性就差不容易解析,这点还是在数据库内部过滤方便。

下面是使用测试oracle 21c Unified Auditing记录audit到syslog.

SQL> select parameter , value from v$option where PARAMETER = 'Unified Auditing';

PARAMETER VALUE
------------------------- -------- ----------------------------------------------------------------
Unified Auditing FALSE

SQL> shut abort
ORACLE instance shut down.
SQL> exit
Disconnected from Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.3.0.0.0

$ cd $ORACLE_HOME/rdbms/lib
$ make -f ins_rdbms.mk uniaud_on ioracle

sqlplus / as sysdba
SQL> startup nomount
ORACLE instance started.

Total System Global Area 1543503024 bytes
Fixed Size 9686192 bytes
Variable Size 973078528 bytes
Database Buffers 553648128 bytes
Redo Buffers 7090176 bytes
SQL> select parameter , value from v$option where PARAMETER = 'Unified Auditing';

PARAMETER                                                        VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
Unified Auditing                                                 TRUE

SQL> alter system reset audit_syslog_level scope=spfile;
System altered.

SQL> alter system set UNIFIED_AUDIT_SYSTEMLOG='user.notice' scope=spfile;
System altered.

SQL> shut immediate
ORA-01507: database not mounted


ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 1543503024 bytes
Fixed Size                  9686192 bytes
Variable Size             973078528 bytes
Database Buffers          553648128 bytes
Redo Buffers                7090176 bytes
Database mounted.
Database opened.


SQL> show parameter audit

PARAMETER_NAME                                               TYPE        VALUE
------------------------------------------------------------ ----------- ----------------------------------------------------------------------------------------------------
audit_file_dest                                              string      /u01/app/oracle/admin/orcl/adump
audit_sys_operations                                         boolean     TRUE
audit_syslog_level                                           string
audit_trail                                                  string      OS
unified_audit_common_systemlog                               string
unified_audit_systemlog                                      string      USER.NOTICE


同样测试增删用户

sqlplus / as sysdba
SQL> create user c##b identified by b;
User created.

SQL> drop user c##b;
User dropped.

SQL> conn system/oracle
Connected.

SQL> create user c##b identified by b;
User created.

SQL> drop user c##b;
User dropped.

tail -f /var/log/messages

Aug 27 03:10:22 oel7db1 journal: Oracle Unified Audit[21418]: LENGTH: '193' TYPE:"4" DBID:"1608557415" SESID:"0" CLIENTID:"" ENTRYID:"5" STMTID:"15" DBUSER:"SYS" CURUSER:"SYS" ACTION:"51" RETCODE:"0" SCHEMA:"" OBJNAME:"C##B" PDB_GUID:"C8209F27C6B16005E053362EE80AE60E"
Aug 27 03:10:23 oel7db1 journal: Oracle Unified Audit[21418]: LENGTH: '193' TYPE:"4" DBID:"1608557415" SESID:"0" CLIENTID:"" ENTRYID:"6" STMTID:"16" DBUSER:"SYS" CURUSER:"SYS" ACTION:"53" RETCODE:"0" SCHEMA:"" OBJNAME:"C##B" PDB_GUID:"C8209F27C6B16005E053362EE80AE60E"
Aug 27 03:11:44 oel7db1 journal: Oracle Unified Audit[21885]: LENGTH: '208' TYPE:"4" DBID:"1608557415" SESID:"1182265899" CLIENTID:"" ENTRYID:"1" STMTID:"11" DBUSER:"SYSTEM" CURUSER:"SYSTEM" ACTION:"51" RETCODE:"0" SCHEMA:"" OBJNAME:"C##B" PDB_GUID:"C8209F27C6B16005E053362EE80AE60E"
Aug 27 03:11:48 oel7db1 journal: Oracle Unified Audit[21885]: LENGTH: '208' TYPE:"4" DBID:"1608557415" SESID:"1182265899" CLIENTID:"" ENTRYID:"2" STMTID:"12" DBUSER:"SYSTEM" CURUSER:"SYSTEM" ACTION:"53" RETCODE:"0" SCHEMA:"" OBJNAME:"C##B" PDB_GUID:"C8209F27C6B16005E053362EE80AE60E"

Note:
可见Unified Audit记录的信息比较少,比如OS_USERNAME, USERHOST, TERMINAL,SYSTEM_PRIVILEGE_USED, SQL_TEXT都是缺失的,Oracle表示这是一种预期形为。
— enjob —

Oracle19c 建议的 One-off patch之disable LAST SUCCESSFUL LOGIN TIME

$
0
0

之前分享过12c后关于用户登录的新特性笔记《Oracle 12c New Feature: Last Login Time for Non-Sys Users》, 此特性对于分别哪些用户长时间未登录(不使用)非常有用,从是从12c开始一直到当前最新的RU19.12 ,都没有在RU中打包关闭该特性的方法。《library cache lock或row cache lock, Failed Logon Delay 因为错误的密码尝试》也有记录登录常见的几个性能问题的event, 前几年在12c就遇到过较高的library cache lock是与该特性有关,用户无法登录,当时的SQL 更新user$, namespace为Last_Successful_Logon_Time,此问题特性只到21C base版本才引入了隐藏参数来禁用。 下面继续我们《Oracle19c避雷系列》的主动规避此特性。

Top Event P1/P2/P3 Values

  • Top Events by DB Time and the top P1/P2/P3 values for those events.
  • % Event is the percentage of DB Time due to the event
  • % Activity is the percentage of DB Time due to the event with the given P1,P2,P3 Values.
Event % Event P1, P2, P3 Values % Activity Parameter 1 Parameter 2 Parameter 3
library cache lock 91.75 “7810470960”,”23613858232″,”8323074 0.68 handle address lock address 100*mode+namespace
enq: TX – row lock contention 8.22 “1415053318”,”4522007″,”24103″ 8.22 name|mode usn<<16 | slot sequence

上图AWR,ASH中的TOP EVENT,也可以写SQL从ASH view中分析

select p3,count(*) from v$active_session_history where event like 'library cache lock%' and ....
 group by p3

SQL> select round(bitand( 8323074,to_number('FF0000','xxxxxxxxx'))/to_number('FFFF','xxxxxxxxx'))  from dual;

ROUND(BITAND(8323074,TO_NUMBER('FF0000','XXXXXXXXX'))/TO_NUMBER('FFFF','XXXXXXXXX'))
------------------------------------------------------------------------------------
                                                                                 127

SQL> select KGLSTDSC from  X$KGLST where indx=127;

KGLSTDSC
----------------------------------------------------------------
Last_Successful_Logon_Time


SQL> @desc dba_users;
           Name                            Null?    Type
           ------------------------------- -------- ----------------------------
    1      USERNAME                        NOT NULL VARCHAR2(128)
    2      USER_ID                         NOT NULL NUMBER
    3      PASSWORD                                 VARCHAR2(4000)
    4      ACCOUNT_STATUS                  NOT NULL VARCHAR2(32)
    5      LOCK_DATE                                DATE
    6      EXPIRY_DATE                              DATE
    7      DEFAULT_TABLESPACE              NOT NULL VARCHAR2(30)
    8      TEMPORARY_TABLESPACE            NOT NULL VARCHAR2(30)
    9      LOCAL_TEMP_TABLESPACE                    VARCHAR2(30)
   10      CREATED                         NOT NULL DATE
   11      PROFILE                         NOT NULL VARCHAR2(128)
   12      INITIAL_RSRC_CONSUMER_GROUP              VARCHAR2(128)
   13      EXTERNAL_NAME                            VARCHAR2(4000)
   14      PASSWORD_VERSIONS                        VARCHAR2(17)
   15      EDITIONS_ENABLED                         VARCHAR2(1)
   16      AUTHENTICATION_TYPE                      VARCHAR2(8)
   17      PROXY_ONLY_CONNECT                       VARCHAR2(1)
   18      COMMON                                   VARCHAR2(3)
   19      LAST_LOGIN                               TIMESTAMP(9) WITH TIME ZONE
   20      ORACLE_MAINTAINED                        VARCHAR2(1)
   21      INHERITED                                VARCHAR2(3)
   22      DEFAULT_COLLATION                        VARCHAR2(100)
   23      IMPLICIT                                 VARCHAR2(3)
   24      ALL_SHARD                                VARCHAR2(3)
   25      PASSWORD_CHANGE_DATE                     DATE

查看该dba_users定义LAST_LOGIN对应
SQL> select from_tz(to_timestamp(to_char(u.spare6, 'DD-MON-YYYY HH24:MI:SS'),
  2  'DD-MON-YYYY HH24:MI:SS'), '0:00')
  3  at time zone sessiontimezone from user$ u;

做SSD trace中可以看到blocking的session current SQL
update user$ set spare6=DECODE(to_char(:2, 'YYYY-MM-DD'), '0000-00-00', to_date(NULL), :2) where user#=:1

解决方法安装One-off Patch 32164034后引入新的隐藏参数_disable_last_successful_login_time ,再配置该参数为true. 禁用该特性,此patch 在12c和19c中当前可以下载,未提供18c patch. 21c base中已经存在。

SQL> @i

USERNAME             INST_NAME            HOST_NAME                  I# SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- --- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
SYS                  CDB$ROOT-anbob21c   oel7db1                     1 1     54741    21.0.0.0.0 20210821 11143      43    11000           0000000077741858 00000000775910E0


SQL> @pd login_time
Show all parameters and session values from x$ksppi/x$ksppcv...

       NUM N_HEX NAME                                                     VALUE                          DESCRIPTION
---------- ----- -------------------------------------------------------- ------------------------------ ---------------------------------------------------------------------------------------------------
       802   322 _disable_last_successful_login_time                      FALSE                          Disable writing Last Successful Login Time to USER$

— enjoy —

Oracle & PostGreSQL 生成 JSON 数据

$
0
0

在WEB应用或图展示的程序中通常使用Json格式传输,JavaScript Object Notation (JSON) 是一种轻量级的数据传输格式,在关系型数据库中通常存储的是表、列格式,如果数据库可以直接返回JSON, 那基于JSON传输的应用将会收益,JSON 是一种完全独立于语言的文本格式,使 JSON 成为理想的数据交换语言。 在PostGreSQL和ORACLE 12.2中都提供了JSON的SQL函数, Oracle Database 21c 中添加了原生 JSON 数据类型,这针对查询和 DML 处理进行了优化。加快处理 JSON 文档的速度。从 21c 开始,这是存储大型 JSON 文档的最佳类型。Oracle Database 19c 引入了一个新选项:使用 JSON_mergepatch 进行 JSON 修补。这仅替换了文档的相关部分,Oracle Database 21c提供了一种更好的方法:JSON_transform。Oracle Database 21c提供了一种更好的方法:JSON_transform,JSON_transform 具有强大的 JSON 操作功能,允许您添加、删除和更改文档中的值,与JSON_mergepatch 不同,您可以针对要更改的特定属性。 下面记录一下PostgreSQL和Oracle返回Json的方法。

PostGreSQL

sdbo=# select version();
                          version
------------------------------------------------------------
 PostgreSQL 13.1, compiled by Visual C++ build 1914, 64-bit
 
sdbo=# \d
                   关联列表
 架构模式 |      名称       |  类型  | 拥有者
----------+-----------------+--------+--------
 public   | sdbo_department | 数据表 | weejar
(1 行记录)


sdbo=# select * from sdbo_department;
 dep_id | dep_name
--------+----------
      1 | mgr
(1 行记录)

sdbo=# insert into sdbo_department values (2,'dev');
INSERT 0 1
sdbo=# select row_to_json(sdbo_department) from sdbo_department;
          row_to_json
-------------------------------
 {"dep_id":1,"dep_name":"mgr"}
 {"dep_id":2,"dep_name":"dev"}
(2 行记录)


sdbo=# alter table sdbo_department add sex char(1);
ALTER TABLE
sdbo=# select row_to_json(sdbo_department) from sdbo_department;
               row_to_json
------------------------------------------
 {"dep_id":1,"dep_name":"mgr","sex":null}
 {"dep_id":2,"dep_name":"dev","sex":null}
(2 行记录)

sdbo=# insert into sdbo_department values (3,'test',1);
INSERT 0 1
sdbo=# select row_to_json(sdbo_department) from sdbo_department;
               row_to_json
------------------------------------------
 {"dep_id":1,"dep_name":"mgr","sex":null}
 {"dep_id":2,"dep_name":"dev","sex":null}
 {"dep_id":3,"dep_name":"test","sex":"1"}
(3 行记录)
 
sdbo=# select row_to_json(row(dep_id,dep_name)) from sdbo_department;
     row_to_json
----------------------
 {"f1":1,"f2":"mgr"}
 {"f1":2,"f2":"dev"}
 {"f1":3,"f2":"test"}
(3 行记录)

sdbo=# select json_build_object('id',dep_id,'name',dep_name) from sdbo_department;
      json_build_object
-----------------------------
 {"id" : 1, "name" : "mgr"}
 {"id" : 2, "name" : "dev"}
 {"id" : 3, "name" : "test"}
(3 行记录)

sdbo=# insert into sdbo_department values (3,'test2',1);
INSERT 0 1
sdbo=# select * from sdbo_department;
 dep_id | dep_name | sex
--------+----------+-----
      1 | mgr      |
      2 | dev      |
      3 | test     | 1
      3 | test2    | 1
(4 行记录)

sdbo=# select json_agg(sdbo_department) from sdbo_department group by dep_id;
                  json_agg
---------------------------------------------
 [{"dep_id":3,"dep_name":"test","sex":"1"}, +
  {"dep_id":3,"dep_name":"test2","sex":"1"}]
 [{"dep_id":2,"dep_name":"dev","sex":null}]
 [{"dep_id":1,"dep_name":"mgr","sex":null}]
(3 行记录)

sdbo=# select json_agg(dep_name) from sdbo_department group by dep_id;
     json_agg
-------------------
 ["test", "test2"]
 ["dev"]
 ["mgr"]
(3 行记录)

sdbo=# select dep_id,json_agg(dep_name) from sdbo_department group by dep_id;
 dep_id |     json_agg
--------+-------------------
      3 | ["test", "test2"]
      2 | ["dev"]
      1 | ["mgr"]
(3 行记录)
ORACLE
SQL> @cc pdb1
ALTER SESSION SET container = pdb1;

Session altered.


USERNAME             INST_NAME            HOST_NAME                  I# SID   SERIAL#  VERSION    STARTED  SPID       OPID  CPID            SADDR            PADDR
-------------------- -------------------- ------------------------- --- ----- -------- ---------- -------- ---------- ----- --------------- ---------------- ----------------
SYS                  PDB1-anbob19c        oel7db1                     1 1     17152    19.0.0.0.0 20210922 2031       33    1938            0000000078881028 00000000794F7F48


SQL> create table anbob.emp(emp_id int,emp_name varchar2(100));
Table created.

SQL> insert into anbob.emp values (1,'a');
1 row created.

SQL> insert into anbob.emp values (2,'b');
1 row created.

SQL> insert into anbob.emp values (3,'c');
1 row created.


SQL> select json_object(*) from anbob.emp;
JSON_OBJECT(*)
-------------------------------- 
{"EMP_ID":1,"EMP_NAME":"a"}
{"EMP_ID":2,"EMP_NAME":"b"}
{"EMP_ID":3,"EMP_NAME":"c"}

 
SQL> alter table anbob.emp add sex char(1);
Table altered.

SQL> insert into anbob.emp values (3,'d',1);
1 row creted.

SQL> select * from anbob.emp;
    EMP_ID EMP_NAME             S
---------- -------------------- -
         1 a
         2 b
         3 c
         3 d                    1

SQL> select json_object(*) j from anbob.emp;
J
---------------------------------------- 
{"EMP_ID":1,"EMP_NAME":"a","SEX":null}
{"EMP_ID":2,"EMP_NAME":"b","SEX":null}
{"EMP_ID":3,"EMP_NAME":"c","SEX":null}
{"EMP_ID":3,"EMP_NAME":"d","SEX":"1"}

SQL> select json_object(key 'eno' value emp_id, key 'ename' value emp_name) from anbob.emp;
JSON_OBJECT(KEY'ENO'VALUEEMP_ID,KEY'ENAME'VALUEEMP_NAME)
---------------------------------------------------- 
{"eno":1,"ename":"a"}
{"eno":2,"ename":"b"}
{"eno":3,"ename":"c"}
{"eno":3,"ename":"d"}

SQL> select json_array(emp_id,emp_name) from anbob.emp;
JSON_ARRAY(EMP_ID,EMP_NAME)
------------------------------------------ 
[1,"a"]
[2,"b"]
[3,"c"]
[3,"d"]


SQL> select json_arrayagg(emp_name) from anbob.emp;
JSON_ARRAYAGG(EMP_NAME)
------------------------------------- 
["a","b","c","d"]

SQL> select json_arrayagg(json_object(key 'eno' value emp_id, key 'ename' value emp_name)) from anbob.emp;
JSON_ARRAYAGG(JSON_OBJECT(KEY'ENO'VALUEEMP_ID,KEY'ENAME'VALUEEMP_NAME))
--------------------------------------------------------------------------------------------- 
[{"eno":1,"ename":"a"},{"eno":2,"ename":"b"},{"eno":3,"ename":"c"},{"eno":3,"ename":"d"}]


SQL>
select json_object(
'eno' value emp_id,
'enames' value json_arrayagg(e.emp_name),
'cnt' value (select count(*) from anbob.emp e1 where e1.emp_id=e.emp_id)
)
from anbob.emp e
join anbob.dept d on e.emp_id=d.id
group by e.emp_id;

JSON_OBJECT('ENO'VALUEEMP_ID,'ENAMES'VALUEJSON_ARRAYAGG(E.EMP_NAME),'CNT'VALUE(SELECTCOUNT(*)FROMANBOB.EMPE1WHEREE1.EMP_ID=E.EMP_ID))
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
{"eno":1,"enames":["a"],"cnt":1}
{"eno":3,"enames":["c","d"],"cnt":2}



Oracle、MySQL、PostGreSQL、SQL Server数据库比较系列(一):null value

$
0
0

最近几年数据库市场百花齐放,在做跨数据库迁移的数据库选型时,除了性能、稳定、安全、运维、功能、可扩展外,像开发中对于值的处理往往容易被人忽视, 之前写过一篇关于PG区别Oracle在SQL解析缓存的笔记《PostgreSQL 12 : Prepare statement和plan_cache_mode 参数》,这里记录一下null 值在这几个数据库中的区别。

软件版本:Oracle 21c 、SQL Server 2019 、MySQL 8.0 、Mariadb 10.6 、PostGreSQL 13、OpenGauss 2.0

创建测试用例表

CREATE TABLE tab_null(id int, name char(10));
 
INSERT INTO tab_null VALUES(1,'anbob');
INSERT INTO tab_null VALUES(2,NULL);

测试 数据过滤

# oracle
SQL> select * from tab_null where name is null;
        ID NAME
---------- ----------
         2

SQL> select * from tab_null where name is not null;
        ID NAME
---------- ----------
         1 anbob

SQL> select * from tab_null where name=null;
no rows selected

SQL> select * from tab_null where null=null;
no rows selected

# postgresql
postgres=# select * from tab_null where name is null;
 id | name
----+------
  2 |
(1 row)

postgres=# select * from tab_null where name is not null;
 id |    name
----+------------
  1 | anbob
(1 row)

postgres=# select * from tab_null where name=null;
 id | name
----+------
(0 rows)

postgres=# select * from tab_null where null=null;
 id | name
----+------
(0 rows)

# MySQL/MariaDB
mysql> select * from tab_null where name is null;
+------+------+
| id   | name |
+------+------+
|    2 | NULL |
+------+------+
1 row in set (0.00 sec)

mysql> select * from tab_null where name is not null;
+------+-------+
| id   | name  |
+------+-------+
|    1 | anbob |
+------+-------+
1 row in set (0.00 sec)

mysql> select * from tab_null where name=null;
Empty set (0.00 sec)

mysql> select * from tab_null where null=null;
Empty set (0.00 sec)

# SQL Server

select * from tab_null where name is null;
        ID NAME
---------- ----------
         2

select * from tab_null where name is not null;
        ID NAME
---------- ----------
         1 anbob

select * from tab_null where name=null;
no rows selected

select * from tab_null where null=null;
no rows selected


Note:
可见所有数据库的结果是一样的。

另一种另类

# Mysql
mysql> select 1 from tab_null where 1 not in (null);
Empty set (0.00 sec)

mysql> select 1 from tab_null where null not in (null);
Empty set (0.00 sec)

mysql> select 1 from tab_null where null  in (null);
Empty set (0.00 sec)

mysql> select 1 from tab_null where exists(select null from dual);
+---+
| 1 |
+---+
| 1 |
| 1 |
| 1 |
+---+
3 rows in set (0.05 sec)

Note:
这类在4个库返回也是一样的,上面只附了MySQL,不再展示其它库。

唯一约束

# oracle
SQL> alter table tab_null add constraint c_tab_null_name_uni  unique(name);
Table altered.

SQL> INSERT INTO tab_null VALUES(3,NULL);
1 row created.

SQL> select * from tab_null;
        ID NAME
---------- ----------
         1 anbob
         2
         3
# postgresql
postgres=# alter table tab_null add constraint c_tab_null_name_uni  unique(name);
ALTER TABLE
postgres=# INSERT INTO tab_null VALUES(3,NULL);
INSERT 0 1
postgres=# select * from tab_null;
 id |    name
----+------------
  1 | anbob
  2 |
  3 |
(3 rows)

# MySQL/MariaDB
mysql> alter table tab_null add constraint c_tab_null_name_uni  unique(name);
Query OK, 0 rows affected (0.14 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> INSERT INTO tab_null VALUES(3,NULL);
Query OK, 1 row affected (0.01 sec)

mysql> select * from tab_null;
+------+-------+
| id   | name  |
+------+-------+
|    1 | anbob |
|    2 | NULL  |
|    3 | NULL  |
+------+-------+
3 rows in set (0.00 sec)

# SQL SERVER
alter table tab_null add constraint c_tab_null_name_uni  unique(name);

INSERT INTO tab_null VALUES(3,NULL);
Msg 2627 Level 14 State 1 Line 12
Violation of UNIQUE KEY constraint 'c_tab_null_name_uni'. 
Cannot insert duplicate key in object 'dbo.tab_null'. The duplicate key value is (<NULL>).

Note:
这里只有SQL SERVER提示一个表中的null和null是重复记录, 其它库可以正常insert 多个 null 到有唯一约束的表。

 

NULL使用索引

# MySQL/MariaDB
mysql> alter table tab_null drop constraint c_tab_null_name_uni;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create index idx_tab_null_name on tab_null(name);
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from tab_null where name is null;
+----+-------------+----------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table    | partitions | type | possible_keys     | key               | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+----------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | tab_null | NULL       | ref  | idx_tab_null_name | idx_tab_null_name | 41      | const |    2 |   100.00 | Using index condition |
+----+-------------+----------+------------+------+-------------------+-------------------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

# PostgreSQL
postgres=# alter table tab_null drop constraint c_tab_null_name_uni;
ALTER TABLE
postgres=# create index idx_tab_null_name on tab_null(name);
CREATE INDEX
postgres=# explain analyze select * from tab_null where name is null;
                                            QUERY PLAN
---------------------------------------------------------------------------------------------------
 Seq Scan on tab_null  (cost=0.00..1.03 rows=1 width=18) (actual time=0.008..0.009 rows=2 loops=1)
   Filter: (name IS NULL)
   Rows Removed by Filter: 1
 Planning Time: 0.130 ms
 Execution Time: 0.019 ms
-- 因为小表代价,这是使用了seq scan 全表扫,下面往表里insert一些数据

postgres=# insert into tab_null select generate_series,generate_series||'anbob' from generate_series(101,10000);
INSERT 0 9900
postgres=# analyze tab_null;
ANALYZE
postgres=# explain analyze select * from tab_null where name is null;
                                                         QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_tab_null_name on tab_null  (cost=0.29..9.64 rows=2 width=15) (actual time=0.010..0.011 rows=2 loops=1)
   Index Cond: (name IS NULL)
 Planning Time: 0.199 ms
 Execution Time: 0.031 ms
(4 rows)

# Oracle
SQL>alter table tab_null drop constraint c_tab_null_name_uni;
Table altered.

SQL> create index idx_tab_null_name on tab_null(name);
Index created.

SQL> explain plan for select /*+index(t)*/ * from tab_null t where name is null;

Explained.

SQL> @x2

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------
Plan hash value: 2647411751

------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |     2 |    50 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TAB_NULL |     2 |    50 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("NAME" IS NULL)

Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1 (U - Unused (1))
---------------------------------------------------------------------------

   1 -  SEL$1 / "T"@"SEL$1"
         U -  index(t)

解决这个问题可以增加常数的复合索引

SQL> create index idx_tab_null_name_0 on tab_null(name,0);
Index created.

SQL> explain plan for select /*+index(t)*/ * from tab_null t where name is null;
Explained.

SQL> @x2
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Plan hash value: 2247804559

-----------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                     |     2 |    50 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TAB_NULL            |     2 |    50 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IDX_TAB_NULL_NAME_0 |     1 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("NAME" IS NULL)

# SQL SERVER
SET statistics profile on;
SELECT * FROM tab_null with (index(idx_tab_null_name)) Where name IS NULL;
Rows Executes StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
1 1 SELECT * FROM tab_null with (index(idx_tab_null_name)) Where name IS NULL 1 1 0 1 0.00657038 SELECT False
1 1 |–Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000])) 1 2 1 Nested Loops Inner Join OUTER REFERENCES:([Bmk1000]) 1 0 4.18E-06 21 0.00657038 [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[id], [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[name] PLAN_ROW False 1
1 1 |--Index Seek(OBJECT:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[idx_tab_null_name]), SEEK:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[name]=NULL) ORDERED FORWARD) 1 3 2 Index Seek Index Seek OBJECT:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[idx_tab_null_name]), SEEK:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[name]=NULL) ORDERED FORWARD, FORCEDINDEX [Bmk1000], [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[name] 1 0.003125 0.0001581 25 0.0032831 [Bmk1000], [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[name] PLAN_ROW False 1
1 1 |–RID Lookup(OBJECT:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD) 1 5 2 RID Lookup RID Lookup OBJECT:([fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[id] 1 0.003125 0.0001581 11 0.0032831 [fiddle_83bb216b11bf448d8dd49445932f20ee].[dbo].[tab_null].[id] PLAN_ROW False 1

Note:
对于is null的谓词条件注意MySQL、MariaDB即使很少的记录也使用的index感觉更像是RULE CBO;PostgreSQL开始使用了全表扫,也可能是基于代价的估算,全表扫要优于使用索引,因为pg默认没有像oracle,sql server, mysql 自带的hint可以强制使用索引,后来我们填充了更多的数据,PostgreSQL也使用上了索引,当然PG 也有扩展pg_hint_plan可以实现,不过PG认为用户中使用hint干扰优化器是不好的习惯,不应该那么做;Oracle数据库因为单列索引不会储存null值,所以is null 即使使用hint 也无法使用索引,需要优化小技巧,增加常量的复合索引使用索引; SQL Server同样我们在加hint with (index(idx_tab_null_name))后,执行计划中的Index Seek 也可以确认用上了索引。

字符串拼接

# sql server 2019
select null+'anbob'

-------------
null

# mariadb 10.6
select null+'anbob'

-------------
null

# mysql 8.0
select null+'anbob'

-------------
null

# postgres 13
postgres=# select 'anbob'||null;
 ?column?
----------

(1 row)

# oracle 21c
SQL> select null||'anbob' from dual;

NULL|
-----
anbob

# OpenGauss
[og@oel7db1 data]$ gsql -d anbob -p 15432
gsql ((openGauss 2.0.0 build 78689da9) compiled at 2021-03-31 21:04:03 commit 0 last mr  )
NOTICE : The password has been expired, please change the password.
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type "help" for help.
                                  ^
anbob=# select null||'anbob' ;
 ?column?
----------
 anbob
(1 row)


Note:
注意也是只有Oracle不同于其它库,在null值和其它字符串拼接后可以正常返回部分有效值,而其它所有库全部返回空。

总结:

对于null值的谓词过滤条件时(IS NULL、IS NOT NULL, >,< ,=),4个数据库返回数据记录是一样的;

对于null 值的唯一约束,只有SQL Server不允许null 记录重复,而其它数据库不限制;

对于is null使用Btree索引, 只有Oracle是默认无法索引的(需要创建常量的复合索引),其它数据库优化器在认为合适时可以正常使用索引;

对于null与字符串拼接就更有意思,sql server\postgresql\mysql在与null拼接后返回null, Oracle返回是字符串的值,而且基于Postgresql的OpenGauss返回和Oracle相同也是字符串,看来是与oracle做过兼容性修改。

— 下期继续 —

Alert: Move partition Update Indexes索引空间可能未释放

$
0
0

在做分区表move维护时,可以使用’UPDATE INDEXES’ 选项更新  global 和 local indexes ,使索引并不失效,11.2.0.4版本前有个小bug,在update indexes期间也有短暂的local index失效,在oracle 12c 后引入新特性move online partition ,可以在DDL期间不锁DML操作,注意在online move 期间也会发生 UPDATE INDEXES or UPDATE GLOBAL INDEXES索引维护, 对于非online move 该update indexes选项同样可用, 所以对于update indexes与否online维护分区没有限制区别。

前几日发现一个现象,好些分区索引比分区表大好多倍,甚至分区表只是initial 大小如8M,对应的索引分区达GB。是因为此业务表存在大量的DELETE, 最近刚做过move partition的维护,释放了TABLE分区的空间,但是index 分区并未释放。之前听说过有客户因为Oracle 12c 的Asynchronous Global Index Maintenance 特性,在做了分区维护后Global Index 空间一直无法reuse的bug(bug# 29814995) 直到19.10 RU才修复. 没想到Local Index也存在空间相关问题,这里演示分区维护有些不同。

–demo version 19.3

# create partition table with global PK
CREATE TABLE anbob.test1_part (product NUMBER(16) PRIMARY KEY,customer VARCHAR2(4000),time_id DATE)
PARTITION BY RANGE (time_id)
(PARTITION test1_PART1 VALUES LESS THAN (TO_DATE('01-JUL-2013','DD-MON-YYYY')),
PARTITION test1_PART2 VALUES LESS THAN (TO_DATE('01-AUG-2013','DD-MON-YYYY')),
PARTITION test1_PART3 VALUES LESS THAN (TO_DATE('01-SEP-2013','DD-MON-YYYY')),
PARTITION test1_PART4 VALUES LESS THAN (TO_DATE('01-OCT-2013','DD-MON-YYYY')),
PARTITION test1_PART5 VALUES LESS THAN (TO_DATE('01-NOV-2013','DD-MON-YYYY')),
PARTITION test1_PART6 VALUES LESS THAN (TO_DATE('01-DEC-2013','DD-MON-YYYY')),
PARTITION test1_PART7 VALUES LESS THAN (TO_DATE('01-JAN-2014','DD-MON-YYYY')),
PARTITION test1_PART_MAX VALUES LESS THAN (MAXVALUE));

insert into anbob.test1_part select rownum,'anbob'||rownum,TO_DATE('01-SEP-2013','DD-MON-YYYY')+rownum/24/60/60 from dual connect by rownum<=1000000; 

SQL> @seg anbob.test1_p

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        40 ANBOB                TEST1_PART                     TEST1_PART3                    TABLE PARTITION      USERS                                5120         12      17681

SQL> alter index anbob.SYS_C008051 rename to pk_TEST1_PART;
Index altered.
 
SQL> create index anbob.idx_test1_part_cust on anbob.test1_part(customer) local;
Index created.

SQL> @ind anbob.test1_part
Display indexes where table or index name matches %anbob.test1_part%...

TABLE_OWNER          TABLE_NAME                     INDEX_NAME                     POS# COLUMN_NAME                    DSC
-------------------- ------------------------------ ------------------------------ ---- ------------------------------ ----
ANBOB                TEST1_PART                     IDX_TEST1_PART_CUST               1 CUSTOMER
                                                    PK_TEST1_PART                     1 PRODUCT


INDEX_OWNER          TABLE_NAME                     INDEX_NAME                     IDXTYPE    UNIQ STATUS   PART TEMP  H     LFBLKS           NDK   NUM_ROWS       CLUF LAST_ANAL DEGREE VISIBILIT
-------------------- ------------------------------ ------------------------------ ---------- ---- -------- ---- ---- -- ---------- ------------- ---------- ---------- --------- ------ ---------
ANBOB                TEST1_PART                     IDX_TEST1_PART_CUST            NORMAL     NO   N/A      YES  N     3       3195       1000000    1000000     193692 27-SEP-21 1      VISIBLE
                     TEST1_PART                     PK_TEST1_PART                  NORMAL     YES  VALID    NO   N     1          0             0          0          0 27-SEP-21 1      VISIBLE
SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        20 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                2560         12     185842

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        26 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                3328         12     185834

1 row selected.


truncate partition update indexes

SQL> alter table anbob.TEST1_PART truncate partition TEST1_PART3 update indexes;

Table truncated.

SQL> @seg anbob.test1_p

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         8 ANBOB                TEST1_PART                     TEST1_PART3                    TABLE PARTITION      USERS                                1024         12      17681

1 row selected.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        20 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                2560         12     185842

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

1 row selected.

SQL> @printtab 'select * from dba_indexes where index_name="PK_TEST1_PART"';
OWNER                         : ANBOB
INDEX_NAME                    : PK_TEST1_PART
INDEX_TYPE                    : NORMAL
TABLE_OWNER                   : ANBOB
TABLE_NAME                    : TEST1_PART
TABLE_TYPE                    : TABLE
UNIQUENESS                    : UNIQUE
COMPRESSION                   : DISABLED
PREFIX_LENGTH                 :
TABLESPACE_NAME               : USERS
INI_TRANS                     : 2
MAX_TRANS                     : 255
INITIAL_EXTENT                : 65536
NEXT_EXTENT                   : 1048576
MIN_EXTENTS                   : 1
MAX_EXTENTS                   : 2147483645
PCT_INCREASE                  :
PCT_THRESHOLD                 :
INCLUDE_COLUMN                :
FREELISTS                     :
FREELIST_GROUPS               :
PCT_FREE                      : 10
LOGGING                       : YES
BLEVEL                        : 0
LEAF_BLOCKS                   : 0
DISTINCT_KEYS                 : 0
AVG_LEAF_BLOCKS_PER_KEY       : 0
AVG_DATA_BLOCKS_PER_KEY       : 0
CLUSTERING_FACTOR             : 0
STATUS                        : VALID
NUM_ROWS                      : 0
SAMPLE_SIZE                   : 0
LAST_ANALYZED                 : 27-sep-2021 22:10:33
DEGREE                        : 1
INSTANCES                     : 1
PARTITIONED                   : NO
TEMPORARY                     : N
GENERATED                     : N
SECONDARY                     : N
BUFFER_POOL                   : DEFAULT
FLASH_CACHE                   : DEFAULT
CELL_FLASH_CACHE              : DEFAULT
USER_STATS                    : NO
DURATION                      :
PCT_DIRECT_ACCESS             :
ITYP_OWNER                    :
ITYP_NAME                     :
PARAMETERS                    :
GLOBAL_STATS                  : YES
DOMIDX_STATUS                 :
DOMIDX_OPSTATUS               :
FUNCIDX_STATUS                :
JOIN_INDEX                    : NO
IOT_REDUNDANT_PKEY_ELIM       : NO
DROPPED                       : NO
VISIBILITY                    : VISIBLE
DOMIDX_MANAGEMENT             :
SEGMENT_CREATED               : YES
ORPHANED_ENTRIES              : YES
INDEXING                      : FULL
AUTO                          : NO
CONSTRAINT_INDEX              : YES
-----------------

PL/SQL procedure successfully completed.

SQL> @printtab 'select * from dba_indexes where index_name="IDX_TEST1_PART_CUST"';
OWNER                         : ANBOB
INDEX_NAME                    : IDX_TEST1_PART_CUST
INDEX_TYPE                    : NORMAL
TABLE_OWNER                   : ANBOB
TABLE_NAME                    : TEST1_PART
TABLE_TYPE                    : TABLE
UNIQUENESS                    : NONUNIQUE
COMPRESSION                   : DISABLED
PREFIX_LENGTH                 :
TABLESPACE_NAME               :
INI_TRANS                     :
MAX_TRANS                     :
INITIAL_EXTENT                :
NEXT_EXTENT                   :
MIN_EXTENTS                   :
MAX_EXTENTS                   :
PCT_INCREASE                  :
PCT_THRESHOLD                 :
INCLUDE_COLUMN                :
FREELISTS                     :
FREELIST_GROUPS               :
PCT_FREE                      :
LOGGING                       :
BLEVEL                        : 2
LEAF_BLOCKS                   : 3195
DISTINCT_KEYS                 : 1000000
AVG_LEAF_BLOCKS_PER_KEY       : 1
AVG_DATA_BLOCKS_PER_KEY       : 1
CLUSTERING_FACTOR             : 193692
STATUS                        : N/A
NUM_ROWS                      : 1000000
SAMPLE_SIZE                   : 1000000
LAST_ANALYZED                 : 27-sep-2021 22:14:20
DEGREE                        : 1
INSTANCES                     : 1
PARTITIONED                   : YES
TEMPORARY                     : N
GENERATED                     : N
SECONDARY                     : N
BUFFER_POOL                   : DEFAULT
FLASH_CACHE                   : DEFAULT
CELL_FLASH_CACHE              : DEFAULT
USER_STATS                    : NO
DURATION                      :
PCT_DIRECT_ACCESS             :
ITYP_OWNER                    :
ITYP_NAME                     :
PARAMETERS                    :
GLOBAL_STATS                  : NO
DOMIDX_STATUS                 :
DOMIDX_OPSTATUS               :
FUNCIDX_STATUS                :
JOIN_INDEX                    : NO
IOT_REDUNDANT_PKEY_ELIM       : NO
DROPPED                       : NO
VISIBILITY                    : VISIBLE
DOMIDX_MANAGEMENT             :
SEGMENT_CREATED               : N/A
ORPHANED_ENTRIES              : NO
INDEXING                      : FULL
AUTO                          : NO
CONSTRAINT_INDEX              : NO
-----------------

PL/SQL procedure successfully completed.


SQL> ALTER INDEX anbob.PK_TEST1_PART COALESCE CLEANUP;

Index altered.

SQL> @printtab 'select * from dba_indexes where index_name="PK_TEST1_PART"';
OWNER                         : ANBOB
INDEX_NAME                    : PK_TEST1_PART
INDEX_TYPE                    : NORMAL
TABLE_OWNER                   : ANBOB
TABLE_NAME                    : TEST1_PART
TABLE_TYPE                    : TABLE
UNIQUENESS                    : UNIQUE
COMPRESSION                   : DISABLED
PREFIX_LENGTH                 :
TABLESPACE_NAME               : USERS
INI_TRANS                     : 2
MAX_TRANS                     : 255
INITIAL_EXTENT                : 65536
NEXT_EXTENT                   : 1048576
MIN_EXTENTS                   : 1
MAX_EXTENTS                   : 2147483645
PCT_INCREASE                  :
PCT_THRESHOLD                 :
INCLUDE_COLUMN                :
FREELISTS                     :
FREELIST_GROUPS               :
PCT_FREE                      : 10
LOGGING                       : YES
BLEVEL                        : 0
LEAF_BLOCKS                   : 0
DISTINCT_KEYS                 : 0
AVG_LEAF_BLOCKS_PER_KEY       : 0
AVG_DATA_BLOCKS_PER_KEY       : 0
CLUSTERING_FACTOR             : 0
STATUS                        : VALID
NUM_ROWS                      : 0
SAMPLE_SIZE                   : 0
LAST_ANALYZED                 : 27-sep-2021 22:10:33
DEGREE                        : 1
INSTANCES                     : 1
PARTITIONED                   : NO
TEMPORARY                     : N
GENERATED                     : N
SECONDARY                     : N
BUFFER_POOL                   : DEFAULT
FLASH_CACHE                   : DEFAULT
CELL_FLASH_CACHE              : DEFAULT
USER_STATS                    : NO
DURATION                      :
PCT_DIRECT_ACCESS             :
ITYP_OWNER                    :
ITYP_NAME                     :
PARAMETERS                    :
GLOBAL_STATS                  : YES
DOMIDX_STATUS                 :
DOMIDX_OPSTATUS               :
FUNCIDX_STATUS                :
JOIN_INDEX                    : NO
IOT_REDUNDANT_PKEY_ELIM       : NO
DROPPED                       : NO
VISIBILITY                    : VISIBLE
DOMIDX_MANAGEMENT             :
SEGMENT_CREATED               : YES
ORPHANED_ENTRIES              : NO
INDEXING                      : FULL
AUTO                          : NO
CONSTRAINT_INDEX              : YES
-----------------

PL/SQL procedure successfully completed.


SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        20 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                2560         12     185842

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

1 row selected.
 
SQL> insert into anbob.test1_part select rownum,'anbob'||rownum,TO_DATE('01-SEP-2013','DD-MON-YYYY')+rownum/24/60/60 from dual connect by rownum<=1000000; 1000000 rows created. SQL> COMMIT;

Commit complete.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     185842

1 row selected.

SQL>  @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        44 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART4                    INDEX PARTITION      USERS                                5632         12     185850
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

2 rows selected.

SQL>

SQL> alter table anbob.TEST1_PART truncate partition TEST1_PART3 update indexes;

Table truncated.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     191362

1 row selected.

SQL> insert into anbob.test1_part select 1000000+rownum,'anbob'||rownum,TO_DATE('01-SEP-2013','DD-MON-YYYY')+rownum/24/60/60 from dual connect by rownum<=1000000; 
1000000 rows created. 
SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        58 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                7424         12     191362

1 row selected.

Note:
truncate partition update indexes后,global index 空间无释放,似乎也没有reuse,即使手动执行COALESCE CLEANUP 清理孤立条目后。 local index发生rebuild空间已释放。

move partition with update indexes

SQL> delete anbob.test1_part;

1000000 rows deleted.

SQL> commit;
Commit complete.

SQL> alter table anbob.TEST1_PART move partition TEST1_PART4 update indexes;
Table altered.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     185842

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        44 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART4                    INDEX PARTITION      USERS                                5632         12     185850
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

2 rows selected.

Note:
move partition update indexes后GLOBAL和local index的索引段空间都未释放。

move partition without update indexes

insert into anbob.test1_part select rownum,'anbob'||rownum,TO_DATE('01-SEP-2013','DD-MON-YYYY')+rownum/24/60/60 from dual connect by rownum<=1000000;
insert into anbob.test1_part select 1000001+rownum,'anbob'||rownum,TO_DATE('01-AUG-2013','DD-MON-YYYY')+rownum/24/60/60 from dual connect by rownum<=10; SQL> @seg anbob.test1_part

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        40 ANBOB                TEST1_PART                     TEST1_PART4                    TABLE PARTITION      USERS                                5120         12      34065
         8 ANBOB                TEST1_PART                     TEST1_PART3                    TABLE PARTITION      USERS                                1024         12      17681

2 rows selected.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     185842

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        44 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART4                    INDEX PARTITION      USERS                                5632         12     185850
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

2 rows selected.

SQL> delete anbob.TEST1_PART partition(TEST1_PART4);

1000000 rows deleted.

SQL> commit;

SQL> alter table anbob.TEST1_PART move partition TEST1_PART4
  2  ;

Table altered.

SQL> @seg  anbob.TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         8 ANBOB                TEST1_PART                     TEST1_PART4                    TABLE PARTITION      USERS                                1024         12      19217
         8 ANBOB                TEST1_PART                     TEST1_PART3                    TABLE PARTITION      USERS                                1024         12      17681

2 rows selected.

SQL> @ind anbob.TEST1_PART;
Display indexes where table or index name matches %anbob.TEST1_PART%...

TABLE_OWNER          TABLE_NAME                     INDEX_NAME                     POS# COLUMN_NAME                    DSC
-------------------- ------------------------------ ------------------------------ ---- ------------------------------ ----
ANBOB                TEST1_PART                     IDX_TEST1_PART_CUST               1 CUSTOMER
                                                    PK_TEST1_PART                     1 PRODUCT


INDEX_OWNER          TABLE_NAME                     INDEX_NAME                     IDXTYPE    UNIQ STATUS   PART TEMP  H     LFBLKS           NDK   NUM_ROWS       CLUF LAST_ANAL DEGREE VISIBILIT
-------------------- ------------------------------ ------------------------------ ---------- ---- -------- ---- ---- -- ---------- ------------- ---------- ---------- --------- ------ ---------
ANBOB                TEST1_PART                     IDX_TEST1_PART_CUST            NORMAL     NO   N/A      YES  N     3       3195       1000000    1000000     193692 27-SEP-21 1      VISIBLE
                     TEST1_PART                     PK_TEST1_PART                  NORMAL     YES  UNUSABLE NO   N     1          0             0          0          0 27-SEP-21 1      VISIBLE
SQL>

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     191362

1 row selected.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        45 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART4                    INDEX PARTITION      USERS                                5760         12     185850
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

2 rows selected.

NOTE:
Global和local index 的大小均未改变,因为是empty空分区,move 后索引都未失效。

move partition online

SQL> alter table anbob.TEST1_PART move partition TEST1_PART4 online;

Table altered.

SQL> @seg anbob.IDX_TEST1_PART_CUST

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART4                    INDEX PARTITION      USERS                                   8         12     266154
         0 ANBOB                IDX_TEST1_PART_CUST            TEST1_PART3                    INDEX PARTITION      USERS                                   8         12     185834

2 rows selected.

SQL> @seg anbob.PK_TEST1_PART

    SEG_MB OWNER                SEGMENT_NAME                   SEG_PART_NAME                  SEGMENT_TYPE         SEG_TABLESPACE_NAME                BLOCKS     HDRFIL     HDRBLK
---------- -------------------- ------------------------------ ------------------------------ -------------------- ------------------------------ ---------- ---------- ----------
        38 ANBOB                PK_TEST1_PART                                                 INDEX                USERS                                4864         12     191362

1 row selected.

-- 10046 trace 
ALTER INDEX "ANBOB"."IDX_TEST1_PART_CUST" REBUILD  PARTITION "TEST1_PART4"
  NOPARALLEL

NOTE:
move online会递归做索引的rebuild, 所以local索引对应的分区释放了,但global index 空间未改变。

对于登录相关的 LAST SUCCESSFUL LOGIN TIME的Library cache lock又出新参数

$
0
0

之前分享过2篇关于 LAST SUCCESSFUL LOGIN TIME 的笔记,Oracle19c 建议的 One-off patch之disable LAST SUCCESSFUL LOGIN TIME Oracle 12c New Feature: Last Login Time for Non-Sys Users, 最近这个特性Oracle又给出来了2个参数,还是很巧妙,继续记录一下。

上周发布了新 Bug 33121934  Library cache lock / load lock / mutex x during connection storm, 也是在登录高并发时,因为更新最后登录时间特性出现的library cache lock等问题,之前是引入_disable_last_successful_login_time禁用,这次引入了2个新的隐藏参数可以细化行为的更新, 不用再那么频繁。

_disable_last_successful_login_time_unlimited_iat

– This controls whether  users associated with a password profile with UNLIMITED Inactive Account Time will not have their LSLT updated.

_granularity_last_successful_login_time

– This controls the granularity of LSLT update for _ALL_ users. Say, it is set to 30 seconds and then all users logons within that period of 30 seconds will NOT update the LSLT

Alert: Oracle GoldenGate 19 was change ALLOWNULLABLEKEYS to NOALLOWNULLABLEKEYS

$
0
0

OGG 19.*默认改变原来OGG 12版本ALLOWNULLABLEKEYS为NOALLOWNULLABLEKEYS, 这样会导致在replicat时因为不考虑可为空的唯一索引做为标示键,而使用全字段组合在一起作为行的唯一标识,但是EXTRACE的源库又只有这个唯一键的附加日志,trail中也只有该唯一列更新列时,在replicat时会产生OGG-1403记录不存在,而丢失更新,insert不受影响, 同时oggerr日志中记录的是INFO OGG-06441,这样更不会引起人的注意,ogg add trandata 也会有提示。

 INFO    OGG-06441Unique key UK.... for table ....  cannot be used due to the inclusion of virtual columns, 
or user-defined datatypes, or extended long varchar columns, or function-based index columns.

而后来又有客户要求,上面的info级别不拖,Oracle更改了上面的提示有info 到warning ,并制作了 Bug 30523672 fix,并且增加了nullable columns原因,已经在ogg 20.* 版本自带, 发现目前OTN上已经下线了ogg 这个版本,目前是ogg 20.3, 修改后的提示如下:

 WARNING OGG-06441 Unique key xxx for table  xxx cannot be used due to the inclusion of virtual
columns, nullable columns, or user-defined datatypes, or extended long varchar columns, or function-based index columns.

NOALLOWNULLABLEKEYS 官方文档
Description

Use NOALLOWNULLABLEKEYS to change the key selection logic so that it does not consider a nullable unique key as a viable candidate for uniquely identifying a row. When disabled, the nullable unique keys are viable candidates. The default value for NOALLOWNULLABLEKEYS is set to true.

Allowing Oracle GoldenGate to use a nullable key can cause data corruption, as Oracle treats each row with a NULL value as a key column and as a separate unique value. It is recommended to use NOALLOWNULLABLEKEYS unless you are absolutely sure that the key column does not contain any NULL values.

Be careful when using this parameter because it impacts the contents of the trail file and all installations must be in sync when using this parameter.

Upon upgrade to Oracle GoldenGate 19c, it is recommended that you query DBA_LOGSTDBY_NOT_UNIQUE view. If SCHEMATRANDATA is not being used, then for each table in DBA_LOGSTDBY_NOT_UNIQUE view, add KEYCOLS that mirror key columns returned by INFO TRANDATA, DELETE TRANDATA, or ADD TRANDATA for table to select or use a key with non-NULL columns.

解决方法
A.
源和目标库的OGG GLOBALS 文件增加ALLOWNULLABLEKEYS 回退到OGG 12的行为,源库表增加全列附加日志。
— or —
B.
replicat 参数中指定KEYCOLS逻辑唯一列,确保应用的表中没有null记录。

小试墨天轮社区Oracle、MySQL、Redis、PostgreSQL等线上数据库测试平台

$
0
0

墨天轮社区最近发布了“数据库在线实训平台”(https://www.modb.pro/marketlist?type=1),目前支持Oracle、MySQL、Redis、PostgreSQL、openGauss和MogDB六类数据库。如果参加过国产数据库的一些线上培训认证的话,会接触到这种形式的数据库玩法,简而言之就是你可以在浏览器中的命令行窗口,做一些数据库命令的学习研究。

Oracle有提供Oracle Live SQL线上用于测试Oracle SQL语法,仅提供Oracle Database, 当时客户环境中数据库种类变的丰富,有时需要测试在不同数据库中SQL语法的兼容性,之前我经常使用是一个类似功能英国一家网站,可以测试Oracle,mysql,PostgreSQL、sqlserver、DB2等主流版本SQL语法,是一种SaaS的形式, 墨天轮社区当前的实训平台提供出数据库及下层的操作系统,是一个浏览器中以命令行访问的远程虚拟主机,可以在OS层查看一些日志文件,做系统性能诊断等,各有好处吧,下面我测试了一下Oracle 和openGauss(pg)2个平台。

开通方法:

1,注册墨天轮社区帐号
2,进入页面上方云市场 或通过这个连接数据库在线实训平台
3,选择计划测的数据库平台,在线支付人民币1分钱,支持微信和支付宝
4,在控制台 我的数据库中可以看到对应的产品库, “连接数据库” 进入虚拟环境的Linux ROOT用户
5,   根据实训窗口左测提示帮助即可进入不同命令行操作。

平台操作体验:

支付开通体验比较方便,平台加载基本<1分钟,命令窗口操作流畅,在资源配置上并没有太节约。对于Oracle环境8c 16g内存 70G 磁盘空间;对于opengauss 配置48c 100g内存 30g磁盘空间。空闲一段时间环境内操作自动断开,需要退出重进。 oracle 环境操作系统当前实际为OEL 7.9并非Rad hat Linux 8。  操作系统也安装了oracle-database-preinstall-18c 预安装包,有配置Hugepage和一些sample schema和SQL脚本,数据库为Oracle 提供的免费XE版本18.4.  多租户环境。命令行窗口是可以直接右键复杂粘贴,暂时不支持上传下载。

对于看到平台上有人问是否可以安装当前主流的Oracle 19c ?或是否安装RAC? 我想大家可以去了解一下Oracle XE版,该版本并不同于生产环境中使用的EE企业版,程序代码基本可以认为独立的产品线,之前我有篇Blog《浅谈ORACLE免费数据库Oracle Database XE版》 有介绍, 该版本在功能和资源上有些限制,比如XE版没有19c,当前看Oracle XE 在18c后是21c,另外也不支持RAC.  同时在CPU,内存上有限制,所以当前的虚拟机给的资源是绰绰有余的, 出于法律风险我个人感觉也不适合提供Oracle企业版。

openGauss平台是2.0版 on Debian GNU/Linux 10,CPU内存资源非常丰富,单机功能测试没有什么问题,暂时未做太多测试不做过多评论。

建议和不足:

1,首先该功能的入口感觉不够醒目或流畅,如支付成功后未跳转;第二次使用时找实训平台已购买的入口不方便。命令行窗口切换(或vi )时会变会半屏,但只是显示问题。

2,另一个问题是如果购买2个数据库,同1个用户无法同时运行多个虚拟平台数据库,想横向对比不同数据库时,需要反复的重启。

3, 虽然1分钱并不多,但是去掉这个限制,相信用户会更多些,而是使用其它方法限制滥用。

总结一下,该平台为个人学习多种数据库、提供了快捷交付环境,命令行操作流畅。也可以做操作系统层上的命令测试。对于无虚机环境测试,研究多类型数据库的同学不妨测试一下。

提示:以上仅为个人观点,不代表我雇主建议。

 

Viewing all 693 articles
Browse latest View live