- 浏览: 194699 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
hahalzb:
请问文件解压缩的密码是什么呀
JMS简介与ActiveMQ实战 -
ershimengx:
JMS&ActiveMQ实战(JMS+ActiveMQ ...
JMS简介与ActiveMQ实战 -
lgh1992314:
zenghuiss 写道我书读的少,你不要蒙我哦。。。over ...
Java method invoke的指令简介 -
P00116:
...
JMS简介与ActiveMQ实战 -
风会停息丶:
你好,下载完成后解压密码是多少,跟网盘下载密码一样吗
JMS简介与ActiveMQ实战
写这篇文章的缘由,在于读过论坛中的一些帖子引发的疑问,先来看一下帖子的内容。
robbin的一个帖子
http://www.iteye.com/topic/8850
http://www.iteye.com/topic/319768
1. 首先最根本的,我们要看一下数据库中对于readonly事务的定义!
第一个帖子中已经给出了结论:
Oracle默认情况下保证了SQL语句级别的读一致性,即在该条SQL语句执行期间,它只会看到执行前点的数据状态,而不会看到执行期间数据被其他SQL改变的状态。 而Oracle的只读查询(read-only transaction)则保证了事务级别的读一致性,即在该事务范围内执行的多条SQL都只会看到执行前点的数据状态, 而不会看到事务期间的任何被其他SQL改变的状态。
这个是Oracle对于只读事务的描述,要保证事务级别的读一致性有两种方式,第一个帖子中也给出了结论:
一是用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE 二是用SET TRANSCATION READ ONLY
我们来做一下测试(采用第二种方式):
编写一个oracle的存储过程:
create or replace procedure p_test as ware_code varchar2(14); begin set transaction read only; select t.ware_code into ware_code from tp_area t where t.area_code = '1'; dbms_output.put_line(ware_code); dbms_lock.sleep(10);--暂停10秒 select t.ware_code into ware_code from tp_area t where t.area_code = '1'; dbms_output.put_line(ware_code); end p_test;
area_code是tp_area表的主键。在暂停的10秒钟内,我们去更改area_code为1的这条记录中ware_code的值,并提交。
经过测试发现,两次的输出结果一致,这就证明了正确性。
ps:对于oracle中只读事务的描述,推荐参考《Oracle 9i&10g编程艺术:深入数据库体系结构》这本书!
但是我们要说明,并不是所有的数据库都支持readonly事务。
2. 接下来我们讨论jdbc中对于readonly事务的描述
jdk1.6中java.sql.Connection接口中定义的方法
setReadOnly(boolean readOnly) throws SQLException的描述:将此连接设置为只读模式,作为驱动程序启用数据库优化的提示。
例如:此连接设置为只读模式后,通知Oracle后,Oracle做自己的优化;通知DB2后,DB2做自己的优化等等,但是并不一定对于数据库而言这就是readonly事务,此readonly并非彼readonly!
讲到这里,很多人可能并不信,难道setReadOnly为true之后数据库并不是以readonly事务执行的?
我们以实际的测试结果说话:
测试环境一:
数据库:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production oracle jdbc驱动版本:Oracle JDBC Driver version - 9.0.2.0.0 此驱动已经是很老的了,但是相信还是有很多项目还在用就是ojdbc14.jar。 jdk版本:jdk 1.6.0_20
测试代码:
Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection(url, username, password); conn.setAutoCommit(false); conn.setReadOnly(true);//启动只读模式 PreparedStatement ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); ResultSet rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); Thread.sleep(10000);//暂停10秒 ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); ps.close(); conn.commit();
在暂定的10秒钟内,我通过pl/sql手动去修改了这条记录中ware_code的值,并提交,那这两次的输出结果一样吗?
测试的结果是:这两次的输出结果是一致的!
咦,这不是对的吗?oracle启动了只读事务,根据事务级都一致性的原则,两次读出来的应该是同一时间点的数据,应该一致啊!
好,别着急,我们再来看一个测试。
测试环境二:
数据库:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production oracle jdbc驱动版本:Oracle JDBC Driver version - 11.2.0.1.0 这种从官方网站上面下载的最新的驱动ojdbc5.jar jdk版本:jdk 1.6.0_20
测试代码(与上面的测试代码一致):
Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection(url, username, password); conn.setAutoCommit(false); conn.setReadOnly(true); PreparedStatement ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); ResultSet rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); Thread.sleep(10000);//暂停10秒 ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); ps.close(); conn.commit();
在暂定的10秒钟内,我同样还是通过pl/sql手动去修改了这条记录中ware_code的值,那这两次的输出结果一样吗?
测试的结果是:这两次的输出结果是不一致的!
--------------------------------------------------------------------分割线--------------------------------------------------------------------------------
是不是不太敢相信自己的眼睛,我开始的时候也是很纳闷,为啥会这样!!??
我们先来看一下 Oracle JDBC Driver version - 9.0.2.0.0 版本的的api中的说明:
oracle.jdbc.driver.OracleConnection public void setReadOnly(boolean value) throws java.sql.SQLException Sets the Connection as read only if the value is true and the enables the Connection for writing (updat/delete/insert) with the value as false.
但是最直接有效的方式还是看源码!
好的,我们来看一下Oracle JDBC Driver version - 9.0.2.0.0 ojdbc14.jar这个版本的驱动源码:
//jdbc.oracle.driver.OracleConnection 的代码片段 public void setReadOnly(boolean flag) throws SQLException { PreparedStatement preparedstatement = null; try { String s = null; if (flag) s = "SET TRANSACTION READ ONLY"; else s = "SET TRANSACTION READ WRITE"; preparedstatement = prepareStatement(s); preparedstatement.execute(); } finally { if (preparedstatement != null) preparedstatement.close(); } m_readOnly = flag; }
从源码中我们可以很明显的看出来当setReadOnly为true时,究竟做了什么事-->"SET TRANSACTION READ ONLY",
所以在此版本的jdbc实现中只要你setReadOnly为true,则对于数据库而言就是以只读事务来执行。
那Oracle JDBC Driver version - 11.2.0.1.0这个版本的驱动究竟怎么回事呢?
首先从这个版本的api中,我们已经找不到oracle.jdbc.driver.OracleConnection这个类了,
我们来看oracle.jdbc.OracleConnectionWrapper implements oracle.jdbc.OracleConnection
虽然api中存在public void setReadOnly(boolean readOnly) throws java.sql.SQLException这个方法,但是没有任何描述,很奇怪。
我们来看一下源码的片段:
protected oracle.jdbc.OracleConnection connection; ..... public void setReadOnly(boolean flag) throws SQLException { connection.setReadOnly(flag); } //OracleConnection接口声明:public interface OracleConnection extends Connection
你能够看出什么来吗? 是啊,根本就没做什么是嘛,对的,什么事情都没做!
ps:貌似此版本的驱动对于readonly属性就是抛弃了,没起作用!(没有再做深入研究,不知这样讲是否正确)
甚至说我如下的代码都可以执行通过:
Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection(url, username, password); conn.setAutoCommit(false); conn.setReadOnly(true); PreparedStatement ps = conn.prepareStatement("update tp_area t set t.ware_code ='t'"); ps.executeUpdate(); ps.close(); conn.commit();
设置只读后,我还能执行更新操作,并且运行测试都是Ok的!
但是如果我想要实现oracle的readonly事务该怎么办呢?
你可以从Oracle JDBC Driver version - 9.0.2.0.0 ojdbc14.jar源码中得到思路,代码如下:
Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection(url, username, password); conn.setAutoCommit(false); conn.setReadOnly(true); //新增的两行 PreparedStatement ps = conn.prepareStatement("set transaction read only"); ps.execute(); ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); ResultSet rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); Thread.sleep(10000);//暂停10秒 ps = conn.prepareStatement("select s.ware_code from tp_area s where s.area_code = '1'"); rs = ps.executeQuery(); rs.next(); System.out.println(rs.getString(1)); ps.close(); conn.commit();
对的,就是设置手动显示地 "set transaction read only"即可!ps:不知道还有没有其他的方式?
经过上述分析后是不是豁然开朗的许多!
总结:1. 首先jdbc的规范中已经说明了readonly只是将此连接设置为只读模式,作为驱动程序启用数据库优化的提示,并不一定以只读事务执行!
2. 对于oracle的jdbc驱动而言,不同版本的驱动会得出不同的结论!
但是我不清楚的是为什么oracle在后续驱动中,不支持了readonly事务了呢?处于性能的考虑?还是别的其他原因,有待求证!
3. SSH架构中Spring的readonly事务
底层的驱动都可能不支持readonly事务,你说Spring的readonly事务能管用吗?答案是很显然的,当然不一定支持。
第二个帖子中的theone说的是对的。
“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作, 那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
ps:对于上述内容中有误的地方,欢迎拍砖!
发表评论
-
字符编码
2011-08-29 11:29 0UTF-16 用两个字节来表示 Unicode 转化格式,这个 ... -
J2EE企业架构性能关键点
2011-08-19 15:33 0硬件、操作系统的性能 1. 运算速度 --> C ... -
自用【链接贴】
2011-09-17 20:05 1576//------------------------- ... -
Tomcat6.0.14下配置Tomcat Administration Web Application
2009-09-30 11:53 1056Tomcat5.5以后的binary核心安装版不再集成Tomc ... -
Spring的AOP应用实例
2009-10-13 10:04 1368/** * 实现org.springframework.a ... -
用Spring集成的JOTM配置分布式事务
2009-11-05 15:45 2443最近项目中涉及到了两个Oracle数据库的操作。需要用到分布式 ... -
JMS简介与ActiveMQ实战
2011-06-24 12:23 821851. JMS架构 Java 消息服务(Java Mes ...
相关推荐
Spring 管理事务(传播特性、隔离级别、readonly).rar
readonly总结 readonly总结
QTP处理readonly控件,对于日期控件效果比较好
c#中const与readonly区别
•readonly和const都是用来标识常量的[1]。•const可用于修饰class的field或者一个局部变量(local variable);而readonly仅仅用于修饰class的field。•const常量的值必定在编译时就已明确并且恒定的;而readonly...
C#编程中 readonly与const的区别详解
RMAN skip readonly 8 RMAN备份只读表空间 8 RMAN skip readonly 0级备份 8 RMAN skip readonly 恢复 10 只读表空间的备份与恢复 12 1、只读表空间定义和特性 12 2、只读表空间的备份与恢复 13 3、Case1只读表空间的...
clickhouse_readonly_recovery clickhouse 表readonly处理通用方法
主要介绍了深入探讨C#中的const、readonly关键字,本文可以帮助你深刻理解这两个关键字,而且是面试中最可能面试到的问题哦,需要的朋友可以参考下
input data-bind="readonly: myobs" >JS ko.applyBindings({ myobs : ko.observable()});此绑定是用AMD编写的。 它返回绑定对象。 第一次需要时,它将自身附加到knockout.bindingHandlers.readonly 。 可以使用...
官方离线安装包,测试可用。请使用rpm -ivh [rpm完整包名] 进行安装
如下: 1.readonly 代码如下: $(‘input’).attr(“readonly”,”readonly”)//将input元素设置为readonly $(‘input’).removeAttr(“readonly”);//去除input元素的readonly属性 if($(‘input’).attr(“readonly...
在网页中我们有时候需要控制文本输入框的“输入状态”,一些关键属性是不能修改的,这个时候需要将文本输入框的readonly属性设置为False,在网页中我们可以使用 <input name=”txt_name” type=”text” readonly...
javascript操作文本框readOnly
方法如下: 代码如下:<select onbeforeactivate=”return false” onfocus=”this.blur()” onmouseover=”this.setCapture()” onmouseout=”this.releaseCapture()”> <option>1 <...
分别解说了C#中const的使用方法和readonly的使用方法和区别
readonly 允许把一个字段设置成常量,但可以执行一些运算,可以确定它的初始值。因为 readonly 是在计算时执行的,当然它可以用某些变量初始化。readonly 是实例成员,所以不同的实例可以有不同的常量值,这使...
如下: 1.readonly 代码如下: $(‘input’).attr(“readonly”,”readonly”)//将input元素设置为readonly $(‘input’).removeAttr(“readonly”);//去除input元素的readonly属性 if($(‘input’).attr(“readonly...
Readonly和Disabled是用在表单中的两个属性,它们都能够做到使用户不能够更改表单域中的内容。但是它们之间有着微小的差别,我在实践中得到了一些规律