分布式事务2PC.ppt

上传人:ga****84 文档编号:319436 上传时间:2018-09-21 格式:PPT 页数:197 大小:1.27MB
下载 相关 举报
分布式事务2PC.ppt_第1页
第1页 / 共197页
分布式事务2PC.ppt_第2页
第2页 / 共197页
分布式事务2PC.ppt_第3页
第3页 / 共197页
分布式事务2PC.ppt_第4页
第4页 / 共197页
分布式事务2PC.ppt_第5页
第5页 / 共197页
点击查看更多>>
资源描述

1、第 六 讲网络环境中的软件质量,一、公共服务二、事务服务三、安全服务四、性能服务,内 容,一、公共服务,1、概念2、公共服务的接口3、公共服务的实现4、公共服务的使用方式,公共服务是中间件提供的重要功能用于对应用的约束性需求进行支持,1、概念,在所有的中间件规范中 公共服务 都是除协议、接口定义语言外的重要组成部分,DCE,线程,DCE,远程过程调用,时间,服务,命名,服务,其它基,本服务,分布式文件服务,其它服务,安,全,管,理,应用,DCE(Distributed Computing Environment),Object Services,Application Interfaces,D

2、omain Interfaces,Common Facilities,OMA:Object Management Architecture,DNA(Distributed Network Architecture),J2EE(Java 2 Platform, Enterprise Edition),设计,开发,与,管理,工具,标准技术与协议,资源层,控制器,数据,/,状态管理,通信服务,安全容器,/,模型,虚拟机,客户应用层,服务层,服务调用,服务容器,核心服务,服务提供接口(,SPI,),注册池,业务规则,/,工作流,EIS,数据库,遗留系统,消息队列,ECM,池,目录,l,一致的对象与事件

3、模型,l,一致的架构模型,SOA (Service Oriented Architecture),公共服务与构件,不同于单机环境下应用程序与程序库之间的关系:公共服务基本上不实现应用系统的功能也不会被链接到具体的应用系统中程序库可以用于实现应用系统的功能且往往被链接到应用系统中类似于单机环境下程序模块与操作系统中系统调用之间的关系:公共服务是网络环境中系统软件的一部分系统调用是单机环境中系统软件的一部分它们都可以独立运行,不依赖于具体的应用系统,公共服务的接口定义了公共服务的调用格式公共服务接口的定义方法与构件的定义方法基本相同例如:OMG不仅用IDL定义应用对象还用IDL定义公共服务SUN采

4、用Java语言的interface声明构件的接口也用它来声明底层服务的接口,2、公共服务的接口,由于实现功能的复杂性一个公共服务往往包含多个接口分别用于代表公共服务内的一组有意义的操作例如:OMG的命名服务包含两个接口:NamingContextBindingIteratorSUN的JTA包含5个接口:UserTransactionTransactionManagerTransactionSynchronizationXAResource,公共服务的具体实现方式是十分丰富的:(1)公共服务可以在应用服务器内实现(2)公共服务可以由另外一个单独的中间件产品实现(3)公共服务可以在局域网内的另一个

5、应用服务器实现这主要是因为在局域网内的许多资源需要统一管理例如负载共享服务、命名服务、安全服务等等(4)公共服务可以作为一种网络基础设施在因特网范围内对各种应用服务器进行支持在下一代因特网中这种趋势十分突出许多公共服务被实现为网络的基础设施例如:身份认证、主体标识等等,3、公共服务的实现,a,c,d,构件,容器,应用服务器,网络基础设施,b,公共服务的实现,如何向公共服务发出一条符合公共服务接口的消息以最终实现功能约束1) 代码直接调用式的使用方式在应用程序代码中直接调用服务接口存在使用直接、效率较高等优点也存在一些不足例如:不利于程序代码的复用不利于在运行过程中根据约束性需求的变化调整具体的

6、实现策略 这些不足可以通过声明式的使用方式克服!,4、 公共服务的使用方式,2) 后期声明式的使用方式应用程序代码不直接调用公共服务而是由容器(截取器)进行调用容器调用的依据是应用系统开发人员在系统组装或者部署阶段对应用程序的声明这种声明可以是针对一个类进行的也可以是针对一个具体的方法进行的声明式的使用方式也存在一些不足例如:效率有所损失,使用点受到限制等实际过程中可以结合使用两种使用方式以取得最满意的效果,二、事务服务,1、动因2、事务概念及特性3、并发控制4、分布式事务5、JAVA 事务服务,1、动因,网络环境下故障的不可避免性:通信媒介的局限性硬件的可靠性变化软件的潜在缺陷,硬件的可靠性

