首页 > 范文大全 > 正文

民族古籍数字化保护系统中ORACLE数据库的并发控制研究

开篇:润墨网以专业的文秘视角,为您筛选了一篇民族古籍数字化保护系统中ORACLE数据库的并发控制研究范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

摘 要:文章给出了在民族古籍数字化保护系统操作中典型的并发事件(G失更新)解决的两种封锁机制。在操作时,采用适当的封锁机制,锁定需要修改的“行”,防止并发事件的产生,以保证数据库的完整性和一致性。

关键词:民族古籍数字化保护系统;并发控制;悲观封锁;乐观封锁

0 引言

在民族古籍数字化保护系统的数据库中,多个用户程序(如查询和著录)可以并行地存取数据库,如果不对并发操作进行控制,会出现存取不正确数据,或破坏数据库数据的一致性的问题。

1 并发事件的产生

数据库是一个共享资源,可为多个应用程序共享。这些应用程序可以串行运行,但在许多情况下,可能多个程序或一个程序的多个进程并行地运行,这就是数据库的并行操作。并发操作带来的数据不一致性包括三类:丢失修改、不可重复读和读“脏”数据。

例如:在古书籍子系统的修改操作中,下面的事件依次发生时会丢失一个更新操作。

(1)用户1检索一行数据。

(2)用户2检索相同的行。

(3)用户1修改那个行,更新数据库并提交。

(4)用户2修改那个行,更新数据库并提交。

具体地说,当用户1移动到屏幕上的“书籍版本(andoctype)”字段时,修改了版本信息,单击保存,并获得更新已经成功的确认。但此时,另一个用户2已经早于用户1五分钟前就在查询记录了,而且屏幕上显示的仍然是旧数据。用户1随后到来。用户2随后更新了“书籍标题(title)”字段,也单击了保存,用户2完全没有意识到他已经重写了用户1对字段的更改,填写了老数据。之所以可能发生此事,是因为应用程序开发人员,发现更新所有列比更改其中一列更容易,写出的程序中,在更改一个指定字段时,会刷新该记录的所有字段。

防止并发事件的产生,最常见的措施是对数据进行封锁控制。

2 封锁

2.1 锁的功能

oracle通过使用一个内部封锁机制维护数据的完整性、并行性和一致。锁用于限制其他用户对数据的存取。Oracle通过获得不同类型的锁,允许或阻止其他用户对相同资源的同时存取并确保不破坏数据的完整性,从而自动满足了数据的完整性、并行性和一致性。

Oracle在两个不同级亡提供读取一致性:语句级读取一致性和事务级读取一致性。Oracle总是实施语句级一致保证单个查询所返回的数据与查询开始时刻的数据相一致。一个查询不会看到在查询过程中提交的其他事务所进行的任何修改。事务级读取一致性是指同一个事务中的所有数据对时间点是一致的。

2.2 封锁机制

丢失更新是一个常见助数据库问题。很多工具,例如ORACLE表单工具(ORACLE FORMS),通过对记录进行锁定以保证记录在查询时不可更改,可以避免此类问题的发生,民族古籍数字化保护系统是基于J2EE平台的,用JAVA语言编写的系统,做不到这一点。在后台进行保护的工具所做的工作,或开发人员必须自己做的工作,是从两种封锁类型中选择使用一种封锁。

(1)悲观封锁

用户在屏幕上修改值之前,这个锁定方法就要起作用。例如,用户计划对他选择的某个特定行执行更新,如单击屏幕上的“修改”按钮,就会放上一个行锁。

悲观锁定(pessimistic locking)仅用于有状态(stateful)或有连接(connected)环境,即应用程序与数据库有一条连续的连接,并且至少在事务生存期中只有一个用户使用这条连接。每个应用都得到数据库的一条直接连接,这条连接只能由该应用实例使用。这种采用有状态方式的连接方法已经不太常见了,特别是随着20世纪90年代中后期应用服务器的出现,有状态连接更是少见。

假设使用的是一条有状态连接,应用可以查询数据而不做任何锁定:

andoc@ANDOCS>select andocid, andoctype, title fromancientdocs where andocid=10;

最后,用户选择他想更新的一行。在上面的查询中,假如用户选择更新andooctype行。在这个时间点上(即用户还没有在屏幕上做任何修改,但是行已经从数据库中读出一段时间了),应用会绑定用户选择的值,从而查询数据库,并确保数据尚未修改。在SQL*Plus中,为了模拟可能执行的绑定调用,可以执行下面的命令:

