用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt

上传人:土8路 文档编号:11518785 上传时间:2021-08-12 格式:PPT 页数:75 大小:1,018KB
返回 下载 相关 举报
用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt_第1页
第1页 / 共75页
用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt_第2页
第2页 / 共75页
用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt_第3页
第3页 / 共75页
用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt_第4页
第4页 / 共75页
用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt_第5页
第5页 / 共75页
点击查看更多>>
资源描述

《用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt》由会员分享,可在线阅读,更多相关《用友NC二次开发参考资料Transaction数据库操作专题技术交流演示文档.ppt(75页珍藏版)》请在三一文库上搜索。

1、,主 题:Transaction Sun ONE = Suns implementation of J2EE + +; Whats DART? Sun 认为的所有企业应用的四个核心要素; Data:数据;企业的一种资产,是企业IT应用的基础和前提,可以通过Data Mining等手段来实现其附加价值; Applications:应用;企业的IT实际应用软硬件环境; Reports:报告;企业数据的View,一般用于直接地反映某个特定的问题; Transactions:事务;企业Critical应用的关键,保证数据的安全,可靠;,Transaction s Definition,事务是作为单个逻

2、辑工作单元执行的一系列操作。当事务结束时,这些操作的结果要么都完成,被接受,要么全被取消。事务具备ACID四个特性。,一、原子性(A:Atomicity),事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。 一个事务中的操作不可能只有一部分被最终提交; 一个事务中的操作也不可能只有一部分被最终回滚; 一个事务当中的临时数据是不可直接查看的,除非是通过程序调试的方式;,二、一致性(C:Consistency),事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。 事务结束时,所有的内部数据结构(如 B 树索引或

3、双向链表)都必须是正确的。,三、隔离性(I:Isolation),由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。 事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。 该特性也称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。,四、持久性(D:Durability),事务完成之后,它对于系统的影响是永久性的。 该修改即使出现系统故障也将一直保持。,Transaction环境的构成,Resource 资源,一般指的是数据库的连接,Connection;

4、Resource Manager 资源管理器,这里指 JDBC Driver; Application Server 应用服务器,这里指EJB Server; Transaction Manager 事务管理器,负责EJB中事务的运行管理; Transaction Application 事务应用程序,如EJB Bean,Client;,Transaction Manager的运行时图,一般Transaction的分类,按照参与事务的资源数: Local Transaction Global Transaction 按照事务中是否有嵌套: None-Nested Transaction Nes

5、ted Transaction,Local Transaction,当Application开始一个数据库Transaction时,如果这个Transaction中只有一个Connection(Resource)或资源管理器(Resource manager),Application通过commit()、rollback()这两个方法来直接控制Transaction,这样的事务称为局部事务(Local transaction); 该类型的Transaction也称为Flat transaction(平板型事务);是我们NC中所采用的事务模式;,Local Transaction示意图,Glob

6、al Transaction,是在一个分布式事务处理系统中,由两个或两个以上的资源管理器所共同执行的单位操作; 系统依靠外部的事务管理器(JTS: Java Transaction Service)来对这些事务进行协调; 在分布式事务中有一个或多个数据库连接,每一个连接都要在(JTS)中进行注册; 分布式事务管理器通过两段式提交(Two-Phase Commit)的方式来提交或回滚该事务; 一般用于High Critical的场合,如:银行交易系统,每笔交易都必须同时写入互为远程异地容灾备份的两个数据库中才能完成的Case;,None-Nested Transaction,非嵌套事务, 指事务

7、中没有嵌套子事务的事务 (Transaction Count 1); 按照当前的EJB规范,Local Transaction /在bean的业务逻辑中 UserTransaction utx = ctx.getUserTransaction(); / 开始事务 utx.begin(); . do work / 提交事务 mit();/或者为utx.rollback();,CMT(Container-Managed Transaction),在CMT中,Bean不直接对事务进行提交操作,而是由Container根据事务的配置,来对事务进行控制,提交或者回滚事务;,EJB Spec1.1中的CM

