sqloracle-databasedata-consistency

Some confusion on the description of read consistency in Oracle


Below is a short brief of read consistency from oracle concepts guide.

What is a sql statement, just one sql? Or Pl/SQL or Store Procedure? Anyone can help provide me one opposite example which can indicates the un-consistency read?

 read consistency 
    A consistent view of data seen by a user. For example, in statement-level read
    consistency the set of data seen by a SQL statement remains constant throughout
    statement execution.

Solution

  • A "statement" in this context is one DML statement: a single SELECT, INSERT, UPDATE, DELETE, MERGE.

    It is not a PL/SQL block. Similarly, multiple executions of the same DML statement (say, within a PL/SQL loop) are separate "statements". If you need consistency over multiple statements or within a PL/SQL block, you can achieve that using SET TRANSACTION ISOLATION LEVEL SERIALIZABLE or SET TRANSACTION READ ONLY. Both introduce limitations.

    An opposite example of an inconsistent read would be as follows.

    Starting conditions: table BIG_TABLE has 10 million rows.

    User A at 10:00:

    SELECT COUNT(*) FROM BIG_TABLE;
    

    User B at 10:01:

    DELETE FROM BIG_TABLE WHERE ID >= 9000000;  -- delete the last million rows
    

    User B at 10:02:

    COMMIT;
    

    User A at 10:03: query completes:

    COUNT(*)
    --------------
    9309129
    

    That is wrong. User A should have either gotten 10 million rows or 9 million rows. At no point were there 9309129 committed rows in the table. What has happened is that user A had read 309,129 rows that user B was deleting before Oracle actually processed the deletion (or before the COMMIT). Then, after the user B delete/commit, user A's query stopped seeing the deleted rows and stopped counting them.

    This sort of problem is impossible in Oracle, thanks to its implementation of Multiversion Read Consistency.

    In Oracle, in the above situation, as it encountered blocks that had rows deleted (and committed) by User B, User A's query would have used the UNDO data reconstruct what those blocks looked like at 10:00 -- the time when user A's query started.

    That's basically it -- Oracle statements operate on the a version of the database as it existed as of a single point in time. This point in time is almost always the time when the statement started. There are some exception cases involving updates when that point in time will be moved to a point in time "mid statement". But it is always consistent as of one point in time or another.