andoc@ANDOCS> variable andocid number

andoc@ANDOCS> variable andoctype vachaer2(1000)

andoc@ANDOCS> variable title vachaer2(1000)

andoc@ANDOCS> exec:andocid:=10; :andocypte:=“藏文”,:title:=“怀念故乡”;

PL/SQL procedure successfully completed.

下面,除了简单地查询值并验证数据尚未修改外,要使用FOR UPDATE NOWAIT锁定这一行。应用要执行一下查询:

andoc@ANDOCS> select andocid, andoctype, title

2 from ancientdocs

3 where andocid=:andocid

4 and andoctype=:andoctype

5 and title=:title

6 for update nowait

7/

根据要查询的where条件,应用将提供绑定变量的值,然后重新从数据库查询这一行,这一次会锁定这一行,不允许其他会话更新。这种方法称为悲观锁定(pessimistic locking)。

所有表都应该有一个主键,而且主键是不可变的。以上代码运行中,可能出现三种情况:

(1)如果底层数据没有改变,就会再次得到标题(titel)为“怀念故乡”这一行,而且这一行会被锁定,不允许其他会话更新,但是允许其他会话读。

(2)如果另一个用户正在更新这一行,就会得到一个ORA-00054:resource busy(ORA-00054:资源忙)错误。相应地,必须等待更新这一行的用户执行完工作。

(3)在选择数据和计划更新之间,如果有人已经修改了这一行,就会得到。行。这说明,屏幕数据是过时的。为了避免丢失更新情况,应用程序需要重新查询(requery),并允许在最终用户修改之前锁定数据。有了悲观锁定,用户2试图更新“书籍标题(title)”字段时,应用程序会识别出“书籍版本(andoctype)”字段已经修改,所以会重新查询数据。因此,用户2不会用这个字段的旧数据覆盖用户1的修改。

当成功地锁定了这一行,应用程序就会绑定新值,执行更新命令后,提交所做的修改:

andoc@ANDOCS> update ancientdocs

2 set andoctype=:andoctype, title=:title

3 where andocid=:andocid;

andoc@ANDOCS> commit;

Commit complete.

现在就可以安全地修改这一行了。它不可能覆盖其他人所做的修改,因为已经验证了在最初读出数据之后以及对数据锁定之前数据没有改变。

(2)乐观封锁

第二种方法称为乐观锁定(optimistic locking),即把所有锁定都延迟到即将执行更新之前才做。

这种锁定方法在所有环境下都行得通,但是采用这种方法,执行更新的用户“失败”的可能性会加大。当这个用户要更新他的数据行时,发现数据已经修改过,就必须从头再来。

可以在应用程序中同时保留旧值和新值,然后在更新数据时使用下面的更新语句,这是乐观锁定常用的一种实现形式:

Update table

Set column1=:new_column1, column2=: new_column2,…

where primary_key=:primary_key

and column1=:old_column1

and column2=:old_column2…

此时,我们乐观地认为数据没有修改。在这中情况下,如果更新语句更新了一行,那么更新成功,这说明在读数据和提交更新之间,数据没有改变。但是如果更新了0行,则更新操作失败,有另外用户已经修改了数据。现在必须确定应用中下一步要做什么,是让最终用户查询这一行现在的新值,然后再重新开始事务呢?还是根据业务规则解决更新冲突,试图合并两个更新的值?

实际上,前面的UPDATE能避免丢失更新,但是有可能被阻塞,在等待另一个会话执行对这一行的UPDATE时,它会挂起。如果所有的会话都使用乐观锁定,那么使用直接的UPDATE一般能成功,因为执行更新并提交时,行只会被锁定很短的时间。但是,如果某些会话使用了悲观锁定,它会在一段相对较长的时间内持有行上的锁,可能就会考虑使用SELECTFOR UPDATE NOWAIT,以此来验证行是否未被修改,并在即将更新操作之前锁定以避免另一个会话阻塞。

3 结束语

本文给出了在民族古籍数字化保护系统操作中典型的解决并发事件(丢失更新)的两种封锁机制。在实际工作中,可选用适当的封锁机制,锁定需要修改的“行”,防止并发事件的产生,以保证数据库的完整性和一致性。