oracle数据隔离级别,oracle 数据库隔离级别

事务不同引发的状况:

脏读(Dirty reads)

一个事务读取另一个事务尚未提交的修改时,产生脏读

很多数据库允许脏读以避免排它锁的竞争。

不可重复读(Nonrepeatable reads)

同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。

幻读(Phantom reads)

同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。

数据库操作的隔离级别

未提交读(read uncommitted)

提交读(read committed)

重复读(repeatable read)

序列化(serializable)

oracle默认隔离级别

read committed (statement level serialization)

每一个语句,在语句开始时,会获取一个此刻的数据快照。

一个事务有多条语句,如果语句之间存在其它完成的事务,

这可能引起不可持续读和幻读。

新建一个测试表books:

name,code,price三个字段

添加两条测试数据

http___img0.tuicool.com_JjARJj.jpg

使用pl/sql和java程序模拟并发

不允许脏读测试:

程序段首先查询code是qqq的书的价格

//获取连接 省略

pstat = conn.prepareStatement("select price from books where code='qqq'");

rs = pstat.executeQuery();

while(rs.next()){

System.out.println("price:"+rs.getDouble(1));

}

close();

输出结果:price:15.0

然后pl/sql执行更新

update books set price=18 where code='qqq';

!pl/sql设置成手动更新,不自动更新

在执行上面java查询代码

输出仍是price:15.0,说明读不到pl/sql中未提交的执行结果,即不允许脏读

pl/sql 执行 commit;

在执行java查询:

输出结果:price:18.0

会有不可重复读何幻读的现象发生就不用测试了吧,

这两种现象都是针对提交后事物的读引起的,read commited隔离级别是允许对提交后

的事物进行读的。

隔离级别:重复读(repeatable read)

这个不允许脏读,不可重复读,但是会有幻读现象。

这个oracle不支持,不好测试。

理解的话就是如果一条查询语句查询的内容有其它事物正在更新的时候,这

查询处于等待状态,直到先前事物提交更新后,才会执行本条查询。也就是

查询的时候也会有锁,需要等待并发的事物释放锁。然后自己获取到锁,执行

自己事物。这样查询也加锁,并发性更低

select ... for update 就是这样可以避免不可重复读的发生

隔离级别:serializable

这个就更严格了,事物执行是一个一个的。一个事务中的语句共享同一个数据快照(在事务开始时存在的数据)。

是事物级别的,脏读,不可重复读,幻读根本就没有机会发生。

前面像read committed都是语句级别的,以语句为单元。

比如

read committed一个事物A有a(select),b(select),c(update)三条语句

当A事物执行a,b的时候,若有B事物执行更新操作,是有可能的

因为a,b是不加锁的

写个例子:

//获取连接和关闭连接代码 省略

//不自动提交

conn.setAutoCommit(false);

/**

* a 查询

*/

pstat = conn.prepareStatement("select price from books where code='qqq'");

rs = pstat.executeQuery();

while(rs.next()){

//输出 price:25.0

System.out.println("price:"+rs.getDouble(1));

}

close();

/**

* 暂停一会,用pl/sql执行B事务

* update books set price=15 where code='qqq';

* commit;

*/

Thread.sleep(10000);

/**

* 如果这里再执行a查询的话,和第一次查询结果就不一样,因为中间有B事务的提交更新

* 修改,这也是不可重复读

*/

//b 更新

pstat = conn.prepareStatement("update books set price=price+10 where code='qqq'");

pstat.executeUpdate();

close();

//c 查询

pstat = conn.prepareStatement("select price from books where code='qqq'");

rs = pstat.executeQuery();

while(rs.next()){

//输出 还是price:25.0 ,因为B事务的干预

System.out.println("price:"+rs.getDouble(1));

}

close();

//提交事务

conn.commit();

if(conn != null){

conn.close();

}

上面执行的顺序,

事务B是在A的执行过程中执行的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值