8、T方法事务属性,NotSupported:不支持; Supports:支持; Required:需要; RequiresNew:需要新事务; Mandatory:独占; Never:从不;,CMTNotSupported,该方法不能在事务中运行,如果一个线程运行在事务中,此时事务要被暂停(suspend),直到该线程从方法中返回。如果没有事务,则该方法正常运行。,CMTSupports,事务可以在该方法中运行,但不是必须的;,CMTRequired,该方法必须在事务中运行。如果线程中不存在事务,那么,Container开始一个事务,线程进入事务,调用该方法。,CMTRequiresNew,不管

9、线程中是否存在事务,Container开始一个新的事务,当线程返回时,该事务被提交或是回滚。如果线程种存在着是事务,那么在方法运行期间它将被暂停(suspend),直到线程返回和新事务的结束。,CMTMandatory,在调用该方法之前,线程必须在事务之中,否则抛出异常。如果有事务,其操作将和Required一样。,CMTNever,在调用该方法之前,线程不能在事务之中,否则抛出异常。,EJB Spec 1.1 Transaction属性表,数据库事务的3个运行阶段,1.事务开始:Begin Transaction语句被写到事务日志中,标示事务的开始点。 2.事务中:执行数据更改指令(如果有)

10、 a.在当前的数据高速缓存中查找要修改的数据,如果不在其中,则从硬盘中加载数据到当前的高速缓存中。 b.在高速缓存中进行相应的修改操作,并把修改情况写到事务日志中,如Insert、Update或Delete语句。 3.事务结束:Commit/Rollback Transaction语句被写到事务日志中,标示事务的结束点,事务的开始点和结束点用于事务的恢复中。,数据库的检查点机制,数据库服务器按照定期间隔生成自动检查点,或者可以通过Checkpoint命令强制数据库在此刻生成一个检查点; 生成检查点时,数据库把已提交后的高速缓存中的数据写到硬盘中,同步数据库与高速缓存中的数据。,基于事务日志和检

11、查点的系统恢复,所有的事务操作都记录在事务日志中,在系统出现故障时,通过事务日志可以很容易地恢复数据。在系统恢复正常后,数据库系统通过事务日志来重构已提交事务,撤消未提交事务。 发生系统故障时,对比事务日志数据和最近检查点的时间,可以可靠地对数据库中的数据进行恢复;,数据库的系统故障示意图,数据库的系统故障恢复过程,“事务1”在检查点前已经提交,在检点后写入硬盘。 “事务2”和“事务4”在检查点没完成提交,但在系统故障点前完成提交,但数据没有写入硬盘,所以进行事务恢复,重构事务。 “事务3”和“事务5”在系统故障点时事务还没有完成,因此要进行事务的回滚。,并发操作中的问题脏读,如果数据库的隔离

12、等级为“READ_ UNCOMMITTED”时:两个客户A、B,A从数据库中读一个记录X=0,操作X=X+10,这时X=10,但事务没有提交,这时B取X,X=10,但此时A放弃,回滚该事务,X=0,这样B中读到就是一个脏数据,称为脏读。如果设置隔离等级为“READ_ COMMITTED”,即只读取提交的事务后的数据就能解决这个问题。,并发操作中的问题不可重复读,两个客户A、B,A从数据库中读一个记录X=0,这时B取更改X,X=10,但此时A重新读X,X已经改变,不能重复读。这里要设置隔离等级为“REPEATABLE_ READ”,也就是在这段读的时时间内锁定该记录,别人无法更改,这样就可以避免

