{"id":3368,"date":"2020-06-03T16:29:26","date_gmt":"2020-06-03T16:29:26","guid":{"rendered":"https:\/\/nenadnoveljic.com\/blog\/?p=3368"},"modified":"2020-10-12T11:51:35","modified_gmt":"2020-10-12T11:51:35","slug":"tracing-latches-redo-copy-contention","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/","title":{"rendered":"Tracing Latches: Redo Copy Contention"},"content":{"rendered":"<h1>Tracing latches<\/h1>\n<p>Latch waits are well instrumented in Oracle database. We can see for how long a process was waiting for a latch. We can also identify the latch holder. But it&#8217;s difficult to observe a problem from the blockers perspective. We don&#8217;t know for how long the blocker was holding the latch. We also don&#8217;t have a broader context.<\/p>\n<p>I closed this gap with the DTrace script <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a>. The script traces the calls to the relevant Oracle C functions. In particular, latches are acquired and released by calling kslgetl and kslfre, respectively <a href=\"https:\/\/andreynikolaev.files.wordpress.com\/2016\/03\/latches_and_mutexes_in_oracle_12c.pdf\">[1]<\/a>. The latch address is passed by the first argument. DTrace prints the latch address and the call stack whenever a latch is requested or released.<\/p>\n<p>For instance, I was tracing a process which executed a simple insert followed by a commit:<\/p>\n<pre><code>dtrace -s <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a> -p <span style=\"color:green\">8451<\/span> &gt; latches.trc<\/code><\/pre>\n<pre><code>@whoami\n\nSADDR            SPID                            SID    SERIAL#        PID\n---------------- ------------------------ ---------- ---------- ----------\nPROCESS\n------------------------\n00000000C859B3A8 <span style=\"color:green\">8451<\/span>                           5214      50407         13\n7820\n\ninsert into t values (1);\n<span style=\"color:blue\">commit<\/span> ;<\/code><\/pre>\n<p>Below is the excerpt from the trace file:<\/p>\n<pre><code>kslgetl: 0X14EE2C028 0 0x0 3925\n\noracle`kslgetl\noracle`kcrfw_redo_gen_ext+0x39f\noracle`kcb_commit_main+0xc11\noracle`<span style=\"color:blue\">kcb_commit<\/span>+0x107\noracle`ktiCommitCleanout+0x257\noracle`kticmt+0x64c\noracle`ktucmt+0x21f\noracle`ktcCommitTxn_new+0x402\noracle`ktcCommitTxn+0x5b\noracle`ktdcmt+0x86\noracle`k2lcom+0x99\noracle`k2send+0x514\noracle`xctctl+0x64\noracle`xctCommitTxn+0x305\noracle`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\n-----------------\n\n\nkslfre: <span style=\"color:red\">0X14EE2C028<\/span> 0 0x0 5135376848\n\noracle`kslfre\noracle`kcrfw_redo_gen_ext+0x1094\noracle`kcb_commit_main+0xc11\noracle`<span style=\"color:blue\">kcb_commit<\/span>+0x107\noracle`ktiCommitCleanout+0x257\noracle`kticmt+0x64c\noracle`ktucmt+0x21f\noracle`ktcCommitTxn_new+0x402\noracle`ktcCommitTxn+0x5b\noracle`ktdcmt+0x86\noracle`k2lcom+0x99\noracle`k2send+0x514\noracle`xctctl+0x64\noracle`xctCommitTxn+0x305\noracle`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\nlatch elapsed[us]: 285, on cpu[us]: 280<\/code><\/pre>\n<p>You have to query the database for the latch name:<\/p>\n<pre><code>select name from v$latch_children where addr = lpad('<span style=\"color:red\">14EE2C028<\/span>',16,'0');\n\n\nNAME\n----------------------------------------------------------------\nredo copy<\/code><\/pre>\n<p>This is tedious, as a process typically allocates many latches. I wrote a Perl program to eliminate that toil. It enriches the trace with the latch name.<\/p>\n<p>First, create the mapping file:<\/p>\n<pre><code>sqlplus -s \/nolog &lt;&lt; EOD\nconnect \/ as sysdba\nset pagesize 0\nset linesize 200\nspool latches.map\nselect '0X'||ltrim(addr,'0'), name from v\\$latch\nunion \nselect '0X'||ltrim(addr,'0'), name from v\\$latch_children ;\nEOD<\/code><\/pre>\n<p>The mapping file contains the address of each latch. Beware that those addresses change after a database restart.<\/p>\n<p>Then, postprocess the captured trace:<\/p>\n<pre><code><a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/process_latches_trace.pl\">process_latches_trace.pl<\/a> latches.trc latches.map<\/code><\/pre>\n<p>Now we can see the latch name for each latch operation:<\/p>\n<pre><code>kslgetl: <span style=\"color:red\">redo copy<\/span> 0X14EE2C028 0 0x0 3925\n\noracle`kslgetl\noracle`kcrfw_redo_gen_ext+0x39f\noracle`kcb_commit_main+0xc11\noracle`kcb_commit+0x107\noracle`ktiCommitCleanout+0x257\noracle`kticmt+0x64c\noracle`ktucmt+0x21f\noracle`ktcCommitTxn_new+0x402\noracle`ktcCommitTxn+0x5b\noracle`ktdcmt+0x86\noracle`k2lcom+0x99\noracle`k2send+0x514\noracle`xctctl+0x64\noracle`xctCommitTxn+0x305\noracle`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\n-----------------\n\n\nkslfre: <span style=\"color:red\">redo copy<\/span> 0X14EE2C028 0 0x0 5135376848\n\noracle`kslfre\noracle`kcrfw_redo_gen_ext+0x1094\noracle`kcb_commit_main+0xc11\noracle`kcb_commit+0x107\noracle`ktiCommitCleanout+0x257\noracle`kticmt+0x64c\noracle`ktucmt+0x21f\noracle`ktcCommitTxn_new+0x402\noracle`ktcCommitTxn+0x5b\noracle`ktdcmt+0x86\noracle`k2lcom+0x99\noracle`k2send+0x514\noracle`xctctl+0x64\noracle`xctCommitTxn+0x305\noracle`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\nlatch elapsed[us]: 285, on cpu[us]: 280<\/code><\/pre>\n<h1>Redo copy latch<\/h1>\n<h2>Logon trace<\/h2>\n<p>I tested the described methodology on a latch contention problem <a href=\"https:\/\/twitter.com\/jolliffe\/status\/1265556259270508546\">discussed on Twitter<\/a>. The root blockers were holding redo copy latches during logon while executing &#8220;update user$ spare6&#8221; &#8211; the last logon time update. There were around 50 logons per seconds.<\/p>\n<p>With <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a> we can measure for how long a process was holding a latch. But how do we get the process ID of a new process? We can&#8217;t query the PID, because the entries in v$session and v$process haven&#8217;t been created yet. Instead, we have to pause the dedicated process immediately after forking. I scripted the solution: <a href=\"https:\/\/nenadnoveljic.com\/blog\/debugging-session-creation\/\">stop_forked.d<\/a> stops the execution in the authentication function kpoauth and prints the PID. Then you have all the time in the world to run <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a>.<\/p>\n<pre><code>dtrace -ws <a href=\"https:\/\/nenadnoveljic.com\/blog\/debugging-session-creation\/\">stop_forked.d<\/a> '\"DB1\"'\nDB: DB1, pid: 4254\n\ndtrace -s <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a> -p 4254 &gt; latches.trc\n\n<a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/process_latches_trace.pl\">process_latches_trace.pl<\/a> latches.trc latches.map<\/code><\/pre>\n<p>A redo copy latch was indeed held for almost 6ms:<\/p>\n<pre><code>...\nkslfre: redo copy 0X14EE2FF70 0 0x0 12905805352\n\noracle`kslfre\noracle`kcrfw_redo_gen_ext+0x1094\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdu_array_flush_retry+0xc6d\noracle`kdu_array_flush1+0x50\noracle`qerupFetch+0x45c\noracle`updaul+0x678\noracle`updThreePhaseExe+0x14e\noracle`updexe+0x1ec\noracle`opiexe+0x30fc\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\n<span style=\"color:red\">latch elapsed[us]: 5976<\/span>, on cpu[us]: 5953\n...<\/code><\/pre>\n<p>That&#8217;s extremely long for a latch &#8211; the elapsed time is normally measured in microseconds. The stack shows that the latch was acquired by an update. But how do we know that it is the originally reported update? We can set a conditional breakpoint when the latch is acquired and look at the active sessions. The following query generates the breakpoint command that we can copy into the gdb.<\/p>\n<pre><code>set define off\nselect \n  'b kslgetl if $rdi &gt;= 0X'||min(addr)||' &amp;&amp; $rdi &lt;= 0X' || max(addr) \n    gdb_breakpoint\n  from v$latch_children where name='redo copy' ;\n\nGDB_BREAKPOINT\n---------------------------------------------------------------------\nb kslgetl if $rdi &gt;= 0X000000014EE2B530 &amp;&amp; $rdi &lt;= 0X000000014EE37ED8<\/code><\/pre>\n<pre><code>@<a href=\"https:\/\/github.com\/tanelpoder\/tpt-oracle\/blob\/master\/ash\/ashtop.sql\">ashtop<\/a> sql_id \"program like 'sql%'\" &amp;5min\n\n    Total                                                                         Distinct\n  Seconds     AAS %This   SQL_ID        FIRST_SEEN          LAST_SEEN           Execs Seen\n--------- ------- ------- ------------- ------------------- ------------------- ----------\n       72      .2   96% | 9zg9qd9bm4spu 2020-06-01 18:27:25 2020-06-01 18:28:37          1\n\n\n@<a href=\"https:\/\/github.com\/tanelpoder\/tpt-oracle\/blob\/master\/awr\/awr_sqlid.sql\">awr_sqlid<\/a> 9zg9qd9bm4spu\n\n      DBID SQL_ID        SQL_TEXT                                                                                                                                                                                                 COMMAND_TYPE   CON_DBID     CON_ID\n---------- ------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------ ---------- ----------\n 510006313 9zg9qd9bm4spu update user$ set spare6=DECODE(to_char(:2, 'YYYY-MM-DD'), '0000-00-00', to_date(NULL), :2) where user#=:1                                                                                                           6  510006313          0<\/code><\/pre>\n<p>As you can see, it&#8217;s the same statement.<\/p>\n<h2>Private strands<\/h2>\n<p><a href=\"https:\/\/fritshoogland.wordpress.com\/\">Frits Hoogland<\/a> noticed the function kcrfw_redo_gen_ext on the stack and concluded that private strands haven\u2019t been used. Since private strands aren&#8217;t used, a redo copy latch has to be allocated before copying data into the redo buffer. Interestingly, private strands are used if we run the same statement in sqlplus. In other words, private strands aren&#8217;t used only during the logon.<\/p>\n<p><ins id=\"kcrfw_redo_gen_ext\">Inserted on October 12, 2020: The block changes are deferred until commit when private strands are being used. The Oracle C function kcrfw_redo_gen_ext is called during commit to perform block changes. A kcrfw_redo_gen_ext function call during DML indicates that the private strands were bypassed. <a href=\"https:\/\/fritshoogland.wordpress.com\/2018\/03\/26\/a-look-into-oracle-redo-part-8-generate-redo\/\">[3]<\/a><\/ins><\/p>\n<h2>kcbklbc<\/h2>\n<p>The almost entire time of holding the latch is being spent in kcbklbc. We can prove this by extending <a href=\"https:\/\/github.com\/nenadnoveljic\/blogs\/blob\/master\/tracing-latches-redo-copy-contention\/trace_latches.d\">trace_latches.d<\/a> as follows:<\/p>\n<pre><code>pid$target:oracle:kcbklbc:entry\n{\n  self-&gt;start_kcbklbc = timestamp ;\n}\n\npid$target:oracle:kcbklbc:return\n\/ self-&gt;start_kcbklbc \/\n{\n  printf(\"kcbklbc[us]: %d\\n\", (timestamp - self-&gt;start_kcbklbc)\/1000 ) ;\n  ustack();\n  self-&gt;start_kcbklbc = 0 ;\n}<\/code><\/pre>\n<p>The extension above measures the time spent in kcbklbc:<\/p>\n<pre><code><span style=\"color:red\">kcbklbc[us]: 5995<\/span>\n\noracle`kcbklbc+0x3a1\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdu_array_flush_retry+0xc6d\noracle`kdu_array_flush1+0x50\noracle`qerupFetch+0x45c\noracle`updaul+0x678\noracle`updThreePhaseExe+0x14e\noracle`updexe+0x1ec\noracle`opiexe+0x30fc\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\noracle`kpuexec+0x1e9a\n\n\n<span style=\"color:red\">kslfre: redo copy<\/span> 0X14EE2E8A8 0 0x0 12899699752\n\noracle`kslfre\noracle`kcrfw_redo_gen_ext+0x1094\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdu_array_flush_retry+0xc6d\noracle`kdu_array_flush1+0x50\noracle`qerupFetch+0x45c\noracle`updaul+0x678\noracle`updThreePhaseExe+0x14e\noracle`updexe+0x1ec\noracle`opiexe+0x30fc\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\nlatch elapsed[us]: 6313, on cpu[us]: 6280<\/code><\/pre>\n<p>The kcbklbc annotation is &#8220;kernel cache buffers checkpoint queue manipulation link buffer into ckpt queue&#8221; <a href=\"http:\/\/orafun.info\/\">[2]<\/a>.<\/p>\n<p>The function is called whenever a redo copy latch gets allocated. In most cases it runs quickly. For example, it took only 61 microseconds for a commit:<\/p>\n<pre><code>kcbklbc[us]: 61\n\noracle`kcbklbc+0x3a1\noracle`kcb_commit_main+0xc11\noracle`kcb_commit+0x107\na.out`ktiCommitCleanout+0x257\na.out`kticmt+0x64c\na.out`ktucmt+0x21f\na.out`ktcCommitTxn_new+0x402\na.out`ktcCommitTxn+0x5b\na.out`ktdcmt+0x86\na.out`k2lcom+0x99\na.out`k2send+0x514\na.out`xctctl+0x64\na.out`xctCommitTxn+0x305\na.out`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\na.out`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\noracle`opiino+0x4a8\n\n\nkslfre: redo copy 0X14EE2DC00 0 0x0 5135376848\n\noracle`kslfre\noracle`kcrfw_redo_gen_ext+0x1094\noracle`kcb_commit_main+0xc11\noracle`kcb_commit+0x107\na.out`ktiCommitCleanout+0x257\na.out`kticmt+0x64c\na.out`ktucmt+0x21f\na.out`ktcCommitTxn_new+0x402\na.out`ktcCommitTxn+0x5b\na.out`ktdcmt+0x86\na.out`k2lcom+0x99\na.out`k2send+0x514\na.out`xctctl+0x64\na.out`xctCommitTxn+0x305\na.out`kksExecuteCommand+0x4fd\noracle`opiexe+0x339a\na.out`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\nlatch elapsed[us]: 192, on cpu[us]: 161<\/code><\/pre>\n<p>The logon update seems like a special case. The execution branches to a code path taking up much more time. Interestingly, the execution doesn&#8217;t take nearly that long after a database restart:<\/p>\n<pre><code>kcbklbc[us]: 14\n\noracle`kcbklbc+0x3a1\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdu_array_flush_retry+0xc6d\noracle`kdu_array_flush1+0x50\noracle`qerupFetch+0x45c\noracle`updaul+0x678\noracle`updThreePhaseExe+0x14e\noracle`updexe+0x1ec\noracle`opiexe+0x30fc\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\noracle`kpuexec+0x1e9a<\/code><\/pre>\n<p>But after a couple of minutes the code for special handling gets executed again. I still haven&#8217;t figured out what that special handling is, and what triggers it.<\/p>\n<h1>Summary<\/h1>\n<p>I wrote a DTrace script for measuring for how long each latch was being held. The script also provides the context by printing the stack when a latch is acquired or released. I&#8217;m not aware of a database trace that shows similar information.<\/p>\n<p>update user$ during logon doesn\u2019t use private strands. Consequently, it allocates a redo copy latch and can hold it for several milliseconds. That&#8217;s an extremely long time to occupy a latch. The most of that time the process is being busy with manipulating the checkpoint queues. That can cause serious wait cascades during logon storms. The best protection is a proper connection pooling.<\/p>\n<h1>Updates<\/h1>\n<h2>June 8th, 2020<\/h2>\n<h3>Recursive DML<\/h3>\n<p><a href=\"https:\/\/jonathanlewis.wordpress.com\/\">Jonathan Lewis<\/a> pointed out that a DML execution under SYS on behalf on another user as a part of the internal code generally bypasses private strands. It&#8217;s easy to show that also insert aud$ copies the data directly into the public redo buffer:<\/p>\n<pre><code>oracle`<span style=\"color:red\">kcrfw_redo_gen_ext<\/span>\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdtchg+0x477\noracle`kdtwrp+0xac3\noracle`<span style=\"color:red\">kdtInsRow<\/span>+0x389\noracle`qerltcNoKdtBufferedInsRowCBK+0x16d\noracle`qerltcSingleRowLoad+0x137\noracle`qerltcFetch+0x1dc\noracle`insexe+0x33e\noracle`opiexe+0x1d8d\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e<\/code><\/pre>\n<h3>kcbklbc<\/h3>\n<p>kcbklbc runs for long only when executed during update user$.<\/p>\n<pre><code>kcbklbc[us]: <span style=\"color:blue\">44<\/span>\noracle`kcbklbc+0x3a1\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdtchg+0x477\noracle`kdtwrp+0xac3\noracle`<span style=\"color:blue\">kdtInsRow<\/span>+0x389\noracle`qerltcNoKdtBufferedInsRowCBK+0x16d\noracle`qerltcSingleRowLoad+0x137\noracle`qerltcFetch+0x1dc\noracle`insexe+0x33e\noracle`opiexe+0x1d8d\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\n\nkcbklbc[us]: <span style=\"color:blue\">2<\/span>\noracle`kcbklbc+0x3a1\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktucmt+0xcfe\noracle`ktcCommitTxn_new+0x402\noracle`<span style=\"color:blue\">ktcCommitTxn<\/span>+0x5b\noracle`audend+0x79\noracle`auddft_internal+0xf6f\noracle`audStatement+0x951\noracle`kpolnb+0x3ef0\noracle`kpoauth+0x419\noracle`opiodr+0x439\noracle`ttcpip+0x5f3\noracle`opitsk+0x9ec\noracle`opiino+0x4a8\noracle`opiodr+0x439\noracle`opidrv+0x33f\noracle`sou2o+0x97\noracle`opimai_real+0x121\noracle`ssthrdmain+0x26b\n\nkcbklbc[us]: <span style=\"color:red\">5011<\/span>\noracle`kcbklbc+0x3a1\noracle`kcbchg1_main+0x1b7f\noracle`kcbchg1+0xe2\noracle`ktuchg2+0x911\noracle`ktbchg2+0x113\noracle`kdu_array_flush_retry+0xc6d\noracle`kdu_array_flush1+0x50\noracle`qerupFetch+0x45c\noracle`updaul+0x678\noracle`updThreePhaseExe+0x14e\noracle`<span style=\"color:red\">updexe<\/span>+0x1ec\noracle`opiexe+0x30fc\noracle`kpoal8+0xb5a\noracle`opiodr+0x439\noracle`kpoodrc+0x26\noracle`rpiswu2+0x2d6\noracle`kpoodr+0x2bb\noracle`upirtrc+0x1089\noracle`kpurcsc+0x6e\noracle`kpuexec+0x1e9a<\/code><\/pre>\n<p>However, if fast_start_mttr_target=0 kcbklbc always runs fast.<\/p>\n<h2>October 12th, 2020<\/h2>\n<h3>kcrfw_redo_gen_ext<\/h3>\n<p>Thanks to Frits Hoogland for the <a href=\"#kcrfw_redo_gen_ext\">additional explanation on kcrfw_redo_gen_ext<\/a>.<\/p>\n<h3>MTTR Advisor<\/h3>\n<p>I investigated the relevant MTTR advisor internals in the <a href=\"https:\/\/nenadnoveljic.com\/blog\/redo-copy-latch-mttr-advisor\/\">subsequent blog post<\/a>.<\/p>\n<h1>References<\/h1>\n<ul>\n<li><a href=\"https:\/\/andreynikolaev.files.wordpress.com\/2016\/03\/latches_and_mutexes_in_oracle_12c.pdf\">[1]<\/a> Andrey Nikolaev, <i>New features of Latches and Mutexes in Oracle 12c.<\/i> December 9, 2015.<\/li>\n<li><a href=\"http:\/\/orafun.info\/\">[2]<\/a> Frits Hoogland, <i>Oracle C functions annotations<\/i><\/li>\n<li><a href=\"https:\/\/fritshoogland.wordpress.com\/2018\/03\/26\/a-look-into-oracle-redo-part-8-generate-redo\/\">[3]<\/a> Frits Hoogland, <i>A look into oracle redo, part 8: generate redo.<\/i> March 26, 2018<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Tracing latches with OS tools, case study: redo copy contention caused by a logon storm <a href=\"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[24,34,5,37],"tags":[],"class_list":["post-3368","post","type-post","status-publish","format-standard","hentry","category-dtrace","category-latches","category-oracle","category-redo"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tracing Latches: Redo Copy Contention - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tracing Latches: Redo Copy Contention - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2020-06-03T16:29:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-10-12T11:51:35+00:00\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Tracing Latches: Redo Copy Contention\",\"datePublished\":\"2020-06-03T16:29:26+00:00\",\"dateModified\":\"2020-10-12T11:51:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/\"},\"wordCount\":951,\"commentCount\":0,\"articleSection\":[\"DTrace\",\"latches\",\"Oracle\",\"redo\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/\",\"name\":\"Tracing Latches: Redo Copy Contention - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"datePublished\":\"2020-06-03T16:29:26+00:00\",\"dateModified\":\"2020-10-12T11:51:35+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/tracing-latches-redo-copy-contention\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tracing Latches: Redo Copy Contention\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tracing Latches: Redo Copy Contention - All-round Database Topics","description":"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/","og_locale":"en_US","og_type":"article","og_title":"Tracing Latches: Redo Copy Contention - All-round Database Topics","og_description":"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm","og_url":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/","og_site_name":"All-round Database Topics","article_published_time":"2020-06-03T16:29:26+00:00","article_modified_time":"2020-10-12T11:51:35+00:00","author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Tracing Latches: Redo Copy Contention","datePublished":"2020-06-03T16:29:26+00:00","dateModified":"2020-10-12T11:51:35+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/"},"wordCount":951,"commentCount":0,"articleSection":["DTrace","latches","Oracle","redo"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/","url":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/","name":"Tracing Latches: Redo Copy Contention - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"datePublished":"2020-06-03T16:29:26+00:00","dateModified":"2020-10-12T11:51:35+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"Tracing latches with OS tools, case study: redo copy contention caused by a logon storm","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/tracing-latches-redo-copy-contention\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tracing Latches: Redo Copy Contention"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=3368"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3368\/revisions"}],"predecessor-version":[{"id":3605,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3368\/revisions\/3605"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=3368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=3368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=3368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}