7、变化:,时间,发生故障的概率,1,导致:电源停电、介质信息丢失等故障,浴盆曲线,逻辑越来越复杂集成带来的特征交互越来越多,软件的潜在缺陷,导致:内存泄露、访问冲突、特征干扰等问题,如何面对错误?,在高层(操作层)进行处理,保持系统的正确性、完整性,例如:银行转帐系统,A,B,从银行A的帐号a向银行B的帐号b转帐 ¥10000.00(1)将A的帐号a中的金额减 ¥10000.00(2)将B的帐号b中的金额加 ¥10000.00,该过程中任何一个环节都可能出错!如何保证系统的可接受性?,访问冲突,网络环境下存在各种资源:处理器存储器外部设备数据库软件构件为提高资源利用率,往往允许许多客户能够访问它

8、们当它们同时访问同一资源时,访问冲突即可能发生例如:更新丢失(lost updates)不一致的读取(inconsistent retrieval),更新丢失问题,存在3个银行帐号A、B、C帐面金额分别为:¥1000,¥2000,¥3000客户C1 从帐号A向帐号B转 ¥400客户C2 从帐号C向帐号B转 ¥300正常结束时 帐号A减少 ¥400帐号C减少 ¥300帐号B增加 ¥700假如 C1、C2 同时访问 B(同时读取、写回B的金额)得到的结果可能是:帐号A减少 ¥400帐号C减少 ¥300帐号B增加 ¥400C2的更新丢失了!,客户C1:从帐号A向帐号B 转 ¥400将帐号A上的金额减

9、 ¥400将帐号B上的金额加 ¥400,客户C2:从帐号C向帐号B 转 ¥300将帐号C上的金额减 ¥300将帐号B上的金额加 ¥300,Balance:=A.read() ¥1000A.write(balance -400) ¥600balance:=C.read() ¥ 3000C.write(balance-300) ¥ 2700balance:=B.read() ¥2000balance:=B.read() ¥ 2000B.write(balance + 300) ¥ 2300B.write(balance + 400) ¥2400,结果:客户C2的更新操作被丢失,不一致的读取问题,存

10、在3个银行帐号A、B、C帐面金额分别为:¥1000,¥2000 ,¥3000客户C1 从帐号A向帐号B转 ¥400客户C2 计算三个帐号的总额正常结束时 总额为 ¥6000假如 C1、C2 同时操作得到的结果可能是:总额为 ¥5600 总额计算错误!,客户C1:从帐号A向帐号B转 ¥400将帐号A上的金额减 ¥400将帐号B上的金额加 ¥400,客户C2:计算三个帐号的总额,Balance:=A.read() ¥1000A.write(balance -400) ¥600balance:=A.read() ¥ 600balance:=balance+B.read() ¥ 2600balance

11、:=balance+B.read() ¥ 5600balance:=B.read() ¥2000B.write(balance + 400) ¥2400,结果:客户C2得到的帐号总额为 ¥5600,与实际总额不一致!,解决上述问题需要掌握如下信息:该操作包括哪些低层操作?这些低层操作涉及哪些持久数据?这些操作的运行结果如何?如果出现错误怎样处理?,类似的问题已经出现在数据库管理系统分布式操作系统等领域,解决该问题的关键概念:事务(Transaction),2、事务概念及特性,事务是一系列操作它们或者全部完成或者全部不做,事务的ACID特性事务的启动、提交与终止事务的类别事务的支持机制,(1)事

12、务的ACID属性,Atomicity原子性 Consistency一致性 Isolation分离性 Durability持久性,原子性(Atomicity)事务或者被全部执行或者任何修改都不起作用事务的起点是 回卷点也是重复执行的起点事务的终点是下一个事务的起点,共享的资源(的状态)需要保持一致在下面情形中容易产生不一致的状态:多个并发事务在互相不知晓的情况下结束应用系统 定义一致性,并负责保证一致性如果事务不能解决不一致问题事务可以被终止,一致性(Consistency),分离性(Isolation),每个事务访问资源时任何其它事务的存在皆是透明的在事务执行过程中任何其它事务进行的修改皆是不