13、这个问题。,并发操作中的问题虚读,两个客户A、B,A从数据库中读到一组结果集X,这时B取往X里面插入新的记录,此时,A重新读X,X中有了新的记录,我们将这称为虚读,或是幻影(phantom)。它和不可重复读之间的区别是,它读到的数据有了新的记录,而不可重复读是读到的数据中作了修改。这里要设置隔离等级为“SERIALIZABLE”, 可以避免改问题;,数据库中四个隔离等级,READ_ UNCOMMITTED READ_ COMMITTED REPEATABLE_ READ SERIALIZABLE,READ_ UNCOMMITTED,可读未被提交的数据,主要用在不需要数据共享,而且不是很重要的任

14、务中,运行速度很快。产生的问题:脏读,不可重复读,虚读。,READ_ COMMITTED,读提交后的数据,而且不是很重要的任务中,如比较粗略的报表类应用中,运行速度快。产生的问题:不可重复读,虚读。,REPEATABLE_ READ,可重复读,用于需要共享,而且比较重要的应用中,如从数据库中查询某些记录,然后要更新它们时,运行速度中等。产生的问题:虚读;,SERIALIZABLE,可连续读,用于高共享,重要的应用中,如银行的存取款操作,运行速度低。不存在上述的脏读、不可重复读、虚读等问题。,数据库的加锁机制,一般的数据库操作中缺省的隔离等级为READ_ COMMITTED; 执行Select,

15、 Insert, Update, Delete操作的前提是被操作的表(或者表的某些行)没有被其它的事务加排他锁(XLock); 执行Insert, Update, Delete三种SQL操作时会导致数据库为该事务对被操作的表(或者表的某些行)加排他锁(XLock) ,直到该事务结束时才释放; 数据库加锁时,一般是加表级锁,除非在Where子句中明确了Row的范围,并且行级锁的机制是Vendor-Specific, 是不可靠的,所以建议不要在程序中依赖行级锁来保证程序的可并发性;,数据库死锁问题分析,一、非并发操作导致的死锁 二、并发操作导致的交叉死锁 三、数据库服务器对典型交叉死锁的自动解锁机

16、制,一、非并发操作导致的死锁,现象描述: 此类死锁表现为只要有多个人操作特定的多个功能节点,系统锁死,一直没有响应;同时借助于数据库的查看当前活动的管理工具,可以看到:数据库的一个进程和另外一个进程互相阻塞(典型的交叉死锁);,非并发死锁的典型伪代码,(在ServletCall所处的线程ServletThread1当中,调用某个BO的业务方法BM1.) BM1()/BO类的一个业务方法,其事务属性为缺省的Required T1.begin();/事务1的起始点 my_table.lock(XMode);/在此调用了insert, update, delete这三种类型的SQL语句来操作数据表m

17、y_table,导致表my_table被数据库加上了排他锁XMode_Lock_On_my_table; . BM2()/BO类的一个其它的业务方法 T2.begin();/事务2的起始点,根据发起事务2的原因,可以分为两种情况,下面将描述; . my_table.operate();/对数据表my_table进行select,insert,update,delete等操作,该行代码执行的前提是:加在my_table上的排他锁XMode_Lock_On_my_table,已经被释放 Tmit();/事务2的结束点 Tmit();/事务1的结束点,在此事务1要么被成功提交,要么被回滚,系统隐含调

18、用my_table.unlock(XMode), 从而my_table被加的排他锁XMode_Lock_On_my_table被释放; ,非并发死锁的两种Case,case 1: 业务方法BM2的事务属性被设置为Request New; case 2: 因为一些没有意料到的情况,BM2方法被运行在一个不同BM1的线程“ServletThread2”中,这时,系统会自动为BM2方法创建一个新的事务空间; (说明: T1,T2:为两个独立的事务,NC中的BO类的业务方法的事务属性缺省为“Required”, 这表示在进入一个BO类的业务方法BM时,隐含事务T1开始,在业务方法BM调用结束的时候,隐

19、含事务T1结束;T2为一个嵌套在T1中的一个事务,事务T2之所以被发起,可能有上述的两种情况),非并发死锁的产生过程,死锁产生的过程: 代码执行的先后顺序决定了Tmit()的代码片段必须在业务方法BM2的调用结束以后才可能被执行,而对数据库资源的竞争,又决定了BM2中的代码片段my_table.operate();又必须首先等Tmit()被执行完后,释放加在my_table上的排他锁XMode_Lock_On_my_table; 结果: 无限的死锁;,非并发死锁的解决方式Case1,case 1: 业务方法BM2的事务属性被设置为Request New; 系统根据该业务方法的事务特性需求将BM

