oracle 数据库隔离级别

oracle 数据库隔离级别[b]事务不同引发的状况:[/b]脏读(Dirtyreads)一个事务读取另一个事务尚未提交的修改时,产生脏读很多数据库允许脏读以避免排它锁的竞争。不可重复读(Nonrepeatablereads)同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发…

大家好,又见面了,我是你们的朋友全栈君。[b]事务不同引发的状况:[/b]

脏读(Dirty reads)

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

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

不可重复读(Nonrepeatable reads)

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

幻读(Phantom reads)

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

[b]数据库操作的隔离级别[/b]

未提交读(read uncommitted)

提交读(read committed)

重复读(repeatable read)

序列化(serializable)

[b]oracle默认隔离级别[/b]read committed (statement level serialization)

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

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

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

新建一个测试表books:

name,code,price三个字段

添加两条测试数据

[img]http://dl2.iteye.com/upload/attachment/0096/6188/19e41b31-81f9-3a08-bd58-e047843614d5.jpg[/img]

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

[i]不允许脏读测试:[/i]

程序段首先查询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';

[color=orange]!pl/sql设置成手动更新,不自动更新[/color]

在执行上面java查询代码

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

pl/sql 执行

commit;

在执行java查询:

输出结果:price:18.0

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

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

的事物进行读的。

[i]隔离级别:重复读(repeatable read)[/i]

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

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

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

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

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

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

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

[i]隔离级别:serializable [/i]

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

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

前面像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的执行过程中执行的

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141148.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • redis如何设置密码及验证密码_redis设置永不过期

    redis如何设置密码及验证密码_redis设置永不过期密码设置这里简单介绍一下redis如何设置密码redis密码设置有两种方式,一种需要重启redis服务,一种不需要重启redis服务。首先,介绍一下需要重启redis服务的设置方式即找到redis的配置文件—redis.conf文件,然后修改里面的requirepass,这个本来是注释起来了的,将注释去掉,并将后面对应的字段设置成自己想要的密码,保存退出。重启redis服务,即可。我…

    2022年4月19日
    78
  • 0基础激光切割怎么学_吉他入门零基础视频教程

    0基础激光切割怎么学_吉他入门零基础视频教程杂谈最近有几个人加我,都说是刚开始学激光slam,基本都是研一,情况也都差不多,有的是课题组里只有自己做slam,有的是完全没人带,自己也没有基础.仔细想一想,其实入门slam真是个不容易的事.首先,编程语言,大多数使用c++,少数用python,c++你得至少能写个小demo吧.知道了如何写c++,还要准备编译环境吧,由于编译以及依赖等问题,做slam基本都用linux,还得知道如何使用ubuntu的命令行,知道怎么编译代码.关于机器人相关的大部分代码都使用ros做接口,因为接口统一,使用方式统

    2022年8月23日
    7
  • gnuplot 入门教程 1

    gnuplot 入门教程 1几年前写的一篇短文,今天找东西时翻出来了,感觉写的还是比较实用的。放在这里供有需要的人参考。现在在网上可以找的科学作图软件有不少,其中不乏优秀者,Win平台上有大名鼎鼎的Origin、Tecplot、SigmaPlot等,类UNIX上有LabPlot、gnuplot等。其他的常见的计算软件如Matlab、Mathematica、Maple、Scilab、IDL、Maxima等也都对科学作图

    2022年6月16日
    36
  • docker搭建kafka集群

    docker搭建kafka集群docker搭建kafka集群我在M1mbp上使用的以下镜像新建文件zk-kafka-docker-compose.ymlversion:”2″services:zookeeper:user:rootimage:docker.io/zookeeperports:-“12181:2181″environment:-ALLOW_ANONYMOUS_LOGIN=yesvolumes:-zoo

    2022年4月25日
    33
  • 170406回顾-SQL Server的smalldatetime类型比较[通俗易懂]

    170406回顾-SQL Server的smalldatetime类型比较[通俗易懂]在比较SQLServer的类型为smalldatetime字段时出现下面的错误:将expression转换为数据类型smalldatetime时出现算术溢出错误正确的比较方法如下:将long型转换为时间格式的字符串,再与smalldatetime类型的字段比较SELECT*FROMtablenameWHEREEditFlag>’2017/3…

    2022年5月18日
    47
  • Vb.net/VB 声明API功能父窗口功能[亲测有效]

    Vb.net/VB 声明API功能父窗口功能

    2021年12月17日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号