事务不同引发的状况: 脏读(Dirty reads) 一个事务读取另一个事务尚未提交的修改时,产生脏读 很多数据库允许脏读以避免排它锁的竞争。 不可重复读(Nonrepeatable reads) 同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。 幻读(Phantom reads) 同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。 数据库操作的隔离级别 未提交读(read uncommitted) 提交读(read committed) 重复读(repeatable read) 序列化(serializable) oracle默认隔离级别read committed (statement level serialization) 每一个语句,在语句开始时,会获取一个此刻的数据快照。 一个事务有多条语句,如果语句之间存在其它完成的事务,这可能引起不可持续读和幻读。 //内容来自AnYun.ORG 新建一个测试表books: name,code,price三个字段 添加两条测试数据 ![]() 使用pl/sql和java程序模拟并发 //内容来自安云网 复制代码 代码如下: //获取连接 省略 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 复制代码 代码如下: update books set price=18 where code='qqq'; !pl/sql设置成手动更新,不自动更新 //内容来自AnYun.ORG
在执行java查询: 会有不可重复读何幻读的现象发生就不用测试了吧, 隔离级别:重复读(repeatable read) 隔离级别:serializable //内容来自AnYun.ORG
当A事物执行a,b的时候,若有B事物执行更新操作,是有可能的 //内容来自AnYun.ORG
例子: //内容来自安云网 复制代码 代码如下: //获取连接和关闭连接代码 省略 //不自动提交 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的执行过程中执行的。 //内容来自安云网 以上通过实例介绍了oracle数据库隔离级别的相关内容,希望对大家有所帮助。 //内容来自AnYun.ORG
//内容来自安云网 3. REPEATABLE READ 这种隔离级别不支持脏读,不支持可重复读,支持幻想读。主要是为了得到一致性的答案与防止丢失更新。 a. 得到一致性答案 在oracle里面这个通过多版本机制得到了实现,但是在其他的数据库需要通过加锁机制进行控制,就以上一个例子为例,怎样才能统计出正确的总金额呢,事务A在读取每一行的时候,给每一行加上共享读锁,这样当事务B执行从账号123转400元到账户987的时候。先是操作第一行将账户123的金额由500修改成100,但是第一行已经被事务A锁定,于是等待,这样事务A能够读取到正确的数据。但是如果事务B执行的操作是从账户987转50元到账户123的时候,事务B先操作第342023行,发现没有被锁定,于是锁定将金额由100修改成50,然后操作第一行,发现锁定了于是等待。而事务A读取到342023行的时候,发现这一行已经被事务B锁定于是等待,这样就陷入了死锁。 //本文来自安云网 b. 丢失更新 在采用共享读锁的数据库中,这种隔离级别可以防止丢失更新,比如事务1先读取了第A行然后修改了这一行的C列(其他列也修改了只是值还和以前一样,因为程序员都是整行的更新)。这个时候事务2想也想修改A行的时候会被阻塞,防止事务1的更新被覆盖。 4. SEAIALIZABLE 不允许脏读,重复读与幻想读,最高的隔离级别。这种隔离级别标明事务A在操作数据库的时候好像就只有事务A在操作,没有其他事务在操作数据库一样。 Oracle 中是这样实现 SERIALIZABLE 事务的:原本通常在语句级得到的读一致性现在可以扩展到事务级。也就是在事务执行的那一刻,将这个事务将要操作的数据拍了一张照片。 从上面的例子我们可以看出,其他数据库采用共享读锁来解决统计总金额问题是没有oracle多版本机制灵活的,其一严重影响了程序的并发性,读阻塞了写。其二可能引起死锁。 //内容来自AnYun.ORG
|