Oracle里未成功commit的数据我们也可能能看到
Posted: January 28, 2012 | Author: Cui Hua | Filed under: Oracle | 3 Comments »我们大家都知道的一个常识是——Oracle里未commit的数据除了当前session之外,其他session是看不到的。
我这里演示了一个有趣的例子,在这个例子里我们可以看到,Oracle里未成功commit的数据我们也可能能看到。
我同时启4个session。
先在session 1里创建一个表t1,插入一条数据但不commit:
Session 1:
Connected to Oracle Database
Connected as scott
SQL> create table t1(id number, name varchar2(10));
Table created
SQL> insert into t1 values(1,’CUIHUA’);
1 row inserted
SQL> select * from t1;
ID NAME
———- ———-
1 CUIHUA
此时跳到session 2,因session 1里刚插入的那条数据还未commit,所以这个时候session 2是看不到这条数据的:
Session 2:
SQL> select * from t1;
ID NAME
———- ———-
接着我们跳到session 3,把lgwr进程suspend住:
Session 3:
SQL> select spid from v$process where pname=’LGWR’;
SPID
————————
2316
SQL> oradebug setospid 2316
Oracle pid: 11, Windows thread id: 2316, image: ORACLE.EXE (LGWR)
SQL> oradebug suspend
已处理的语句
现在我们回到session 1,执行commit命令,因为lgwr进程已经被我们suspend住了,所以当前session 1里要执行的commit操作一定会被hang住:
Session1:
SQL> commit;
……这里hang住了
Oracle里commit操作的流程是这样的:
1、Oracle先去改这个transaction所对应的undo segment header中slot的状态;
2、改完状态后再flush log buffer;
现在我们把lgwr hold住了,所以上述步骤2 Oracle是没法做了,但步骤1还是可以做的。而只要步骤1做完了,其他的session就能看到这个transaction所做的改变了(通过ITL中记录的transaction id去check相应的undo segment header中slot的状态),也就是说对于其他session而言,这个transaction已经commit了,虽然这个transaction其实并没有成功commit。
好了,我们现在回到session 2,看一下我们现在能否看到刚才insert的那条记录:
Session 2:
SQL> select * from t1;
ID NAME
———- ———-
1 CUIHUA
从结果里可以看到,刚才看不到的那条记录现在我们已经能看到了,即session 1对于session2而言已经commit了,虽然session1的commit操作其实并没有成功的做完。
现在我们跳到session 4,执行shutdown abort:
Session 4:
SQL> shutdown abort
ORACLE 例程已经关闭。
然后我们再在session 4中执行startup,startup后我们从alert log里可以很明显的看到Oracle做了instance recovery:
Sat Jan 28 19:14:03 2012
alter database mount exclusive
Successful mount of redo thread 1, with mount id 4288810811
Database mounted in Exclusive Mode
Lost write protection disabled
Completed: alter database mount exclusive
alter database open
Beginning crash recovery of 1 threads
parallel recovery started with 2 processes
Started redo scan
Completed redo scan
read 918 KB redo, 126 data blocks need recovery
Started redo application at
Thread 1: logseq 44, block 77312
Recovery of Online Redo Log: Thread 1 Group 2 Seq 44 Reading mem 0
Mem# 0: C:\APP\CUIHUA\ORADATA\CUIHUA112\REDO02.LOG
Completed redo application of 0.52MB
Completed crash recovery at
Thread 1: logseq 44, block 79149, scn 1652578
126 data blocks read, 95 data blocks written, 918 redo k-bytes read
等待上述库成功startup后,我们再次回到session 1,看一下刚才我们已经commit的那条数据是否还在:
Session 1:
SQL> select * from t1;
ID NAME
———- ———-
从结果里可以看到,刚才我们insert且执行了commit操作的那条记录现在已经丢失了。
叫做“commit未成功完成”应该更确切一些。
请问:lgwr进程被我们suspend了,在shutdown abort的时候,log buffer中的内容是如何被写到redo log中的?因为根据alert文件中instance recovery过程,可知是应用redo的。
shutdown abort的时候log buffer里的内容没有被写到redo log中,这部分内容已经丢了,但这没有关系,因为这部分redo所对应的transaction一定是没有commit。