在SQL Server的最近版本中,微软对SQL Server进行了某些修改,使其一次锁定的数据量大大减少,这是数据库设计
SQL Server的解决方案听起来很简单,但实际上其幕后为提供足够的系统高性能而采取了很多措施。例如,如果你在同时修改多行数据,SQL Server则会把数据锁定范围提升到页级别乃至锁定整个数据表,从而不必针对每一记录跟踪和维护各自的数据锁。
Oracle方法
|
代码返回两行数据,然后,再打开另一个SQLPlus实例——更新实例来执行以下命令:
|
代码执行后回复消息称两行数据已被更新。
注意,以上代码中并每有像在SQL Server示例那样键入“begin tran”字样的代码。Oracle 的SQLPlus隐含启用交易(你还可以模仿SQL Server的行为,设置“autocommit to on”自动地提交交易)。接下来我们在SQLPlus更新实例中再执行同查询实例一样的select语句。
结果清楚地表明:Michael和Pat的薪水都增加了,然而这个时候我还没有提交数据变更交易。Oracle不需要用户等待数据更新实例中操作被提交,它径直返回Michael和Pat的查询信息,但实际上返回的是数据更新开始之前的数据视图!
这时候,熟悉SQL Server的人可能会说了,在查询中设置(NOLOCK)不也能达到同样的效果吗?可是,对SQL Server而言,在数据映像之前是不能获取数据的。指定(NOLOCK)实际上只是得到了没有提交的数据。Oracle的方法则提供了数据的一致视图,所有的信息都是针对交易的、基于存储数据快照的。
如果在SQLPlus的更新实例中提交更新交易在查询实例中就能看到薪水数据发生变化。如果在查询实例中重新运行先前的查询语句,那么Oracle将返回新的薪水数值。
存储数据快照
这个特殊的存储区域在哪里呢?这个问题的答案就跟你正在使用的Oracle版本有关了。在 Oracle 8i及其以前版本中会为这一目的创建特殊的回滚段。然而,这种举措会给数据库管理员(DBA)带来管理和调整数据段的工作负担。例如,DBA必须确定为此需要的数据段的数量以及大小等。假如回滚段没有正确配置,那么对交易而言它们就可能不得不排队等待回滚段中出现必要的数据空间。
Oracle 9i就不同了,这是Oracle的最新版本,Oracle实现了一种新特性,这就是所谓的undo表空间,它有效地消除了以上的管理复杂性。虽然回滚段仍然可以继续使用,但是,DBA现在可以选择创建undo表空间的方式令Oracle自己管理“前映像”的复杂空间分配。
Oracle的这种方法对程序员具有重要意义。因为回滚空间不是无限的,所以,更新交易的数据快照会取代先前交易的映像。因此,如果必要的回滚段被其他交易的映像覆盖的话。运行时间较长的查询操作就可能产生“ snapshot too old”错误。
下面举个可能发生的案例。假设在上午11:59的时候某位职员开始更新John Doe帐务的交易。这宗交易在下午12:01被提交。同时,下午12:00某财务经理开始查询所有的客户帐务报表和当月收费总计。因为客户很多,所以这一查询操作很费了点时间,但是不论这次操作到底执行了多久,反正它检索出的结果就是下午12:00数据库中存在的数据。如果包含John Doe帐务前映像的回滚空间在查询执行到该客户名字的时候被覆盖则查询返回错误消息。
Oracle的解决方案当然更为合理,在抽象意义上提供了相比SQL Server更佳的数据一致性。在执行Oracle查询的时候无须担心较长的查询操作会锁定重要的交易。但是,在两种数据库同时支持海量用户的情况下也很难证明Oracle是否就能真正实现具体条件下的数据一致性。