`
icyheart
  • 浏览: 779678 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

在客户端处理Oracle的数据行加锁问题(select for update)

阅读更多

数据的完整性和并发性:
  
  在网络数据库处理数据中,需要保证数据的完整性、多事务的并发性和数据的一致性。数据库系统必须最大限度的保证数据内容的有效性和合理性,使得数据合法与合理,即保证数据的完整性。而网络(多用户)数据库应用系统中,通常都会遇到多个事务同时请求修改同一数据。数据库的并发性处理保证数据库系统据能够合理有效地处理多个事务请求,在数据库管理系统协调下,宏观表现为并行处理,微观为逐个串行处理,保证数据的一致性,从而避免数据处理中的 “脏”数据发生。在数据库系统本身对数据的并发性和一致性有基本控制能力下,以Oracle为例的关系数据库系统已经能保证数据的并发性能,而数据库的应用设计则需要以考虑数据在并发过程中的一致性为重点。一个简单的例子:甲乙同时从数据库中读出了一条相同的数据记录。甲把数据作了修改,并且作了事务提交。(而乙此时并不知道数据已经被修改了。)称乙已经读出的数据为脏数据,破坏了数据的一致性 , 为了保证数据的一致性,此时有必要对数据进行加锁。再例如:一银行帐户有¥6000, 此时甲要从中提出¥5000,而乙也同时要从中提出¥5000,双方在不加锁查询时,双方均认为可以提款,事实上肯定有一方的提交会失败。原因是在最终事务提交时,要对数据作了加锁查询效验处理。
  

 


  并发性和一致性 
  
  数据库中的数据锁 为了防止多个用户事务交替操作数据库对象,破坏性数据库完整性,同时又要保证数据的并发性和一致性,数据库管理系统一般提供了各种类型的封锁机制,可以自动为一个事务封锁资源,而在事务不需要时自动释放。以使另一个需要独占该资源的事务能够继续进程,而不会造成事务死锁。数据库对象的封锁完全能够由数据库系统自动完成,ORACLE (一般情况数据库)对加锁有以下特征:A 多种封锁模式.例如:系统表的转有锁,共享锁。B 完备的自动加/解锁功能和释放机制。C 用低级别的封锁换取高级别的并发处理。D能够在客户端/服务器模式下自动封锁过程。Oracle 的主要封锁类型有:
  A 数据锁,用于封锁表或表中的指定行.属于数据操纵锁,
  
  B 字典锁,用于保护数据库对象(表,索引)的创建维护.属于数据定义锁
  
  C 内部锁。用于保护数据库的内部结构.
  
  正常情况下,为完成数据操纵,一般需要两种级别的封锁方式,封锁整表或行封。通常只在热备份数据,时候,需要对整表进行锁定. 而应用程序的事务处理通常是数据行的数据操纵语句:
  
  INSERT,
   UPDATE,
   DELETE,
   SELECT (FOR UPDATE)
  
  以上操作在执行过程中,数据库都会对相应的行做数据行封锁.
  
  一般情况下,只要行封事务不放弃封锁, 此行就不可能被其他任何用户的事务修改(部分语句,如SELECT仍然允许不加锁地读出)。只有当数据库重新启动,数据表空间离线/在线处理,当事务正常提交、回滚时,行封事务才能被自动解除封锁. (通常 ROLLBACK ,COMMIT 可以自动解除行封锁。)在表上的数据锁的高低级别为:
  
  


  简单的SELECT 语句无任何锁,INSERT, UPDATE, DELETE为行专有(RX),允许在操作中多次修改这些行, 提交或回滚后自动解除封锁,
  
  SELECT (FOR UPDATE )为专有行的数据锁.在应用程序中使用最多.也是通常对数据行进行控制的简单有效的方法。例如:在Windows95下,同时分别用两个以上SQL*PLUS,以相同的用户联接Oracle Server相同的实例,在其中一个窗口下做Update/Delete中任意操作,只要没有提交,均不影响其它窗口的不加锁查询,但是不可以再其它窗口下对同一条记录作Update/Delete 操作,Insert没有提交以前,其它操作均无效。只有当一方事务完成(提交/回滚)以后立即释放相应资源,另一方申请的事务才能成功响应。
  
  行锁在应用程序的注意事项
  在实际应用中,可能由于一次事务提交的数据太多,造成数据加锁时间太长,破坏了数据的并发共享特性。如果事务独占了相应的资源,没有得到释放,而另一个事务占有该事务的下一个资源,就有可能造成数据库应用系统死锁。另外,如果在加锁过程中,出现网络中断,客户端掉电等突发问题,被加锁的资源无法解锁,其它应用程序将无法继续获得已经被加锁的资源,也可以出现死锁. 通常只有DBA才能取消事务或通过数据表空间的在线/离线操作解除加锁事务(通常大型应用系统这样做有一定的风险)。如果在程序应用中经常出现这样的问题,则造成应用数据库应用系统无法正常工作。虽然这样的情况在C/S程序的开发/应用中并不经常出现,但是在应用程序设计中都是应该严格考虑的。
  
  常用的数据加锁方法(以ORACLE 与PB连接为例)
  A 在客户端编程方法:在客户端的编程处理的方法最简单,调试也很直观、方便。但是这种方法仅仅在中、小型网络中可以使用。因为当网络用户数量增加,或应用程序在客户端应用过程中意外中断(死机,退出),则可能造成数据行的死锁。其他用户无法正确独占加锁。但是实际应用表明此种方法在网络自身可靠性好、用户数量不大时经常被采纳。
  
  下面是用POWERBUILDER 与 ORACLE的数据联结处理实例。
  
  /**********************************************************
  
  *变量:ls_goodscode , li_store_qty
  
  * 表:AMS.TAB_STORE_GOODSINFO
  
  *
  
  *功能:从库存数中减去 2
  
  *
  
  **********************************************************/
  
  STRING ls_goodscode
  
  INTEGER li_stroe_qty
  
  ls_goodscode = sle_goodscode.text
  
  SELECT QTY
  
  INTO li_store_qty
  
  FROM AMS.TAB_STORE_GOODSINFO
  
  WHERE GOODS_NO = SUBSTR(:ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(:ls_goodscode , 14, 4)
  
  FOR UPDATE NOWAITE ; // 对数据加锁,不等待。
  
  if SQLCA.SQLCODE = 0 then // if _01
  
  if li_store_qty >=2 then // if _02
  
  UPDATE AMS.TAB_STORE_GOODSINFO
  
  SET QTY = :li_store_qty - 2
  
  WHERE GOODS_NO = SUBSTR(:ls_goodscode , 1, 13)
  
  AND SERIAL_NO = SUBSTR(:ls_goodscode , 14, 4);
  
  if SQLCA.SQLCODE = 0 then
  
  COMMIT ; // 成功提交
  
  else
  
  ROLLBACK ;// 及时回滚解锁
  
  messagebox("系统提示", "库存数量已经不足!");
  
  end if
  
  else
  
  ROLLBACK;
  
  messagebox("系统提示", "库存数量已经不足!");
  
  end if // end if 02
  
  else //其中 ORA-00054: resource busy and acquire with NOWAIT specified
  
  ROLLBACK ;// 及时回滚解锁
  
  messagebox("系统提示", "数据读入有误,请稍候再试!",stopsign! ok!);
  
  end if // end if 01
  
  //同时在当前的FROM WINDOW中的CLOSEQUERY中显示写明ROLLBACK ;
  
  设计说明:当第一句SELECT完成以后,如果数据加锁正确,则可以继续工作,但是此时可能数据被别的应用程序控制,则返回Oracle的错误代码:ORA-00054说明共享冲突。此句可以用一个有限的循环控制,但是一定要防止数据死锁。同时为了保证万无一失,在当前FORM的关闭事件中显示写明回滚(ROLLBACK)。
  
  B 在客户端按传输(Transaction )方法处理:将要提交的所有SQL任务作为多个子串传送到服务器端,用动态SQL方法在客户端一次传输完成后,在服务器端一次执行完成,只有当事务执行正确,才能提交, 否则回滚。这样在执行多个表操作提交时,数据执行加锁的时间影响将大大减小。这样极大程度的缓解了多表共享数据的加锁问题。好处是不需要服务器端的调试,但是,编程调试过程复杂。但是实际效果与第一种方法基本一致。
  
  C 存储过程方法:这种方法是直接调用服务器的存储过程,所有的对Client端程序代码可以大大减少,数据一致性,并发性,安全性都能得到保证。客户端的异常通常不会影起数据的死锁。
  
  下面是用POWERBUILDER 与 ORACLE的数据联结处理实例。
  
  /**********************************************************
  
  *变量:ls_goodscode , li_store_qty
  
  * 表:AMS.TAB_STORE_GOODSINFO
  
  *
  
  *功能:从库存数中减去 2
  
  *
  
  **********************************************************/
  
  STRING ls_goodscode
  
  INTEGER li_stroe_qty
  
  ls_goodscode = st.text
  
  if len(ls_goodscode) = 17 then
  
  DECLARE pstore_goods PROCEDURE FOR pd_store_goods(:ls_goodscode ) ;
  
  // 从库存数中减去 2
  
  execute pstore_goods;
  
  if SQLCA.SLQCODE < 0 then
  
  ROLLBACK ;
  
  messagebox("系统提示", "数据操作有误,请稍候再试!",stopsign! ok!);
  
  end if
  
  else
  
  messagebox("系统提示", "数据输入有误!",information!, ok!);
  
  end if
  
  //同时在当前的FR

 

这么长一篇文章,要掌握的有一点就是数据加锁,for update、for update nowait这在平时是很有用的。

0
0
分享到:
评论

相关推荐

    数据库oracle for update of和for update的区别

    ### 数据库Oracle锁:FOR UPDATE OF与FOR UPDATE的区别 在Oracle数据库中,为了确保数据的一致性和准确性,尤其是在多用户环境中进行并发操作时,锁机制是必不可少的一部分。本文将详细介绍`FOR UPDATE`与`FOR ...

    oracle 客户端 oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端ora

    oracle 客户端 oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端oracle 客户端...

    oracle执行update语句时卡住问题分析及解决办法

    这种只有update无法执行其他语句可以执行的其实是因为记录锁导致的,在oracle中,执行了update或者insert语句后,都会要求commit,如果不commit却强制关闭连接,oracle就会将这条提交的记录锁住。由于我的java程序...

    .net不需要客户端无客户端 连接Oracle数据库附代码

    它是Oracle Data Provider for .NET (ODP.NET) 的一部分,特别设计用于.NET框架,使得开发者可以直接在.NET应用中与Oracle数据库交互,而无需安装Oracle客户端。 Oracle.ManagedDataAccess.dll是Oracle官方提供的一...

    ORACLE数据库系统加锁问题的研究.pdf

    Oracle数据库系统在处理数据时,为了确保数据的完整性和一致性,采用了加锁机制。加锁主要是为了解决在网络环境下的多事务并发访问同一数据时可能出现的问题,防止数据的不一致性和“脏读”。脏读是指一个事务读取到...

    Oracle客户端安装与新建数据源

    Oracle客户端是用于与Oracle数据库服务器通信的软件组件,它提供了连接到服务器的接口,使得应用程序能够执行SQL查询、事务处理和其他数据库操作。ODBC(Open Database Connectivity)是一种标准的数据库访问接口,...

    Oracle客户端连接Oracle服务器.docx

    - TOAD (Tool for Oracle Application Developers) 是一个强大的Oracle数据库管理工具,支持图形化的界面进行数据库管理、开发和性能调优。用户可以通过TOAD输入服务器信息,包括主机名、端口号和服务名,然后输入...

    oracle客户端免安装版

    它主要用于在不安装完整客户端的情况下,实现应用程序与Oracle数据库之间的通信,便于远程访问、数据查询、数据管理等操作。这个版本特别适合开发者、测试人员以及那些只需要偶尔连接Oracle数据库的用户,因为它占用...

    oracle11g客户端for_linux安装文档

    Oracle 11g 客户端 for Linux 安装文档 Oracle 11g 客户端 for Linux 安装文档提供了详细的安装步骤和配置信息,以便用户成功安装 Oracle 11g 客户端 for Linux。 标题解释 Oracle 11g 客户端 for Linux 安装文档...

    for_update_和_for_update_nowait_的区别

    当执行包含`FOR UPDATE`子句的`SELECT`语句时,Oracle会在所选择的行上放置排他锁(exclusive lock),即X锁,这种锁允许持有者读写数据,但阻止其他事务读写相同的行,直到原事务结束(通常是指提交或回滚)。...

    ORACLE数据库系统加锁问题的研究 (1).pdf

    Oracle数据库系统是关系型数据库的一种,它在处理并发事务时采用了加锁机制来确保数据的一致性和完整性。本文主要探讨了Oracle数据库中的加锁问题,包括为何启用锁、Oracle数据库中的各类锁以及锁的工作原理。 ...

    Oracle19c-Windows客户端

    9. **性能优化**: Oracle 19c客户端在Windows平台上的性能有所提升,包括更快的数据传输速度、更高效的内存管理以及对多核处理器的优化。 10. **兼容性**: Oracle 19c客户端可与多个版本的Oracle数据库服务器兼容,...

    9i客户端 oracle客户端

    Oracle 9i客户端是Oracle数据库的一个重要组成部分,主要用于与Oracle服务器进行通信,提供数据查询、数据更新、应用程序开发等服务。这个"9i客户端 oracle客户端"的描述虽然简洁,但蕴含了丰富的IT知识,让我们深入...

    客户端安装Oracle11g客户端精简版

    Oracle11g客户端是Oracle数据库系统的一个组成部分,主要用于与服务器端进行通信,执行查询、数据操作和应用程序开发。本文将详细介绍如何在Windows 7操作系统上安装Oracle11g客户端的精简版,以及安装后的注意事项...

    OracleClient-18C Oracle客户端,包括windows和Linux

    总的来说,OracleClient-18C是一个全面的数据库客户端解决方案,涵盖了从连接管理、数据查询到安全性的各个方面,为用户在Windows和Linux环境中提供了高效且安全的Oracle数据库访问能力。无论你是开发人员、系统管理...

    oracle的update的五种方式

    例如:`BEGIN FOR cr IN (SELECT * FROM t_join_situation WHERE year='2011') LOOP UPDATE t_join_situation SET join_state='1' WHERE current of cr; END LOOP`。这种方式适用于大批量数据的更新,但需要注意游标...

    oracle19客户端安装包

    Oracle数据库是全球广泛使用的数据库管理系统之一,Oracle 19c客户端是连接到Oracle服务器进行数据查询、管理和维护的重要工具。本指南将详细介绍如何使用提供的"setup.exe"文件来安装Oracle 19c客户端。 一、系统...

    oracle12c 32位简易客户端

    在这个简易客户端中,ODBC驱动程序的提供使得用户可以利用ODBC数据源来配置和管理Oracle数据库连接,实现跨平台的数据交换和应用集成。 即时客户端(Instant Client)是Oracle提供的一种精简版客户端,它不需要完整...

    oracle11g客户端-windows简约

    Oracle 11g客户端在Windows环境下的安装与配置是一个重要的IT知识领域,特别是对于那些需要在Windows操作系统上处理Oracle数据库的开发者和管理员来说。Oracle Client是Oracle数据库的一个组件,它提供了连接到...

    解析oracle对select加锁的方法以及锁的查询

    解析oracle对select加锁的方法以及锁的查询一、oracle对select加锁方法 代码如下:create table test(a number,b number);insert into test values(1,2);insert into test values(3,4);insert into test values(8,9);...

Global site tag (gtag.js) - Google Analytics