20、2运行在一个新的事务空间T2中; 解决方式A:调整代码执行的先后顺序: 将代码片段my_table.lock(XMode);移动到BM2的调用结束以后去执行; 解决方式B: 将代码片段my_table.lock(XMode)封装一个新的业务方法,并且将该业务方法的事务属性设置为Request New,从而保证在调用BM2前,排他锁XMode_Lock_On_my_table已经被释放; 如果以上的两种解决方式对你的情况都不适用,则你的业务方法的业务逻辑有问题,需要考虑作必需的调整;,非并发死锁的解决方式Case2,case 2: 因为一些没有意料到的情况,BM2方法被运行在一个另外的线程Ser

21、vletThread2中,这时,系统会自动为BM2方法创建一个新的事务空间; 比较常见的起因: 通过BO_Client类来调用业务方法BM2,则将导致BM2方法运行在一个不同于BM1的线程空间中,从而隐含地启动了一个新的事务T2; 解决方案: 现在通过更新类ServletCallBase,可以自动将在BO方法中对BO_Client类的调用转换为普通的EJB Lookup /事务1的起始点my_table1.lock(XMode);/在此调用了insert, update, delete这三种类型的SQL语句来操作数据表my_table1,导致表my_table1被数据库加上了排他锁XMode_

22、Lock_On_my_table1; . System.SameTime(); . my_table2.operate();/需要对数据表my_table2进行操作,前提是加在数据表my_table2上的排他锁XMode_Lock_On_my_table2已经被释放; Tmit();/事务1的结束点,在此事务1要么被成功提交,要么被回滚,系统隐含调用my_table1.unlock(XMode), 从而my_table1被加的排他锁XMode_Lock_On_my_table1被释放; ,并发死锁的典型伪代码Thread2,(在ServletCall所处的线程ServletThread2当中,

23、调用某个BO的另外一个业务方法BM2.) BM2()/BO类的另外一个业务方法,其事务属性为缺省的Required T2.begin();/事务2的起始点; my_table2.lock(XMode);/在此调用了insert, update, delete这三种类型的SQL语句来操作数据表my_table2,导致表my_table2被数据库加上了排他锁XMode_Lock_On_my_table2; . System.SameTime(); . my_table1.operate();/对数据表my_table1进行select,insert,update,delete等操作,该行代码执行的

24、前提是:加在my_table1上的排他锁XMode_Lock_On_my_table1已经被释放 Tmit();/事务2的结束点,在此事务21要么被成功提交,要么被回滚,系统隐含调用my_table2.unlock(XMode), 从而my_table1被加的排他锁XMode_Lock_On_my_table2被释放; ,并发死锁的产生过程,说明: T1,T2:为两个独立的事务,分别运行在不同的Servlet线程当中,并且方法的事务属性都为缺省的Required; 死锁产生的过程: 如果存在某个时刻(System.SameTime(),以数据库服务器的时钟为准),事务T1,事务T2都已经成功地

25、分别获得了不同的排他锁XMode_Lock_On_my_table1、XMode_Lock_On_my_table2,这样的话,事务T1,事务T2之间就会发生典型的交叉死锁。,并发死锁的解决方式(一),1.确认业务方法BM1,BM2中对两个表的操作先后顺序是否是必须按照伪代码中的顺序,如果可以的话,将一些对数据表进行Select操作的SQL语句首先执行,这可以避免一部分的问题; 2.确认业务方法BM1,BM2中将对两个表my_table1,my_table2的操作分别封装在一个事务(T1,T2)是否是必须的,如果可以的话,将其中对数据表进行Delete,update,insert操作的代码片段