13、可见的通过下列途径实现:两阶段锁乐观并发控制,持久性(Durability),对于一个完成的事务其结果总是持久的 尽管后来的事务可以进一步修改其结果的值在事务结束之前被修改的资源的状态必须被保存到持久存储体中例如:磁盘持续性RAMEPROM等,Begin: 启动一个新事务Commit: 结束一个事务存储事务过程所做的修改使得修改可以被其它事务访问Abort:结束一个事务取消事务过程所做的所有修改,(2)事务的启动、提交与终止,Begin,Commit,Abort,(3)事务的类别 平坦的事务与嵌套的事务,平坦事务:Flat Transactions,Main Transaction,Call,

14、Call,Call,Commit,BeginTrans.,BeginTrans.,Commit,BeginTrans.,Commit,BeginTrans.,Commit,嵌套事务:Nested Transactions,(4)事务的支持机制单机环境下:并发控制(2PL)多机环境下:全局控制(分布式事务:2PC),3、并发控制,1)概述2)两阶段锁(Two Phase Locking :2PL)3)乐观并发控制(Optimistic Concurrency Control)4)比较(Comparison),可串行化(Serializability)避免死锁(Deadlock Freedom)公

15、平(Fairness)并发粒度(Degree of Concurrency)复杂度(Complexity),1)概述,评价并发算法的准则,2)两阶段锁,应用最广泛的并发控制技术RDBMSs (Oracle, Sybase, DB/2, etc.)ODBMSs (O2, ObjectStore, Versant, etc.)Transaction Monitors (CICS, etc)并发过程需要对共享的资源进行加锁控制如果锁操作与当前资源的状态不冲突,可以得到锁控制两阶段锁机制保证操作的可串行化,锁是一个标记,标明一个进程正在以某种模式访问一个资源最小的锁模式为:读、写锁被用来指示多个并发进

16、程对某一资源的当前使用状态,加锁:Locking,进程在访问共享的资源之前,必须获得所有的锁 在访问共享的资源之后,必须释放所有的锁2PL: 进程一旦开始释放锁,它再不能获取其它的锁一个典型的 2PL 加锁过程为:,所获得的锁的数目,时间,锁的兼容性,进程是否能够获得锁取决于所请求的锁是否与资源目前的锁状态(其它进程已请求的锁)兼容兼容性由锁兼容性矩阵决定最小的锁兼容性矩阵:,Read,Write,Read,+,-,Write,-,-,锁冲突,如果所请求的锁与资源的锁状态不兼容,则不能获得所请求的锁这被称为“锁冲突”处理锁冲突的方法有:强迫请求进程等待,直到冲突的锁被释放告诉请求进程,无法获得

17、所请求的锁,死锁,2PL 可能导致死锁状态在该状态下,多个进程分别获取部分所需的资源,并互相等待其它进程释放资源死锁必须通过终止一个或多个相关的进程才能得到解决这需要被终止的进程放弃它们已经进行的所有操作解决死锁的核心在于避免死锁,锁粒度,2PL适用于任意粒度的资源并发程度高的进程将需要小粒度的锁机制小粒度的锁机制将导致需要较大数目的锁实现这将导致系统开销的增加因此,在实现具体系统时,需要在并发度与锁开销之间进行权衡层次锁是其中的一种折中方案,层次锁,用于内部包含其它内容的资源例如:文件 (包含多条记录)集合或序列 (包含对象)锁状态增加了intention read (IR) 与 inten

18、tion write (IW) 用于标识资源祖先的状态锁的兼容性:,R,w,IR,IW,R,+,-,+,-,w,-,-,-,-,IR,+,-,IW,-,-,+,+,+,+,锁的透明性,谁请求锁?并发控制基础设施构件的实现体构件的客户第一种情形很好,但不易实现:基础设施必须管理所有资源基础设施必须掌握所有对资源的访问最后一种情形是不期望的、需要避免的!,3)乐观并发控制,2PL的复杂度与被访问资源的数目呈线性关系如果冲突发生的概率较小时,开销偏大乐观并发控制的思路是:进程首先修改资源状态的(逻辑)副本验证并发进程之间的冲突如果没有冲突:写回副本否则:取消所有修改并重新开始,4)比较,共性:都保证

