Oracle-数据库的隔离级别测试

一、需求

只要看数据库原理方面的书籍,基本上都会讲到数据库隔离级别!那么具体有什么影响? 什么情况现象? 测试一波,实验再看。

看如下测试信息之前,先问几个问题:

1)隔离级别有哪些内容?

2)Oracle数据库支持什么隔离级别,默认使用什么隔离级别?

3)测试使用不同隔离级别出现什么现象?

二、理论学习

https://www.cnblogs.com/1-2-3/archive/2012/04/05/oracle-isolation-level-ora-08177.html
设置隔离级别使用 SET TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

未授权读取
   也称为读未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,
但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。 授权读取 也称为读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,
但是未提交的写事务将会禁止其他事务访问该行。 可重复读取(Repeatable Read) 可重复读取(Repeatable Read):禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。
读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。 序列化(Serializable) 序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。
如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。 脏读 不可重复读 幻读 Read uncommitted √ √ √ Read committed × √ √ Repeatable read × × √ Serializable × × × 测试!脏读 ! 不支持 可重复读取(Repeatable Read) 不支持 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SQL
> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED * ERROR at line 1: ORA-02179: valid options: ISOLATION LEVEL { SERIALIZABLE | READ COMMITTED }   - 幻读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,虽然查询条件相同,每次返回的结果集却不同。   - 脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。   - 不可重现的读取(nonrepeatable read):同一查询在同一事务中多次进行,在此期间,由于其他事务提交了对数据的修改或删除,每次返回不同的结果。 Oracle默认选择 Read committed,及读提交; 允许出现 nonrepeatable read,一个事务的过程中,读取的数据由于其它事务的改变修改,并且提交后,事务查询数据得到不同结果; 不允许出现脏读,无法读取其它事务没有commit造成的数据变动; 允许出现幻读,及同样的查询,如果其它事务修改数据并且commit,可以查询得到不同的结果!

三、实验测试

3.1 不可重复读

Oracle的序列化(serializable)隔离级别

1.不可重复读(删除或修改的记录)
SQL> select table_name,INI_TRANS from user_tables where table_name='PCT_T1';
TABLE_NAME                      INI_TRANS
------------------------------ ----------
PCT_T1                                  1
“Oracle Database stores control information in each data block to manage access by concurrent transactions. Therefore, 
if you set the transaction isolation level to SERIALIZABLE, then you must use the ALTER TABLE command to set INITRANS to at least 3.
This parameter causes Oracle Database to allocate sufficient storage in each block to record the history of recent transactions that accessed
the block. Higher values should be used for tables that will undergo many transactions updating the same blocks.” alter table pct_t1 initrans 50; session 1 SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SQL> select count(*) from pct_tt2; COUNT(*) ---------- 81 session 2 SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; session 1 delete pct_tt2 where id=166; SQL> commit; COUNT(*) ---------- 80 session 2 SQL> select count(*) from pct_tt2; COUNT(*) ---------- 81 SQL> delete pct_tt2 where id=165; delete pct_tt2 where id=165 * ERROR at line 1: ORA-08177: can't serialize access for this transaction SQL> delete pct_tt2 where id=167; SQL> commit; COUNT(*) ---------- 79 session 1 遇到报错会进行刷新 SQL> select count(*) from pct_tt2; COUNT(*) ---------- 79 但是session1 删除记录提交后,session 2查询并没有查询到这个记录! 不可重复读! 与默认不太一样

3.2 幻读

session1
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SQL> insert into test values(5);
1 row created.
SQL> select * from test;
        ID
----------
         1
         2
         5
         4

         
session2 
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SQL> insert into test values(6);
1 row created.
SQL> select * from test;
        ID
----------
         1
         2
         4
         6

session1
SQL> commit;
        ID
----------
         1
         2
         5
         4

session2
SQL> select * from test;
        ID
----------
         1
         2
         4
         6
?会话1 插入的数据会话2无法看到!  串行化事物隔离了,如果是默认情况oracle select 会根据current scn ,事务 commit scn < current scn的数据能看到事务中途其它事务造成的数据改变
原文地址:https://www.cnblogs.com/lvcha001/p/14362627.html