SCN и Oracle

Converting Hexadecimal Oracle SCNs to Decimal

Oracle serializes transactions and manages concurrency and recovery using an ever-increasing number called a system change number, or SCN. Usually, we see these numbers expressed in decimal, in places like the v$ views and the alert log. Occasionally, however, Oracle’s code expresses SCNs in hexadecimal. Unfortunately, you can’t just perform a straght conversion from hex to dec to express these hex SCNs in dec. Here is the same Oracle SCNs expressed in hex and dec:

0x952.f5e60bda
10251917462490

Thanks to Tanel Poder’s generous assistance, I learned how to convert this kind of SCN to decimal.

The first portion of the hex scn is the number of times the second portion has reached the maximum value (ffffffff), and started back at 00000001. We’ll call it “wrap.”

The second portion of the hex scn is the base SCN value that increments one with each new change. We’ll call it “base.”

The formula for converting the hex SCN to dec would therefore be:

decimal = wrap * 4294967296 + base

I write a Unix shell on-liner to do the conversion:

1
$ a=0x952.f5e60bda;echo $((${a%%.*}*4294967296+0x${a##*.}))

Just replace the hex SCN I used in the example with your own.

Пример изменения SCN в буферном кеше:

 

Vadim_Maximov
SQL> create table a as select * from 
...

 CLASS STATE CHANGES FORCED_READS FORCED_WRITES TCH OBJECT_NAME HSCN_BAS HSCN_WRP HSUB_SCN
---------- ---------- ---------- ------------ ------------- ---------- -------------------------------------------------------------------------------- ---------- ---------- ----------
 4 1 1 0 0 1 A 6185383 0 1

Объект создан, в буферном кеше только блок заголовка сегмента (class=4),
в статусе текущий (state = 1)
SCN = ( HSCN_BAS=6185383 , HSCN_WRAP = 0)
Блоки данных писались на прямую, потому в буферном кеше их нет

Vadim_Maximov
SQL> update a set object_name = 'updated_' || object_name;

 CLASS STATE CHANGES FORCED_READS FORCED_WRITES TCH OBJECT_NAME HSCN_BAS HSCN_WRP HSUB_SCN
---------- ---------- ---------- ------------ ------------- ---------- -------------------------------------------------------------------------------- ---------- ---------- ----------
 4 1 1 0 0 2 A 6185383 0 1
 1 3 1 0 0 0 A 4294967295 65535 255
 1 1 1 0 0 1 A 6185388 0 1

Блок заголовка не менялся.
В процессе ищзменения в буферном кеше создано две версии блока,
текущая, после измения class=1 state=1 SCN(изменения) = (HSCN_BAS = 6185388 , HSCN_WRAP = 0).
И восстановленная (CR-копия, state = 3), на базе которой делаются изменения , с SCN = (FFFFFFFF,FFFF), вероятно некоторое “Условное” значение, а может даже просто, что то типа “не заполнено”,”очень много”, “очень мало”.

Vadim_Maximov
SQL> commit;
 CLASS STATE CHANGES FORCED_READS FORCED_WRITES TCH OBJECT_NAME HSCN_BAS HSCN_WRP HSUB_SCN
---------- ---------- ---------- ------------ ------------- ---------- -------------------------------------------------------------------------------- ---------- ---------- ----------
 4 1 1 0 0 2 A 6185383 0 1
 1 3 1 0 0 0 A 4294967295 65535 255
 1 1 1 0 0 1 A 6185461 0 1

В current-блок (class=1, state=1) записан SCN окончания транзакции (6185461,0).
Прочие блоки продалжают висеть в кеше

Vadim_Maximov
SQL> alter system checkpoint;

 CLASS STATE CHANGES FORCED_READS FORCED_WRITES TCH OBJECT_NAME HSCN_BAS HSCN_WRP HSUB_SCN
---------- ---------- ---------- ------------ ------------- ---------- -------------------------------------------------------------------------------- ---------- ---------- ----------
 4 1 1 0 0 2 A 4294967295 65535 1
 1 3 1 0 0 0 A 4294967295 65535 255
 1 1 1 0 0 1 A 4294967295 65535 1

SQL>

После checkpoint текущие блоки сброшены на диск. SCN-ы в буферном кеше для буферов блоков проставлено в наше “условное значение”.
На первый взгляд примерно так.