26、单独封装在一个独立的事务(增加一个事务属性为Request New的业务方法)中;,并发死锁的解决方式(二),3.如果1,2不能解决该问题的话,那么在程序中这个问题就是不可以解决的(事实上的确存在这种交叉死锁的可能场景),则尽量在业务流程的设计上减少该两个业务方法对应的功能节点被多人同时并发执行的机会; 4.Anyway, 最后死锁还是发生了,由数据库服务器根据其交叉死锁的解除策略,Kill掉T1,T2事务所对应的数据库进程当中的已经完成工作量较少的一个,让该事务回滚,相应业务方法报错,让用户重新执行该功能;保证另外一个业务方法正确执行;,三、交叉死锁的自动解锁,在SQL Server/Ora

27、cle中如果发生两个数据库进程之间的交叉死锁,数据库服务器将自动检测到该DeadLock不知其具体的能够检测的嵌套层次深度限制,并且选择其中一个已完成工作量较少的数据库进程作为牺牲品(DeadLock Victim),让该数据库进程的工作回滚,并返回给客户端一个错误;同时保证另外一个数据库进程正常完成;,SQL Server 解除交叉死锁返回的Exception,java.sql.SQLException: MicrosoftODBC SQL Server DriverSQL Server: detailMessage:MicrosoftODBC SQL Server DriverSQL Se

28、rver SQLState:40001根据X/Open和SQL Access Group SQL CAE 规范,SQL Error对应的数值,相应的错误信息为 串行错误 vendorCode:1205SQL Server给这个错误的厂商标记号,Oracle 解除交叉死锁返回的Exception,java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource detailMessage:ORA-00060: deadlock detected while waiting for resource SQL

29、State:61000? vendorCode:60Oracle给这个错误的厂商标记号,远程过程调用的基本概念,任何远程过程调用(RPC: Remote Procedure Call) 较本地调用而言,都需要消耗比较多的系统资源,都不应被假设为本地调用; 该过程当中发起的一方为客户端,被动响应的一方为服务器端;,客户端: 负责向服务器端发出请求,接受服务器端返回的响应;,服务器端: 负责响应客户端发出的请求,执行相应的操作,并将结果或者异常作为响应返回给客户端;,开发过程中与事务相关的一些典型错误(一),我的BO中事务属性设为“RequestNew”的业务方法为什么把不在该方法事务中的操作也回

30、滚了? A.BO还没有进行部署,或部署位置有误; B.BO的XML部署文件已经OutOfDate, 需要重新生成部署文件,重新部署; C.没有通过JNDI查找HomeObject,再Create EJB Object,然后调业务方法的方式来进行调用;(无论其调用的业务方法是在同一个BO中抑或在另外一个BO中),开发过程中与事务相关的一些典型错误(二),为什么我通过Query Analyzer工具查看到的数据库数据和我在程序中获得的数据不一致? 极可能因为你在程序中看到的数据是一个事务当中的临时数据,往往该事务最后没有能够被提交,而是被回滚掉了。所以,无论你如何在Query Analyzer中进

31、行查看,是看不到某个被回滚的事务当中的临时数据的;,NC开发中事务的缺省约定,1. EJB服务器封装了Connection,为EJB Bean提供事务管理服务。程序员不要在自己的代码中调用Connection的setTransactionIsolation (int level)、setAutoCommit(Boolean autoCommit) 、commit()、rollback()这四个方法。 2. NC中的BO对象是Session Bean, 类型为Stateless, CMT, 各个业务方法的事务属性是“Required”, 3.如果你的BO属性与缺省值不同,请提供相应的部署文件,并