19、可串行化需要一个取消过程两阶段锁: 锁开销较大可能出现死锁在易于冲突时工作得好乐观控制: 冲突概率小时开销小不会出现死锁在分布式系统中冲突集合的计算复杂时间同步开销较大,4、分布式事务,1)基本概念2)两阶段提交,1)基本概念,分布式事务 是涉及多个服务器(结点)的事务例如:在不同银行之间进行转帐!,事务是一系列操作它们或者全部完成或者全部不做,单机环境:,多机环境:,处理逻辑,单机控制机制,处理结点,单阶段提交(不加控制): 客户直接向各结点发出提交命令 如果某一结点提交失败则重复提交命令不足: 客户发出命令时,结点无权力终止事务,问题:如何保证参与事务的各个结点 皆正确提交(Commit)

20、?,解决方式:基于单结点的并发控制机制(每个结点保证本结点操作的事务性)提供两阶段提交(two-phase commit)机制,与分布式事务相关的分布式系统组成部分可以被划分为如下三种角色:事务性客户( Transactional Client )事务性服务器( Transactional Server )协调器( Coordinator ),事务性服务器,事务性客户,协调器,事务性客户,仅通过协调器获取与事务相关的具体操作内容通过访问协调器 进行 事务的启动与提交动作事务的实现 对于事务性客户是透明的对于事务性客户而言,一个服务器是否是事务性的是透明的,分布式事务的启动者与提交者,事务性服务

21、器,每个事务性服务器在事务协调器的控制下访问、修改 资源事务性服务器必须能随时访问协调器事务性服务器必须在事务启动时向协调器注册 以便于协调器进行控制事务性服务器必须实现事务协议(两阶段提交协议),分布式事务具体操作的执行者,协调器,实现分布式事务的关键部件分布式事务协调者负责处理事务的“开始”、“提交”以及“终止”操作分布式事务协调器需要定位事务标识不同的事务可以拥有不同的分布式事务协调器,分布式事务执行的控制者,Phase one: 投票(Voting)Phase two: 完成(Completion),2)两阶段提交,Phase One,投票阶段协调器询问各服务器是否能够(愿意)进行提交

22、操作?各个服务器回应: Yes: 表明可以根据指令进行提交但尚不知道是否真的将执行提交动作 No: 表明终止当前的操作因此:服务器可以单方面地终止一个事务但不能单方面地提交一个事务,Phase Two,完成阶段协调器收集投票,并决策:如果每个服务器皆投 Yes,则进行提交如果任何一个服务器投 No,则进行终止所有投 Yes 的服务器将接受到: DoCommit 命令,如果事务将被提交 Abort命令,如果事务不能被提交各服务器提交自己包含的事务操作并对“DoCommit ”命令给予回复(HaveCommitted),服务器的不确定时期,服务器在投“Yes”票后,处于能够提交,但不清楚是否必须提

23、交的状态该时间段被称为server uncertainty期通常该时间段很短 协调器从接受到处理各投票的时间段仍然可能存在故障(小概率事件),导致系统发生错误,两阶段提交的恢复,2PC启动(各服务器开始投票)之前发生的任何故障将导致“终止”协调器在“提交决策”之前发生错误将导致“终止”在该时刻之后(进行“提交决策”)发生故障,协调器将重启动(该过程中协调器保存了事务参与者的信息),然后,重新对所有提交消息进行决策如果在投票之后、提交之前发生故障,服务器将在重新启动后,通知协调器重新计算投票结果如果提交之后、回复之前发生故障,服务器将在重新启动后,向协调器发送 HaveCommitted 消息,

24、Coordinator,server,step status,step status,prepared to commit(uncertain),Prepared to commit(waiting for votes),committed,committed,done,1,2,3,4,Can commit?,yes,DoCommit,HaveCommitted,两阶段提交的过程:,5、JAVA 事务服务,1)EJB事务模型2)JTA3)EJB事务情景4)构件提供者的责任5)应用系统装配者的责任,1)EJB事务模型,EJB模型中的分布式事务服务涉及5个部分:事务管理器:transaction

