TPC-C
malcolm, September 29, 2003 - 10:48 am UTC
> We run our TPC-C's in serializable (it is a requirement
> of that benchmark).
But I thought Oracle (and possibly mainframe DB2) is the only database to support serializable isolation level. I didn't think that any other databases had the mutli-version read consistancy which is required. So how do they publish TPC-C results without meeting the requirements? Or am I a victim of Oracle propaganda? ;-)
September 29, 2003 - 12:48 pm UTC
serializable does not require multi-versioning (and DB2 surely doesn't do multi-versioning).
serializable can be accomplished via read locks -- at the cost of concurrency.
Just to clarify
A reader, September 29, 2003 - 2:57 pm UTC
Multi-versioning can not help in the support of the serializable isolation level. So mayby you are a victim of Oracle propaganda :)
September 29, 2003 - 4:32 pm UTC
umm, our serializable model is entirely built on the premise of multi-versioning actually.
Oracles approach to serializable transactions is multi-versioning.
The others use locks.
no victims here...
RE: So mayby you are a victim of Oracle propaganda
Mark A. Williams, September 29, 2003 - 3:59 pm UTC
> So mayby you are a victim of Oracle propaganda
In what way? What elaborations can you make in regard to that statement?
- Mark
Victim of some kind...
malcolm, September 30, 2003 - 5:13 am UTC
Well, perhaps I'm a victim of some kind... I've been working solely with Oracle for so long that I've completely forgotten about the existence of 'read locks'. :-)
first transaction in Oracle
vkoul, February 15, 2004 - 3:10 am UTC
Sorry Tom, I was waiting for putting a question, but weeks after weeks I was not able to, so I am putting this question.
On Database startup what is the first transaction Oracle performs (I was asked to answer this question in an interview)
February 15, 2004 - 11:45 am UTC
trick question, one that is not answerable by the interviewers themselves unless they wrote the Oracle database itself (doubtful, no?)
I'd ask them, hmm, you mean transcations are happening when I do a startup nomount? Amazing - i did not know they could do that without any sort of redo logs, datafiles, whatever.
maybe they meant, "what does oracle sort of do upon startup", that would be a fair question -- one that most experienced DBA's should be able to answer in general. Things like "well, it use the init file to find the control files. it would use the control files to find the data/online redo log files. It would then see if crash recovery needed to be done. If so, it would use the redo to replay the transactions that were not yet recorded to the datafiles. It would then use the UNDO information to rollback transactions that were in flight when the db crashed and then ....blah blah blah...."
First Transaction In Oracle
VKOUL, February 17, 2004 - 1:22 pm UTC
Thanks Tom, You are the best ...
Switching isolation_level within a session.
Mathew Butler, March 27, 2006 - 7:39 am UTC
9.2.0.5 Win2K
I'm just looking at some reporting requirements which necessitate taking a consistent copy of data from various tables. Basically, we pull a consistent set of data out of one schema, load it with a "tag" into another schema ( for auditing purposes ) and then report on it.
My plan was to:
alter session set isolation_level = serializable
/
<collect consistent copy of data>
commit
/
alter session set isolation_level = read committed
/
<continue with remaining processing>
However, it doesn't look to me like this can be achieved without reconnecting to the DB after the commit. See below:
SQL>
SQL> alter session set isolation_level = serializable
2 /
Session altered
SQL> commit
2 /
Commit complete
SQL> alter session set isolation_level = read committed
2 /
alter session set isolation_level = read committed
ORA-01453: SET TRANSACTION must be first statement of transaction
Am I missing something, or is re-connecting the only way to avoid the ORA-01453?
Best Regards.
March 27, 2006 - 10:06 am UTC
ops$tkyte@ORA10GR2> alter session set isolation_level = serializable;
Session altered.
ops$tkyte@ORA10GR2> commit;
Commit complete.
ops$tkyte@ORA10GR2> alter session set isolation_level = read committed;
Session altered.
I cannot reproduce your findings at all. In any release.
Peculiar
Mathew Butler, March 27, 2006 - 11:31 am UTC
Note to self: Always test in SQLPlus.
I was using the command window of PLSQL/Developer. I agree with your results using SQLPlus.
Mat.
March 27, 2006 - 3:14 pm UTC
I betcha plsql developer "optimized" away the commit on you ;)
Possible problem with serializable transactions....
Mathew Butler, July 03, 2006 - 7:03 am UTC
Any idea what is happening here?
I'm seeing some peculiar behaviour with serializable transactions. Test case is below - I think I am doing everything correctly. There are two tests, run as one script ( with a connect at the beginning of each test ). Both are logically equivalent ( one uses a single anonymous block to add some sata, the other uses two anonymous blocks.- no other differences )
I can see;
1) In test 1 more data being returned that was created from another transaction, after latreing to serializable transactions.
2) In test 2 an ORA-01877 for data that I believe I should be able to update.
I've highlighted the sections of the test below that are of interest.
Is this expected behaviourm, or am I missing something?
SQL*Plus: Release 9.2.0.5.0 - Production on Mon Jul 3 11:49:14 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
SQL> connect test/test@mig1
Connected.
SQL>
SQL> /* setup */
SQL> drop table t;
Table dropped.
SQL> create table t (col1 number);
Table created.
SQL> create or replace procedure set_isolation_level_s is
2 begin
3 -- commit as isolation_level must be executed at start of transaction
4 execute immediate 'alter session set isolation_level = serializable';
5 end;
6 /
Procedure created.
SQL> create or replace procedure set_isolation_level_rc is
2 begin
3 execute immediate 'alter session set isolation_level = read committed';
4 end;
5 /
Procedure created.
SQL> create or replace procedure add_data_to_t ( p_val t.col1%type ) is
2 pragma autonomous_transaction;
3 begin
4 insert into t values (p_val);
5 commit;
6 end;
7 /
Procedure created.
SQL> /* end setup */
SQL> /* Test 1 */
SQL> begin
2 add_data_to_t(1);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> insert into t values(11);
1 row created.
SQL> commit;
Commit complete.
SQL> begin
2 set_isolation_level_s;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- add some more data
SQL> begin
2 add_data_to_t(2);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> begin
2 add_data_to_t(3);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- check data - should only be able to see 1, 11
SQL> select * from t;
<b> COL1
----------
1
11
2
3</b>
SQL> -- update data created by other session prior to serializable change
SQL> update t set col1 = 5 where col1 = 1;
1 row updated.
SQL> /* Test 2*/
SQL> connect test/test@mig1
Connected.
SQL> delete from t;
4 rows deleted.
SQL> commit;
Commit complete.
SQL>
SQL> -- add some data in seperate transaction
SQL> begin
2 add_data_to_t(1);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> insert into t values(11);
1 row created.
SQL> -- set the isolation level so will report on this point in time
SQL> commit;
Commit complete.
SQL> begin
2 set_isolation_level_s;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- check data
SQL> select * from t;
COL1
----------
1
11
SQL> -- add some more data
SQL> begin
2 add_data_to_t(2);
3 add_data_to_t(3);
4 end;
5 /
PL/SQL procedure successfully completed.
SQL> -- check data
SQL> select * from t;
<b> COL1
----------
1
11</b>
SQL> -- update data created by other session
SQL> update t set col1 = 5 where col1 = 1;
update t set col1 = 5 where col1 = 1
*
ERROR at line 1:
<b>ORA-08177: can't serialize access for this transaction</b>
Mathew Butler, July 10, 2006 - 7:38 am UTC
Many thanks for the response.
* From the response I understand that the SCN used to define the start of the transaction is stored in the block header. As such I should find that the ORA-01877 was raised in my test when data from both sessions was created on the same block - I've shown this in the test below. <b>Is my understanding correct?</b>
* What about the unexpected additional rows that are returned in test 1?? ( I've bolded then in the re-test below). <b>Is this the same effect?</b>
* <b>Is there a reliable means of achieving a consistent read throughout a transaction - does flashback query with tables re-built with rowdependencies give me this?
I'm trying to satisfy some peculiar reporting requirements and need to obtain a consistent view of the data across the transaction with minimal extra code ie: handling of unexpected ORA-01877 and possibly also allow some updates.</b>
Here is the test including block information:
SQL> connect test/test@mig1
Connected.
SQL> /* setup */
SQL> drop table t;
Table dropped.
SQL>
SQL> create table t (col1 number);
Table created.
SQL>
SQL> create or replace procedure set_isolation_level_s is
2 begin
3 -- commit as isolation_level must be executed at start of transaction
4 execute immediate 'alter session set isolation_level = serializable';
5 end;
6 /
Procedure created.
SQL> create or replace procedure set_isolation_level_rc is
2 begin
3 execute immediate 'alter session set isolation_level = read committed';
4 end;
5 /
Procedure created.
SQL> create or replace procedure add_data_to_t ( p_val t.col1%type ) is
2 pragma autonomous_transaction;
3 begin
4 insert into t values (p_val);
5 commit;
6 end;
7 /
Procedure created.
SQL> /* end setup */
SQL> /* Test 1 */
SQL> begin
2 add_data_to_t(1);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> insert into t values(11);
1 row created.
SQL> commit;
Commit complete.
SQL> begin
2 set_isolation_level_s;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- add some more data
SQL> begin
2 add_data_to_t(2);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> begin
2 add_data_to_t(3);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- check data - should only be able to see 1, 11
SQL> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 32
11 32
<b> 2 32
3 32</b>
SQL> -- update data created by other session prior to serializable change
SQL> update t set col1 = 5 where col1 = 1;
1 row updated.
SQL>
SQL> /* Test 2*/
SQL> connect test/test@mig1
Connected.
SQL> delete from t;
4 rows deleted.
SQL> commit;
Commit complete.
SQL> -- add some data in seperate transaction
SQL> begin
2 add_data_to_t(1);
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> insert into t values(11);
1 row created.
SQL> -- set the isolation level so will report on this point in time
SQL> commit;
Commit complete.
SQL> begin
2 set_isolation_level_s;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> -- check data
SQL> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 32
11 32
SQL> -- add some more data
SQL> begin
2 add_data_to_t(2);
3 add_data_to_t(3);
4 end;
5 /
PL/SQL procedure successfully completed.
SQL> -- check data
SQL> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 32
11 32
SQL> -- update data created by other session
SQL> update t set col1 = 5 where col1 = 1;
update t set col1 = 5 where col1 = 1
*
ERROR at line 1:
ORA-08177: can't serialize access for this transaction
July 10, 2006 - 8:42 am UTC
8177's can be thrown when they technically need not be, it is an implementation restriction.
flashback query will give you consistent read throughout the transaction - across transactions in fact.
the "extra rows" are not "extra rows", you set your sessions default isolation level to "serializable", that kicks in at the first statement of a new transaction, you did:
o set default isolation to serializable
o run transaction and commit (you have not yet started a transaction for yourself)
o run transaction and commit (ditto)
o started your "transaction" by running the first statement, the select, it
is serializable "as of now"
eg:
ops$tkyte@ORA10GR2> exec set_isolation_level_s;
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> exec add_data_to_t(2);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> exec add_data_to_t(3);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
<b>this is the beginning of YOUR 'transaction'</b>
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 80
11 80
2 80
3 80
ops$tkyte@ORA10GR2> exec add_data_to_t(4);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 80
11 80
2 80
3 80
<b>See, you still only see 4 rows, but commit:</b>
ops$tkyte@ORA10GR2> commit;
Commit complete.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 80
11 80
2 80
3 80
4 80
<b>and you see them all, now if you change:</b>
ops$tkyte@ORA10GR2> create or replace procedure set_isolation_level_s is
2 begin
3 -- commit as isolation_level must be executed at start of transaction
4 execute immediate 'alter session set isolation_level = serializable';
5 execute immediate 'set transaction isolation level serializable';
6 end;
7 /
<b>to both change the DEFAULT ISOLATION LEVEL as well as BEGIN A TRANSACTION... then:</b>
ops$tkyte@ORA10GR2> exec set_isolation_level_s;
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> exec add_data_to_t(2);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> exec add_data_to_t(3);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 88
11 88
ops$tkyte@ORA10GR2> exec add_data_to_t(4);
PL/SQL procedure successfully completed.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 88
11 88
ops$tkyte@ORA10GR2> commit;
Commit complete.
ops$tkyte@ORA10GR2> select col1,dbms_rowid.rowid_block_number(rowid) from t;
COL1 DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
1 88
11 88
2 88
3 88
4 88
<b>you do not 'see the extra rows', since your plsql call to set the isolation level started a transaction itself</b>
I see!
Mathew Butler, July 10, 2006 - 9:18 am UTC
Very happy with this explanation. Thanks for the nod about the "alter session" and "set transaction" I had previously understood these to do the same thing.
This next question may be important to the implementation of this report:
Under what circumstances can 8177's can be thrown when they technically need not be?
Briefly, the report may also need to insert/update a few rows of data. It is extremely likely that these rows may be on the same block as rows previously inserted by other processes. My current understanding is that an 8177 may be raised in this case. So some concern here...
...obviously if one is raised I can catch it, but would probably need an autonomous transaction "fudge" in order to make the changes. This messes with my transaction integrity on failure.
Do I have good reason for my concern?
July 10, 2006 - 9:24 am UTC
there is no real documentation on when they will be thrown when not needed, just understand they will be and the application needs to be aware of that.
serializable is designed for extremely short duration OLTP situations. It is not something to be considered for long running reports (read only OR flashback query is)
Further info request...
Mathew Butler, July 10, 2006 - 9:45 am UTC
>>there is no real documentation on when they will be
>>thrown when not needed, just understand they will be and
>>the application needs to be aware of that.
OK, "maybe fine" - but again, what does one do if one is encountered when not needed?
>>serializable is designed for extremely short duration
>>OLTP situations. It is not something to be considered
>>for long running reports (read only OR flashback query
>>is)
Can you explain why not intended for long transactions? - I think my requirement may be a "special case".
The reporting process is to do the following:
- run as a single process ( no other concurrent reporting processes..currently )
- pull a consistent snapshot of data from schema1 and load into schema2
- store some data in schema1 about the fact that this process has occurred ( one insert and one update )
- once data successfully transferred then commit
- proceed to generate several reports on copy of data in schema2 in "read committed" mode.
The whole process is intended to run in < 1 hour.
There will be minimal concurrent updates of schema1 data during the copy - maybe 1 or two versions of each copied block
I'm thinking about this in detail as I really think that flashback query is the "best" answer however, I've been asked to come up with a solution that minimises code change ( this is an enhancement to an existing report that currently uses user defined application locks to serialise access during the copy - looking for a solution to allow concurrent access )
July 10, 2006 - 9:53 am UTC
one retries the transaction or one fails the transaction.
eg: what does one do when one recieves ora-60, deadlock detected?
They (serializable transactions) are not designed, intended, useful, workable for long running transactions. "by definition", that is just a fact.
I can't drop this one, just yet...
Mathew Butler, July 10, 2006 - 10:04 am UTC
>one retries the transaction or one fails the transaction.
>eg: what does one do when one recieves ora-60, deadlock
>detected?
Accepted - and also a good reason not to use serializable for "long" transactions as "long" tx => "long" time to rollback and re-try. Will have to test to see how much time this rollback/re-try might take and identify whether this is acceptable. If not acceptable then flashback query will look more promising.
Thanks again.
Isolation Level Read Only
Mark, July 10, 2006 - 10:43 am UTC
Hi Tom,
Regarding a high-load, Read-Only reporting database, is it advantageous (performance-wise) to set the isolation level = read only as opposed to the default value?
8i Standard 8.1.7.4 (freakin' dinosaur)
Regards,
Mark
July 10, 2006 - 12:37 pm UTC
nope, it would either have no effect or cause extra work (because unless the database is opened read only, there is not any such thing as a read only database)
likely the answer is "it would have no effect".
read only would simply freeze the SCN at the beginning of the transaction - the same amount of work would be done to put a block back the way it was as of that SCN as it would to put it back the way it was if the SCN was set when the statement is opened in your case: none, the block isn't being modified.
Isolation Level
V, December 04, 2006 - 2:30 pm UTC
Tom, I have the following which I have inherited:
create or replace PROCEDURE ins_suggestion
(
isubj IN VARCHAR2,
iattach_flg IN CHAR,
iqual_flag IN CHAR,
isfty_flag IN CHAR,
icost_flag IN CHAR,
ifunction IN VARCHAR2,
ilob_name IN VARCHAR2,
ibenefit IN VARCHAR,
icompetitive_flag IN CHAR,
isite_name IN VARCHAR,
icur_methprob IN VARCHAR,
isubmit IN VARCHAR,
iprop_methprob IN VARCHAR
)
IS
cur_esn_num VARCHAR2(11);
isite_id VARCHAR2(3);
icoor_emp_num VARCHAR2(10);
ianly_emp_num VARCHAR2(10);
isug_stat VARCHAR2(2);
iemp_name VARCHAR2(50);
iemp_dept VARCHAR2(10);
iemp_phone VARCHAR2(14);
l_curr_yr char(4);
p_curr_yr char(4);
l_dummy number;
BEGIN
--
--
select curr_yr into l_curr_yr from esn_seq_num;
select to_char(sysdate,'YYYY') INTO p_curr_yr FROM DUAL;
IF l_curr_yr <> p_curr_yr THEN
UPDATE esn_seq_num set curr_yr = to_char(sysdate,'YYYY');
COMMIT;
EXECUTE IMMEDIATE 'SELECT esn.nextval from dual' INTO l_dummy;
EXECUTE IMMEDIATE 'alter sequence esn increment by -'||(l_dummy)||' minvalue 0';
EXECUTE IMMEDIATE 'SELECT esn.nextval from dual' INTO l_dummy;
EXECUTE IMMEDIATE 'alter sequence esn increment by 1';
END IF;
SELECT esn.nextval INTO cur_esn_num FROM DUAL;
select
case when length(cur_esn_num)=4 then to_char(sysdate,'MMYY')||cur_esn_num
when length(cur_esn_num)=3 then to_char(sysdate,'MMYY')||'0'||cur_esn_num -- 100 0100
when length(cur_esn_num)=2 then to_char(sysdate,'MMYY')||'00'||cur_esn_num -- 10 0010
when length(cur_esn_num)=1 then to_char(sysdate,'MMYY')||'000'||cur_esn_num -- 1 0001
--else 0
end
INTO cur_esn_num from dual;
-- Removed in support if new ESN FORMAT MMYY####
--SELECT last_esn + 1 INTO cur_esn_num FROM esn_seq_num;
UPDATE esn_seq_num SET last_esn = cur_esn_num;
...
...
INSERT into table
commit;
EXCEPTION
WHEN dup_val_on_index THEN
dbms_output.put_line('Duplicate ' ||
SQLERRM);
RAISE;
WHEN OTHERS THEN
dbms_output.put_line('Error: ' ||
SQLERRM);
RAISE;
END ins_suggestion;
As you notice, I am resetting the sequence in the begining of the year. I believe I need to set some isolation level here in case the insert fails but am not sure.
December 05, 2006 - 9:35 pm UTC
sorry, no clue what you are really doing here. All I see is a bunch of code which may or may not accomplish whatever goal you may or may not have in mind.
What I don't see is "a goal"
no clue why you would want to reset something at the beginning of the year - or how you can tell "we are the first of the year" or whatever.
Goal
V, December 06, 2006 - 9:46 am UTC
The goal here is to have a unique # to identify a row with the format of: MMYY#### i.e. 12060001 When the Year changes the # should be 01070001 . This is a app that was inherited and adding or removing attributes is not possible because of tight time constraints.
I was attempting to assign the # in the already existing SP. Prior to the change, the # was assigned like:
SELECT last_esn + 1 INTO cur_esn_num FROM esn_seq_num;
UPDATE esn_seq_num SET last_esn = cur_esn_num;
December 07, 2006 - 8:36 am UTC
why
how do you KNOW you are the first record of the YEAR???????
every time you insert, you'd have to ask yourself that question "am I the first??"
and in order to answer that - you have to obviously SERIALIZE ALL INSERTS.
even in AUGUST - because it might be AUGUST when you first insert.
Now, ask yourself - do you really really want to do that??????
Isolcation NOT for Object's Existance ?
Yogesh Purabiya, April 14, 2007 - 3:16 am UTC
(1) What is the difference between
set transaction isolation level serializable;
AND
alter session set isolation_level = serializable;
(2) Following is the spool output of a session.
Statement "select * from x;" gave error first time, since there was no such table.
Once created (in a different session), it gave no errors.
So, is the existance of an object not marked with SCN ?
12:07:01 stores1@ >c/set /
1* alter session set isolation_level = serializable
12:07:06 stores1@ >/
Session altered.
real: 15
12:07:08 stores1@ >select * from x;
select * from x
*
ERROR at line 1:
ORA-00942: table or view does not exist
real: 0
12:07:12 stores1@ >/
no rows selected
real: 15
12:07:23 stores1@ >
12:07:47 stores1@ >spo off
April 16, 2007 - 10:35 am UTC
1) transaction vs session
single transaction till commit, versus rest of session until exit.
ops$tkyte%ORA10GR2> create table t ( x int );
Table created.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> insert into t values ( 1 );
1 row created.
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> set transaction isolation level serializable;
Transaction set.
ops$tkyte%ORA10GR2> select * from t;
X
----------
1
ops$tkyte%ORA10GR2> declare
2 pragma autonomous_transaction;
3 begin
4 update t set x = x+1;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> select * from t;
X
----------
1
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2> select * from t;
X
----------
2
ops$tkyte%ORA10GR2> declare
2 pragma autonomous_transaction;
3 begin
4 update t set x = x+1;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> select * from t;
X
----------
3
<b>we are not serializable anymore - we see the update.....</b>
ops$tkyte%ORA10GR2> alter session set isolation_level = serializable;
Session altered.
ops$tkyte%ORA10GR2> select * from t;
X
----------
3
ops$tkyte%ORA10GR2> declare
2 pragma autonomous_transaction;
3 begin
4 update t set x = x+1;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> select * from t;
X
----------
3
ops$tkyte%ORA10GR2> commit;
Commit complete.
ops$tkyte%ORA10GR2> select * from t;
X
----------
4
ops$tkyte%ORA10GR2> declare
2 pragma autonomous_transaction;
3 begin
4 update t set x = x+1;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> select * from t;
X
----------
4
<b>we are serializable even after the commit - session....</b>
2) I see NO CONFLICT with serializable here.
Isolation with DDL
Yogesh Purabiya, April 17, 2007 - 11:35 pm UTC
Thanks a lot, as usual.
It is really a nice and clear reply.
ORA-08177 errors
Doug Floyd, November 28, 2007 - 9:53 am UTC
Is there any possible way that ORA-08177 could occur unless the isolation level is set to something other than the default read committed?
The reason I ask is one of our databases has been receiving this error recently when running an update statement and I'm trying to prove to our developers that it is happening because the application they are using (SAS) must be changing the isolation level. Is there a way I can determine what isolation level they are using when the error occurs (through a v$ view or otherwise)?
Thanks!
November 28, 2007 - 11:07 pm UTC
$ oerr ora 8177
08177, 00000, "can't serialize access for this transaction"
// *Cause: Encountered data changed by an operation that occurred after
// the start of this serializable transaction.
// *Action: In read/write transactions, retry the intended operation or
// transaction.
transaction is serializable - I'm not aware of any other circumstance you would get that.
trace a SAS session and see if they issue this.
what would happened
A reader, January 16, 2009 - 1:00 am UTC
Tom,
I have two session running in this fashion, assume table t have 1000 records.
Time Session 1 Session 2
0 declare x number;
1 begin
2 select count(*) into x
from t; begin
3 --do another work delete t;
4 --do another work commit;
5 --do another work end;
6 select count(*) into x
from t;
7 end;
For the first select on t at session 1, Oracle returning 1000 rows as I expected, but for the second select what the number will be returned ? Zero or 1000, Tom ?
Thanks.
January 16, 2009 - 6:16 pm UTC
depends on the isolation level.
Using standard read committed - the counts at time t2 and t6 would be different since the delete and commit that happened at times t3 and t4 would be visible to t6.
Using serializable or read only transactions, t2 and t6 would report the same count.
The Concepts Manual 11.2 on serializable
Milan, April 27, 2011 - 8:23 am UTC
Hi Tom.
The Concepts manual still insists that there is a performance tradeoff between serializable and read committed:
http://download.oracle.com/docs/cd/E11882_01/server.112/e16508/consist.htm#i13945 In particular:
<quote>
Complete isolation of concurrently running transactions could mean that one transaction cannot perform an insertion into a table being queried by another transaction.
</quote>
I just can't think of such scenario.
Readers should NEVER block writers, right?
If the above excerpt from the concepts manual is wrong, can you please use your authority to make them rectify the misleading statements.
Thank you for all the things that I learned from you.
April 27, 2011 - 9:13 am UTC
Sorry, I can see how that would be confusing. What we were trying to say is more along the lines of:
To describe consistent transaction behavior when transactions run concurrently, database researchers have defined a transaction isolation model called serializability. A serializable transaction operates in an environment that makes it appear as if no other users were modifying data in the database.
While this degree of isolation between transactions is generally desirable, running many applications in serial would seriously compromise application throughput. Complete isolation of concurrently running transactions would mean that one transaction cannot perform an insert into a table being queried by another transaction. In short, real-world considerations usually require a compromise between perfect transaction isolation and performance.
Oracle Database maintains data consistency by using a multiversion consistency model and various types of locks and transactions. In this way, the database can present a view of data to multiple concurrent users, with each view consistent to a point in time. Because different versions of data blocks can exist simultaneously, transactions can read the version of data committed at the point in time required by a query and return results that are consistent to a single point in time.
We were trying to convey that whilst serializable gives the appearance of "single user", it does so (in Oracle) in a highly concurrent fashion.
ioslation level and multi-version
A reader, July 04, 2012 - 11:21 pm UTC
Hi Tom,
In your book 'expert-oracle-database-architecture-2ND' page 247, you talking about the multi-version and isolation level.
Table 7-3. ACCOUNTS Table During Modifications
Row Account Number Account Balance Locked?
1 123 ($500.00) changed to $100.00 X
2 456 $240.25 --
... ... ... --
342,023 987 ($100.00) changed to $500.00 X
select sum(account_balance) from accounts;
I have a question that given the default behaviour is read committed in oracle.
Suppose the sum has go over row 1 which means it already take $500,
and then just before it hit the last row(342,023), the other transaction committed.
So 342,023 is 500 rather than 100 now, but row 1 already summed, will it be a issue that
400 was calculated twice?
July 05, 2012 - 8:31 am UTC
with multi-versioned READ CONSISTENCY - all of the blocks used by a statement are all as of the same point in time.
If the other session had committed, we would have noticed the timestamp of the last block read was newer than our query start time and we would have rolled back the modification to the point in time our query began.
Every block used by the query will be as of the same point in time. It will be read consistent. If a block is locked - we can read around the lock, if the block was modified - we roll back the changes so as to see what was committed in the database as of the time our query (or transaction in serializable) began