32、进行部署;,NC开发中事务编程的注意点(一),1.在NC编程中,客户端程序没有事务,不能开始事务。因此,客户端程序作为调用BO对象的客户程序时,它总是处在“没有事务”的状态。 2.在服务器端,当BO类调用一个非BO类时,非BO类(如DMO类)将与调用它的BO类处在同一个事务中。如果BO类没有处在一个事务中,那么它调用的所有非BO类都不处在事务中。,NC开发中事务编程的注意点(二),3.事务要小,请求的资源要尽可能的少: 事务运行时要锁定其中的数据库资源,这样其他人就没法使用这些资源,无法使资源得到共享,同时降低了系统的并发性。Insert、Update和Delete等语句要写成影响最少的行数,

33、同时要使事务小,能够快速完成; 4.对于CMT和BMT最好不要相互嵌套,,NC开发中事务编程的注意点(三),5.尽量少使用嵌套事务: 嵌套事务有可能造成死锁,复杂的嵌套消耗大量系统资源,降低系统效率及稳定性,而且现在各种EJB中间件对嵌套事务的支持有限,推荐不超过2级。 6.在开始事务之前解决用户介入问题。 例如要把用户输入的数据写到数据库中,不要在用户输入之前开始事务,等到用户把数据输入完毕,经过检验正确后,开始事务,完成数据库的写入操作。,使用中间件及数据库的注意事项(一),1.不要使用了嵌套比较复杂的查询: 建议将嵌套子查询拆开,利用程序来进行实现,过于的依赖数据库的功能是不恰当的。对于

34、嵌套多表进行扫描的查询,以及对部分列的类型格式进行转换会严重的影响效率。建议不用嵌套子查询,用连接代替,连接的效率要比它高许多。,使用中间件及数据库的注意事项(二),2.程序中要进行运算的时候,禁止使用BigDecimal,Double to String, String to Double这几种转换。在它们进行转换的时间要远大于实际运算的时间。 3.对于业务规则的处理,尽量不要使用TRIGGER来保证数据的一致性,在业务程序中完成一致性,可以通过业务锁来完成数据一致性的控制。 4.三层结构设计中考虑计算压力的平衡,合理分布:一部分利用数据库完成。一部分使用程序完成,达到一个整体的性能提高。,

35、使用中间件及数据库的注意事项(三),5.一般插入/查询一条数据的执行时间应在几毫秒,几十毫秒之间。对复杂的查询/插入语句,可以使用如下在代码中打桩的方法对单条查询/插入进行计时: long t=System.currentTimeMillis(); /execute one row select/insert operation: long t= System.currentTimeMillis()-t; System.out.println(“ Time used for single row operation is : “+t);,使用中间件及数据库的注意事项(四),6.复杂查询可以使用

36、数据库工具查询执行路径,注意查看“Step”数目, ”Loop”, ”Scan Table”嵌套。复杂查询一定要在大数据量的情况下先在数据库中测试,符合要求后再到程序中进行调试。 7.对开单处理等对速度要求很高的业务,对查询速度,返回数据量,及算法需进行Fine-Grained Tuning,提高性能。,使用中间件及数据库的注意事项(五),8.对于中间件的访问,最好成批进行,不要每进行一个很小的操作都调用中间件,这样一方面加大了中间件的压力,另外访问中间件,通过RPC的方式,每次建立连接也要消耗时间。 9.对于大的任务,最好在程序中调用Thread.sleep(200),让出部分时间片,以供其

37、他程序使用, 以提供系统的整体吞吐率。,Acknowledgement,本PPT文档参阅或者直接引用了下列资料的部分内容: “EJB事务培训”, presented by 黎峰; “Mastering Enterprise JavaBeans ”, presented by ED Roman; “Transaction Management in J2EE”, presented by Christophe Coenraets, Sysbase Corp.; “Sun ONESun Open Net Environment”, presented by Sun microsystems Corp.; “Enterprise JavaBeans Specification, v1.1”, presented by Sun microsystems Corp.;,其它,WWW . UFSOFT . COM,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1