oracle数据库:开发成功的Oracle应用_笔记11
1.3.4数据库独立性(续)
2.确保能够适用
这里的目标是充分利用可用的工具,但是确保能够根据具体情况逐一修改实现。
例如,许多数据库应用都有一个功能,即为每一行生成一个唯一的键。插入行时,系统应自动生成一个键。为此,ORACLE实现了一个名为SEQUENCE的数据库对象。每个数据库都有一个解决办法。不过,不论从做法上讲,还是从输出来看,各个数据库的方法都有所不同。所以,有见识的开发人员有两条路可走。
.开发一个完全独立于数据库的方法来生成唯一的键
.在各个数据库中实现键时,提供不同的实现,并使用不同的技术
从理论上讲,第一种方法的好处是从一个数据库转向另一个数据库时无需执行任何修改。称为“理论上”的好处,因为这种实现实在太庞大了,所以这种方案根本不可行。要开发一个完全独立于数据库的进程,必须创建如下所示的一个表。
scott@ORCL>conn scott/tiger
Connected.
scott@ORCL>create table id_table
2 (id_name varchar2(30) primary key,
3 id_value number);
Table created.
scott@ORCL>insert into id_table values('MY_KEY',0);
1 row created.
scott@ORCL>commit;
Commit complete.
scott@ORCL>update id_table
2 set id_value=id_value+1
3 where id_name='MY_KEY';
1 row updated.
scott@ORCL>select id_value
2 from id_table
3 where id_name='MY_KEY';
ID_VALUE
----------
1
看上去很简单,但是有以下结果(注意结果不止一项)。
.一次只能一个用户处理事务行。需要更新这一行来递增计数器,这会导致程序必须串行完成这个操作。在最好的情况下,一次只有一个人生成一个新的键值
.在ORACLE中(其他数据库中的行为可能有所不同),倘若隔离级别为SERIALIZABLE,除第一个用户外,试图并发完成此操作的其他用户都人接到这样一个错误:"ORA-08177:can't serialize access for this transaction"(ORA-08177:无法串行访问这个事务)
scott@ORCL>set transaction isolation level serializable;
Transaction set.
scott@ORCL>update id_table
2 set id_value=id_value+1
3 where id_name='MY_KEY';
1 row updated.
scott@ORCL>select id_value
2 from id_table
3 where id_name='MY_KEY';
ID_VALUE
----------
2
下面,再到另一个SQL*Plus会话完成同样的操作,并发地请求唯一的ID:
scott@ORCL>set transaction isolation level serializable;
Transaction set.
scott@ORCL>update id_table
2 set id_value=id_value+1
3 where id_name='MY_KEY';
此时它会阻塞,因为一次只有一个事务可以更新这一行。这展示了第一种可能的结果,即这个会话会阻塞,并等待该行提交。但是由于我们使用的是Oracle,而且隔离级别是SERIALIZABLE,提交第一个会话的事务时会观察到以下行为:
scott@ORCL>COMMIT;
Commit complete.
第二个会话立即显示以下错误:
ORA-08177
所以,尽管这个逻辑原本想做到独立于数据库,但它根本不是数据库独立的。根据隔离级别,这个逻辑甚至在单个数据库中都无法可靠地完成!有时我们会阻塞并等待,但有时却会得到一条错误消息。
3、分层编程
假设你在使用JDBC进行编程,如果用的都是直接的SQL(SELECT、INSERT、UPDATE和DELETE),可能不需要抽象层。完全可以在应用程序中直接编号SQL,前提是只能用各个数据库都支持的构造,而且经验证,这些构造在不同数据库上会以同样的方式工作。另一种方法的可移植性更好,而且可以提供更好的性能,就是使用存储过程来返回结果集。你会发现,每个开发商的数据库都可以从存储过程返回结果集,但是返回的方式不同。针对不同的数据库,要编写的具体源代码会有所不同。
这里有两个选择,一种做法是不使用存储过程返回结果集,另一种做法是针对不同的数据库实现不同的代码。我就坚持第二种做法,即针对不同的开发商编写不同的代码,而且大量使用存储过程。初看上去,另换一个数据库实现时这好像会增加开发时间。不过你会发现,在多个数据库上实现时,采用这种方法实际上容易得多。不用寻找适用于所有数据库的最佳SQL,而只需实现最适合该数据库的SQL。这些工作可以在应用之外完成,这样对应用调优时就有了更大的灵活性。可以在数据库自身中修正一个表现很差的查询,并立即部署所做的改动,而无需修改应用。另外,采用这种方法,还可以充分利用开发商提供的SQL扩展。例如,Oracle在其SQL中通过CONNECT BY操作支持层次查询。这个独有的特性对于处理递归查询很有意义。在Oracle中,可以自由地使用这个SQL扩展,因为它在应用“之外”。
针对特定的数据库,按照数据库特有的一组功能,可以采用最适于该数据库的方式来实现。开发人员可以自由地使用底层数据库平台的强大能力。
对于不同的数据库来说,SQL语法可能存在差异,实现有所不同,同一个查询在不同数据库中的性能也不一样。不仅如此,还存在并发控制、隔离级别、查询一致性等问题。SQL92/SQL99试图对事务应如何工作以及隔离级别如何实现给出一个明确的定义,但最终,不同的数据库还是有不同的结果。
ORACLE的隔离级别
http://www.2cto.com/database/201203/125702.html
Oracle事务隔离级别
http://www.52ij.com/jishu/5139.html
oracle数据库:开发成功的Oracle应用_笔记10
http://database.51cto.com/art/201011/234119.htm
详解oracle事务隔离级别
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5140.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
