Oracle Block Cleanouts 块清除
当用户发出提交(commit)之后,oracle是需要写出redo来保证故障时数据可以被恢复,oracle并不需要在提交时就写出变更的数据块。由于在事务需要修改数据时,必须分配ITL事务槽,必须锁定行,必须分配回滚段事务槽和回滚表空间来记录要修改的数据的前镜像。当事务提交时,oracle需要将回滚段上的事务表信息标记为非活动,以便空间可以被重用那么还有ITL事务信息和锁定信息需要清除,以记录提交。
由于oracle在数据块上存储了ITL和锁定等事务信息,所以oracle必须在事务提交之后清除这些事务数据,这就是块清除。块清除主要清除的数据有行级锁、ITL信息(包括提交标志、scn等)。
如果提交时修改过的数据块仍然在buffer cache中,那么oracle可以清除ITL信息,这种清除叫做快速块清除(fast block cleanout),快速块清除还有一个限制,当修改的块数量超过buffer cache的10%,则对超出的部分不再进行快速块清除。
如果提交事务时,修改过的数据块已经被写回到数据文件上(或大量修改超出10%的部分),再次读出该数据块进行修改,显然成本过于高昂,对于这种情况,oracle选择延迟块清除(delayed block cleanout),等到下一次访问该block时再来清除ITL锁定信息,这就是延迟块清除。oracle通过延迟块清除来提高数据库的性能,加快提交操作。
快速提交是最普遍的情况。来看一下延迟块清除的处理:
SYS@ prod>update scott.emp set sal=1999 where empno=7369;
1 row updated.
SYS@ prod>update scott.emp set sal=1998 where empno=7499;
1 row updated.
SYS@ prod>update scott.emp set sal=1997 where empno=7521;
1 row updated.
更新完成之后,强制刷新buffer cache,将buffer cache中的数据都写出到数据文件:
SYS@ prod>alter system flush buffer_cache;
System altered.
查询事务及回滚段用户与转储
SYS@ prod>select xidusn,xidslot,ubafil,ubablk from v$transaction;
XIDUSN XIDSLOT UBAFIL UBABLK
---------- ---------- ---------- ----------
6 30 3 8028
SYS@ prod>select * from v$rollname where usn=6;
USN NAME
---------- ------------------------------
6 _SYSSMU6_2897970769$
此时再提交事务;
SYS@ prod> commit;
Commit complete.
由于此时更新过的数据已经写出到数据文件,oracle将执行延迟块清除,将此时的数据块和回滚段转储出来:
SYS@ prod>select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from scott.emp;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------ ------------------------------------
4 149
SYS@ prod> alter system dump datafile 4 block 149;
System altered.
SYS@ prod> alter system dump undo header '_SYSSMU1_592353410$';
System altered.
SYS@ prod> alter system dump datafile 3 block 8028;
System altered.
SYS@ prod>oradebug setmypid
Statement processed.
SYS@ prod>oradebug tracefile_name
/u01/diag/rdbms/prod/prod/trace/prod_ora_3775.trc
查看跟踪文件信息,看数据块上的信息,ITL事务信息仍然存在:
其中scn表示提交commit scn,fsc表示快速提交scn
Block dump from disk:
buffer tsn: 4 rdba: 0x01000095 (4/149)
scn: 0x0000.0013bc2d seq: 0x01 flg: 0x04 tail: 0xbc2d0601
frmt: 0x02 chkval: 0x931a type: 0x06=trans data
Block header dump: 0x01000095
Object id on Block? Y
seg/obj: 0x123d7 csc: 0x00.13bbc9 itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1000090 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0007.00a.0000030f 0x00c000e3.00d3.2c C--- 0 scn 0x0000.0013baa2
0x02 0x0006.01e.00000398 0x00c01f5c.0173.07 ---- 3 fsc 0x0000.00000000
xid=0x0006.01e.00000398的事务lck=3
数据块的锁定信息仍然存在:
block_row_dump:
tab 0, row 0, @0x1c88
tl: 39 fb: --H-FL-- lb: 0x2 cc: 8
col 0: [ 3] c2 4a 46
col 1: [ 5] 53 4d 49 54 48
col 2: [ 5] 43 4c 45 52 4b
col 3: [ 3] c2 50 03
col 4: [ 7] 77 b4 0c 11 01 01 01
col 5: [ 3] c2 14 64
col 6: *NULL*
col 7: [ 2] c1 15
tab 0, row 1, @0x1caf
tl: 44 fb: --H-FL-- lb: 0x2 cc: 8
col 0: [ 3] c2 4b 64
col 1: [ 5] 41 4c 4c 45 4e
col 2: [ 8] 53 41 4c 45 53 4d 41 4e
col 3: [ 3] c2 4d 63
col 4: [ 7] 77 b5 02 14 01 01 01
col 5: [ 3] c2 14 63
col 6: [ 2] c2 04
col 7: [ 2] c1 1f
tab 0, row 2, @0x1e00
tl: 43 fb: --H-FL-- lb: 0x2 cc: 8
col 0: [ 3] c2 4c 16
col 1: [ 4] 57 41 52 44
col 2: [ 8] 53 41 4c 45 53 4d 41 4e
col 3: [ 3] c2 4d 63
col 4: [ 7] 77 b5 02 16 01 01 01
col 5: [ 3] c2 14 62
col 6: [ 2] c2 06
col 7: [ 2] c1 1f
再来看回滚段的信息:
********************************************************************************
Undo Segment: _SYSSMU6_2897970769$ (6)
********************************************************************************
Version: 0x01
FREE BLOCK POOL::
uba: 0x00c01f5c.0173.07 ext: 0xd spc: 0x1cfc
uba: 0x00000000.0173.02 ext: 0xd spc: 0x1f06
uba: 0x00c01f59.0173.23 ext: 0xd spc: 0xc58
uba: 0x00000000.0095.01 ext: 0x10 spc: 0x1ed0
uba: 0x00000000.0095.01 ext: 0x10 spc: 0x1ed0
TRN TBL::
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
------------------------------------------------------------------------------------------------
0x1e 9 0x00 0x0398 0xffff 0x0000.0013bc55 0x00c01f5c 0x0000.000.00000000 0x00000001 0x00000000 1559115495
undo块
********************************************************************************
UNDO BLK:
xid: 0x0006.014.00000399 seq: 0x173 cnt: 0x1e irb: 0x1e icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f8c 0x02 0x1f18 0x03 0x1ebc 0x04 0x1e68 0x05 0x1dcc
0x06 0x1d74 0x07 0x1d1c 0x08 0x1c94 0x09 0x1c30 0x0a 0x1bdc
0x0b 0x1b70 0x0c 0x1aec 0x0d 0x1a7c 0x0e 0x19fc 0x0f 0x1974
0x10 0x18e8 0x11 0x1880 0x12 0x1798 0x13 0x1730 0x14 0x16d8
0x15 0x1650 0x16 0x15d4 0x17 0x156c 0x18 0x14e4 0x19 0x144c
0x1a 0x13e4 0x1b 0x1308 0x1c 0x1220 0x1d 0x11b8 0x1e 0x1160
事务提交,事务表已经释放。如果此时查询scott.emp表,数据库将产生延迟块清除:
SYS@ prod>set autotrace on
SYS@ prod>select * from scott.emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 1980-12-17 00:00:00 1999 20
7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1998 300 30
7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1997 500 30
7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30
7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30
7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10
7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10
7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30
7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30
7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20
7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10
12 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 468 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 12 | 468 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
9 consistent gets
6 physical reads
116 redo size
1382 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
SYS@ prod>select * from scott.emp;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
7369 SMITH CLERK 7902 1980-12-17 00:00:00 1999 20
7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1998 300 30
7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1997 500 30
7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30
7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30
7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10
7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10
7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30
7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30
7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20
7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10
12 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 12 | 468 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMP | 12 | 468 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
1382 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
注意,在此查询是产生了物理读取和redo,这个redo就是因为延迟块清除导致的,再次查询则不会
产生redo了。
再次转储一下该数据块和回滚段:
SSYS@ prod> alter system dump datafile 4 block 149;
System altered.
SYS@ prod> alter system dump undo header '_SYSSMU1_592353410$';
System altered.
SYS@ prod> alter system dump datafile 3 block 8028;
System altered.
SYS@ prod>oradebug setmypid
Statement processed.
SYS@ prod>oradebug tracefile_name
/u01/diag/rdbms/prod/prod/trace/prod_ora_3775.trc
查看跟踪文件,看到此时ITL事务信息已经清除,但是注意,这里的xid和uba信息仍然存在:
Block header dump: 0x01000095
Object id on Block? Y
seg/obj: 0x123d7 csc: 0x00.13bfab itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1000090 ver: 0x01 opc: 0
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0007.00a.0000030f 0x00c000e3.00d3.2c C--- 0 scn 0x0000.0013baa2
0x02 0x0006.01e.00000398 0x00c01f5c.0173.07 C--- 0 scn 0x0000.0013bc55
数据块块的锁定位也已经清除了:
block_row_dump:
tab 0, row 0, @0x1c88
tl: 39 fb: --H-FL-- lb: 0x0 cc: 8
col 0: [ 3] c2 4a 46
col 1: [ 5] 53 4d 49 54 48
col 2: [ 5] 43 4c 45 52 4b
col 3: [ 3] c2 50 03
col 4: [ 7] 77 b4 0c 11 01 01 01
col 5: [ 3] c2 14 64
col 6: *NULL*
col 7: [ 2] c1 15
tab 0, row 1, @0x1caf
tl: 44 fb: --H-FL-- lb: 0x0 cc: 8
col 0: [ 3] c2 4b 64
col 1: [ 5] 41 4c 4c 45 4e
col 2: [ 8] 53 41 4c 45 53 4d 41 4e
col 3: [ 3] c2 4d 63
col 4: [ 7] 77 b5 02 14 01 01 01
col 5: [ 3] c2 14 63
col 6: [ 2] c2 04
col 7: [ 2] c1 1f
tab 0, row 2, @0x1e00
tl: 43 fb: --H-FL-- lb: 0x0 cc: 8
col 0: [ 3] c2 4c 16
col 1: [ 4] 57 41 52 44
col 2: [ 8] 53 41 4c 45 53 4d 41 4e
col 3: [ 3] c2 4d 63
col 4: [ 7] 77 b5 02 16 01 01 01
col 5: [ 3] c2 14 62
col 6: [ 2] c2 06
col 7: [ 2] c1 1f
提交之后的undo信息
当提交事务之后,回滚段事务表标记该事务为非活动,继续再来看一下回滚段数据块的信息,
看到这里的irb指向了0x3d,此前的事务已经不可回滚
********************************************************************************
UNDO BLK:
xid: 0x0006.004.00000399 seq: 0x173 cnt: 0x3d irb: 0x3d icl: 0x0 flg: 0x0000
看一下偏移量列表也已经新增了一条信息0x3d 0x01c8
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1f8c 0x02 0x1f18 0x03 0x1ebc 0x04 0x1e68 0x05 0x1dcc
0x06 0x1d74 0x07 0x1d1c 0x08 0x1c94 0x09 0x1c30 0x0a 0x1bdc
0x0b 0x1b70 0x0c 0x1aec 0x0d 0x1a7c 0x0e 0x19fc 0x0f 0x1974
0x10 0x18e8 0x11 0x1880 0x12 0x1798 0x13 0x1730 0x14 0x16d8
0x15 0x1650 0x16 0x15d4 0x17 0x156c 0x18 0x14e4 0x19 0x144c
0x1a 0x13e4 0x1b 0x1308 0x1c 0x1220 0x1d 0x11b8 0x1e 0x1160
0x1f 0x10b0 0x20 0x1000 0x21 0x0f94 0x22 0x0f24 0x23 0x0eb8
0x24 0x0e4c 0x25 0x0d9c 0x26 0x0cec 0x27 0x0c80 0x28 0x0c14
0x29 0x0ba8 0x2a 0x0b3c 0x2b 0x0a8c 0x2c 0x0a20 0x2d 0x09b4
0x2e 0x0904 0x2f 0x087c 0x30 0x0820 0x31 0x0770 0x32 0x06c0
0x33 0x0610 0x34 0x05a4 0x35 0x0538 0x36 0x04cc 0x37 0x0460
0x38 0x03f4 0x39 0x0388 0x3a 0x031c 0x3b 0x02b0 0x3c 0x0234
0x3d 0x01c8
再看前镜像的信息,仍然存在。
虽然这个事务已经提交了,不可以回滚了,但是在覆盖之前,这个前镜像信息仍然存在,通过某些手段,还是可以获得这个信息的.比如回闪查询