25、manager应用服务器:application server资源管理器:resource manager应用系统: application program通讯资源管理器:communication resource manager通过实现相互之间的接口它们共同完成事务过程,事务管理器 提供的服务与管理功能包括:事务声明事务性资源管理同步事务上下文传播 应用服务器 (或者是传统的 TP monitor) 提供事务处理的基础设施以支持 应用的运行环境(包括事务语句管理)这样一个应用服务器的例子是EJB server,资源管理器 (通过一个资源适配器) 提供应用对资源的访问资源管理器实现一个事务资

26、源接口 事务管理器通过该接口进行事务关联事务完成及事务恢复工作这样一个资源管理器的例子是一个关系数据库服务器,事务性应用系统依赖于应用服务器提供的事务属性声明 来提供事务管理支持这样一个应用系统的例子是利用EJB构件体系结构开发出来的应用系统一些独立的Java 客户程序也希望 通过使用由 应用服务器或事务管理器 提供的高层接口声明事务边界通讯资源管理器 向进入、发出的请求提供 事务上下文传播及访问事务服务 等功能,JTA 与 JTS,Java Transaction API (JTA) 是一个事务管理器 与参与分布式事务处理的其他部分例如:应用系统资源管理器应用服务器 等 之间的接口规范Jav

27、a Transaction Service (JTS) API 是 CORBA OTS规范的一个实现提供了在服务器之间利用IIOP传播事务上下文的互操作例如,一个EJB 服务器厂商可以使用一个 JTS实现 作为低层的事务管理器 EJB 体系结构不要求EJB 容器支持JTS 接口EJB 体系结构要求EJB 容器支持JTA 接口,2)JTA,Java Transaction API 包含三部分:一个高层应用系统事务声明接口: UserTransaction 由事务性客户使用一个高层事务管理器接口 TransactionManager Transaction Synchronization由应用服务

28、器使用一个标准的X/Open XA 协议的JAVA 实现 XAResource 由事务性资源管理器使用,UserTransaction 接口,UserTransaction 接口向应用系统提供控制事务边界的能力可被Java 客户程序或者EJB 构件使用其中,begin 方法启动一个全局性事务并将事务与调用者线程关联transaction-thread关联 由事务管理器透明地管理,public interface javax.transaction.UserTransactionpublic abstract void begin();public abstract void commit();

29、public abstract int getStatus();public abstract void rollback();public abstract void setRollbackOnly();public abstract void setTransactionTimeout(int seconds);,interface javax.transaction.Statuspublic final static int STATUS_ACTIVE;public final static int STATUS_COMMITTED;public final static int STA

30、TUS_COMMITTING;public final static int STATUS_MARKED_ROLLBACK;public final static int STATUS_NO_TRANSACTION;public final static int STATUS_PREPARED;public final static int STATUS_PREPARING;public final static int STATUS_ROLLEDBACK;public final static int STATUS_ROLLING_BACK;public final static int S

31、TATUS_UNKNOWN;,下面的代码段展示了一个构件管理事务的会话构件对UserTransaction 的使用/ In the session beans setSessionContext method,/ store the bean context in an instance variableSessionContext ctx = sessionContext;/ somewhere else in the beans business logicUserTransaction utx = ctx.getUserTransaction();/ start a transactio

32、nutx.begin();.do work/ commit the mit();,EJB服务器 中对 UserTransaction 的使用,如果应用服务器支持由事务性客户执行的事务声明应用服务器必须支持客户程序通过JNDI方式获得UserTransaction 对象应用一个通过系统属性获得 UserTransaction 名字字符串的例子为:/ get the system property value configured by administratorString utxPropVal = System.getProperty(“jta.UserTransaction”);/ use

33、JNDI to locate the UserTransaction objectContext ctx = new InitialContext();UserTransaction utx = (UserTransaction)ctx.lookup(utxPropVal);/ start transaction work.utx.begin();. do mit();,事务性客户中对 UserTransaction 的使用,TransactionManager 接口,TransactionManager 接口允许应用服务器 根据被管理应用系统的需求控制事务边界例如:EJB容器为事务性EJB构

34、件 管理事务状态 容器利用 TransactionManager 接口 声明事务边界事务管理器将与线程关联的事务上下文作为其内部数据结构的一部分 进行维护线程的事务上下文或者为空或者指向一个全局事务多个线程可能同时与同一个全局事务关联,interface javax.transaction.TransactionManagerpublic abstract void begin();public abstract void commit();public abstract int getStatus();public abstract Transaction getTransaction();

