本文将演示Oracle的多版本控制,以及串行化事务。
在session1中,建一个表,插入两条测试数据
SESSION1:
SCOTT@ prod> create table t ( x int ) ;
Table created.
SCOTT@ prod> insert into t values(1) ;
1 row created.
SCOTT@ prod> select * from t ;
X
----------
1
SCOTT@ prod> insert into t values ( 2 ) ;
1 row created.
未提交的情况下不能更改事务级别。
SCOTT@ prod> alter session set isolation_level = serializable ;
ERROR:
ORA-01453: SET TRANSACTION must be first statement of transaction
提交。
SCOTT@ prod> commit ;
Commit complete.
事务级别改为串行化。
串行化的事务级别下,其它事务提交的任何更改在这个事务里都是不可见的。因此需要数据在事务开始那一刻的版本,对于数据库系统来说也就是多版本控制来完成的事情。
SCOTT@ prod> alter session set isolation_level = serializable ;
Session altered.
SCOTT@ prod> set autotrace on statistics ;
SCOTT@ prod>
SCOTT@ prod> select * from t ;
X
----------
1
2
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
581 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
可以看到8 consistent gets。
在另一个Session中做10000次更新提交操作。
SESSION2:
SCOTT@ prod> begin
2 for i in 1 .. 10000
3 loop
4 update t set x = x + 1 ;
5 commit ;
6 end loop ;
7 end ;
8 /
PL/SQL procedure successfully completed.
Session1中再次查询
SESSION1:
SCOTT@ prod> select * from t ;
X
----------
1
2
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
10321 consistent gets
0 physical reads
0 redo size
581 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
可以看到10321 consistent gets , Oracle这了得到这个数据块需要大量读取UNDO。
再次执行
SCOTT@ prod> select * from t ;
X
----------
1
2
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
581 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
2 rows processed
可以看到8 consistent gets,说明这个旧版本也已经被缓存。
Data Buffer里面可能有一个数据块的多个不同版本。
通过这个查询可以看到:
SYS@ prod> select file# , block# , count(*) from v$bh
2 group by file# , block#
3 having count(*) > 3 order by 3 ;
FILE# BLOCK# COUNT(*)
---------- ---------- ----------
5 462570 4
1 3169 4
1 78616 5
1 83776 5
1 78621 6
5 462574 6
2 62125 6
7 rows selected.
可以看到有多个版本数大于3个的数据块。