35、public void resume(Transaction tobj);public abstract void rollback();public abstract void setRollbackOnly();public abstract void setTransactionTimeout(int seconds);public abstract Transaction suspend() ;,Transaction 接口应用于 与目标对象关联的事务的操作当事务被创建时每个全局事务皆被与一个事务对象关联事务对象可被用于: 注册事务涉及的事务性资源 注册事务同步回调函数 提交或者卷回事

36、务 获得事务的状态,Transaction 接口,由应用服务器进行资源登记的目的在于: 通知 事务管理器 资源管理实例参与该全局事务这允许事务管理器通知参与的资源管理器有关所执行工作的信息 使事务管理器将每个事务使用的资源进行分组 使事务管理器引导事务管理器与资源管理器之间的两阶段提交事务协议,interface javax.transaction.Transaction public abstract void commit(); public abstract boolean delistResource(XAResource xaRes, int flag); public abstra

37、ct boolean enlistResource(XAResource xaRes); public abstract int getStatus(); public abstract void registerSynchronization(Synchronization sync); public abstract void rollback(); public abstract void setRollbackOnly();,synchronization 接口允许应用服务器在事务提交之前与之后的时刻 获得从事务管理器发来的通知对于每次事务启动,应用服务器都可能注册一个事务 Synch

38、ronization 回调将被事务管理调用的对象: beforeCompletion 方法在两阶段提交之前被调用该方法在即将被提交的事务的上下文中执行 afterCompletion 方法在两阶段提交之后被调用事务的状态以参数的方式被提供,interface javax.transaction.Synchronizationpublic abstract void beforeCompletion();public abstract void afterCompletion(int status);,XAResource 接口,.XAResource 接口是 基于X/Open CAE规范的XA

39、 接口的Java 实现XAResource 接口定义资源管理器与 事务管理器 在分布式事务处理环境之间的契约一个资源管理器的资源适配器实现XAResource 接口以支持 全局事务与事务资源的关联例如一个与关系数据库的连接,public interface javax.transaction.xa.XAResourcepublic abstract void commit(Xid xid, boolean onePhase);public abstract void end(Xid xid, int flags);public abstract void forget(Xid xid);pub

40、lic abstract int getTransactionTimeout();public abstract boolean isSameRM(XAResource xares);public abstract int prepare(Xid xid);public abstract Xid recover(int flag);public abstract void rollback(Xid xid);public abstract boolean setTransactionTimeout(int seconds);public abstract void start(Xid xid,

41、 int flags);,3)EJB事务情景,对多个数据库的更新,包含消息与数据库更新的事务,通过多个EJB服务器进行的数据库的更新,客户管理的事务声明,容器声明的事务声明,4)构件提供者的责任,Bean-managed 与 container-managed,当设计一个企业级构件时构件提供者必须决定由构件在业务方法中声明事务(构件管理的事务声明)还是由容器根据部署描述中的事务属性声明事务(容器管理的事务声明)一个会话构件或者消息驱动的构件可以 被设计为bean-managed 的事务声明或者 被设计为container-managed 事务声明但同时只能是其中的一个一个实体构件必须总是被设计

42、为container-managed 事务声明,利用 bean-managed 事务声明的构件,一个有态构件实例可以 但不必须在业务方法返回前提交一个启动的事务如果一个事务在业务方法结束时还没有被提交容器保持事务与实例之间的关联直到实例最终完成事务一个无态构件必须在事务方法返回前提交一个事务一个消息驱动的构件必须在onMessage方法返回前提交一个事务,public class MySessionEJB implements SessionBean EJBContext ejbContext;public void someMethod(.) javax.transaction.UserTr

43、ansaction ut;javax.sql.DataSource ds1, ds2;java.sql.Connection con1, con2;java.sql.Statement stmt1, stmt2;InitialContext initCtx = new InitialContext();/ obtain con1 object and set it up for transactionsds1 = (javax.sql.DataSource)initCtx.lookup(“java:comp/env/jdbc/Database1”);con1 = ds1.getConnection();stmt1 = con1.createStatement();/ obtain con2 object and set it up for transactionsds2 = (javax.sql.DataSource)initCtx.lookup(“java:comp/env/jdbc/Database2”);con2 = ds2.getConnection();stmt2 = con2.createStatement();,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 重点行业资料库 > 1

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。