07_transaction

07_transaction

ID:34579589

大小:464.34 KB

页数:33页

时间:2019-03-08

上传者:xinshengwencai
07_transaction_第1页
07_transaction_第2页
07_transaction_第3页
07_transaction_第4页
07_transaction_第5页
资源描述:

《07_transaction》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库

数据库事务与并发n教学内容n数据库事务的概念n声明事务边界n并发问题n设置事务隔离级别n使用悲观锁解决并发问题n使用乐观锁解决并发问题PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 数据库事务的概念n事务是指一组相互依赖的操作行为,如银行交易、股票交易或网上购物。事务的成功取决于这些相互依赖的操作行为是否都能执行成功,只要有一个操作行为失败,就意味着整个事务失败。例如,Tom到银行办理转账事务,把100元钱转到Jack的账号上,这个事务包含以下操作行为:n(1)从Tom的账户上减去100元。n(2)往Jack的账户上增加100元。n显然,以上两个操作必须作为一个不可分割的工作单元。假如仅仅第一步操作执行成功,使得Tom的账户上扣除了100元,但是第二步操作执行失败,Jack的账户上没有增加100元,那么整个事务失败。n数据库事务是对现实生活中事务的模拟,它由一组在业务逻辑上相互依赖的SQL语句组成。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 数据库事务的生命周期PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn MySQL数据库系统的客户程序PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 声明事务的边界n事务的开始边界。n事务的正常结束边界(COMMIT):提交事务,永久保存被事务更新后的数据库状态。n事务的异常结束边界(ROLLBACK):撤销事务,使数据库退回到执行事务前的初始状态。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在mysql.exe程序中声明事务n每启动一个mysql.exe程序,就会得到一个单独的数据库连接。每个数据库连接都有个全局变量@@autocommit,表示当前的事务模式,它有两个可选值:n0:表示手工提交模式。n1:默认值,表示自动提交模式。n如果要察看当前的事务模式,可使用如下SQL命令:nmysql>select@@autocommitn如果要把当前的事务模式改为手工提交模式,可使用如下SQL命令:nmysql>setautocommit=0;PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在MySQL中创建支持事务的表n在MySQL中,数据库表分为三种类型:INNODB、BDB和MyISAM类型。其中InnoDB和BDB类型的表支持数据库事务,而MyISAM类型的表不支持事务。在MySQL中用createtable语句新建的表默认为MyISAM类型。如果希望创建INNODB类型的表,可以采用以下形式的DDL语句:createtableACCOUNTS(IDbigintnotnull,NAMEvarchar(15),BALANCEdecimal(10,2),primarykey(ID))type=INNODB;PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在自动提交模式下运行事务n在自动提交模式下,每个SQL语句都是一个独立的事务。如果在一个mysql.exe程序中执行SQL语句:nmysql>insertintoACCOUNTSvalues(1,'Tom',1000);nMySQL会自动提交这个事务,这意味着向ACCOUNTS表中新插入的记录会永久保存在数据库中。此时在另一个mysql.exe程序中执行SQL语句:nmysql>select*fromACCOUNTS;n这条select语句会查询到ID为1的ACCOUNTS记录。这表明在第一个mysql.exe程序中插入的ACCOUNTS记录被永久保存,这体现了事务的ACID特性中的永久性。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在手工提交模式下运行事务n在手工提交模式下,必须显式指定事务开始边界和结束边界:n事务的开始边界:beginn提交事务:commitn撤销事务:rollbackPDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在手工提交模式下运行事务n(1)启动两个mysql.exe程序,在两个程序中都执行以下命令,以便设定手工提交事务模式:nmysql>setautocommit=0;n(2)在第一个mysql.exe程序中执行SQL语句:nmysql>begin;nmysql>insertintoACCOUNTSvalues(2,'Jack',1000);n(3)在第二个mysql.exe程序中执行SQL语句:nmysql>begin;nmysql>select*fromACCOUNTS;nmysql>commit;n以上select语句的查询结果中并不包含ID为2的ACCOUNTS记录,这是因为第一个mysql.exe程序还没有提交事务。n(4)在第一个mysql.exe程序中执行以下SQL语句,以便提交事务:nmysql>commit;n(5)在第二个mysql.exe程序中执行SQL语句:nmysql>begin;nmysql>select*fromACCOUNTS;nmysql>commit;n此时,select语句的查询结果中会包含ID为2的ACCOUNTS记录,这是因为第一个mysql.exe程序已经提交事务。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 通过JDBCAPI声明事务边界nConnection类提供了以下用于控制事务的方法:nsetAutoCommit(booleanautoCommit):设置是否自动提交事务ncommit():提交事务nrollback():撤销事务PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 通过JDBCAPI声明事务边界try{con=java.sql.DriverManager.getConnection(dbUrl,dbUser,dbPwd);//设置手工提交事务模式con.setAutoCommit(false);stmt=con.createStatement();//数据库更新操作1stmt.executeUpdate("updateACCOUNTSsetBALANCE=900whereID=1");//数据库更新操作2stmt.executeUpdate("updateACCOUNTSsetBALANCE=1000whereID=2");con.commit();//提交事务}catch(Exceptione){try{con.rollback();//操作不成功则撤销事务}catch(Exceptionex){//处理异常……}//处理异常……}finally{…}PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 通过HibernateAPI声明事务边界n声明事务的开始边界:Transactiontx=session.beginTransaction();n提交事务:tx.commit();n撤销事务:tx.rollback();PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 多个事务并发运行时的并发问题n第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。n脏读:一个事务读到另一事务未提交的更新数据。n虚读:一个事务读到另一事务已提交的新插入的数据。n不可重复读:一个事务读到另一事务已提交的更新数据。n第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一事务已提交的更新数据。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 取款事务和支票转账事务n取款事务包含以下步骤:n(1)某银行客户在银行前台请求取款100元,出纳员先查询账户信息,得知存款余额为1000元。n(2)出纳员判断出存款额超过了取款额,就支付给客户100元,并将账户上的存款余额改为900元。n支票转账事务包含以下步骤:n(1)某出纳员处理一转帐支票,该支票向一帐户汇入100元。出纳员先查询账户信息,得知存款余额为900元。n(2)出纳员将存款余额改为1000元。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 并发运行的两个事务导致脏读取款事务在T5时刻把存款余额改为900元,支票转账事务在T6时刻查询账户的存款余额为900元,取款事务在T7时刻被撤销,支票转账事务在T8时刻把存款余额改为1000元。由于支票转账事务查询到了取款事务未提交的更新数据,并且在这个查询结果的基础上进行更新操作,如果取款事务最后被撤销,会导致银行客户损失100元。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 并发运行的两个事务导致第二类丢失更新取款事务在T5时刻根据在T3时刻的查询结果,把存款余额改为1000-100元,在T6时刻提交事务。支票转账事务在T7时刻根据在T4时刻的查询结果,把存款余额改为1000+100元。由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失100元。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 数据库的事务隔离级别PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 隔离级别与并发性能的关系PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 设定隔离级别的原则n隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。n对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为ReadCommitted,它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、虚读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在mysql.exe程序中设置隔离级别n每启动一个mysql.exe程序,就会获得一个单独的数据库连接。每个数据库连接都有个全局变量@@tx_isolation,表示当前的事务隔离级别。MySQL默认的隔离级别为RepeatableRead。如果要察看当前的隔离级别,可使用如下SQL命令:nmysql>select@@tx_isolation;n如果要把当前mysql.exe程序的隔离级别改为ReadCommitted,可使用如下SQL命令:nmysql>settransactionisolationlevelreadcommitted;PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 在Hibernate中设置隔离级别n在Hibernate的配置文件中可以显式的设置隔离级别。每一种隔离级别都对应一个整数:n1:ReadUncommittedn2:ReadCommittedn4:RepeatableReadn8:Serializablen例如,以下代码把hibernate.properties文件中的隔离级别设为ReadCommitted:hibernate.connection.isolation=2对于从数据库连接池中获得的每个连接,Hibernate都会把它改为使用ReadCommitted隔离级别。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 使用悲观锁Accountaccount=(Account)session.get(Account.class,newLong(1),LockMode.UPGRADE);account.setBalance(account.getBalance()-100);Hibernate执行的select语句为:select*fromACCOUNTSwhereID=1forupdate;updateACCOUNTSsetBALANCE=900…PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用悲观锁协调并发运行的取款事务和支票转账事务PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 使用乐观锁n乐观锁是由应用程序提供的一种机制,这种机制既能保证多个事务并发访问数据,又能防止第二类丢失更新问题。n在应用程序中,可以利用Hibernate提供的版本控制功能来实现乐观锁。对象-关系映射文件中的元素和元素都具有版本控制功能:n元素利用一个递增的整数来跟踪数据库表中记录的版本n元素用时间戳来跟踪数据库表中记录的版本。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制n(1)在Account类中定义一个代表版本信息的属性:privateintversion;publicintgetVersion(){returnthis.version;}publicvoidsetVersion(intversion){this.version=version;}PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制n(2)在ACCOUNTS表中定义一个代表版本信息的字段:createtableACCOUNTS(IDbigintnotnull,NAMEvarchar(15),BALANCEdecimal(10,2),VERSIONinteger,primarykey(ID))type=INNODB;PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制n(3)在Account.hbm.xml文件中用元素来建立Account类的version属性与ACCOUNTS表中VERSION字段的映射:……PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制n当Hibernate更新一个Account对象时,会根据它的id与version属性到ACCOUNTS表中去定位匹配的记录,假定Account对象的version属性为0,那么在取款事务中Hibernate执行的update语句为:updateACCOUNTSsetNAME=’Tom’,BALANCE=900,VERSION=1whereID=1andVERSION=0;n如果存在匹配的记录,就更新这条记录,并且把VERSION字段的值加1。当支票转账事务接着执行以下update语句时:updateACCOUNTSsetNAME=’Tom’,BALANCE=1100,VERSION=1whereID=1andVERSION=0;n由于ID为1的ACCOUNTS记录的版本已经被取款事务修改,因此找不到匹配的记录,此时Hibernate会抛出StaleObjectStateException。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制n在应用程序中应该捕获该异常,这种异常有两种处理方式:n方式一:自动撤销事务,通知用户账户信息已被其他事务修改,需要重新开始事务。n方式二:通知用户账户信息已被其他事务修改,显示最新存款余额信息,由用户决定如何继续事务,用户也可以决定立刻撤销事务。PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用元素对ACCOUNTS表中记录进行版本控制try{tx=session.beginTransaction();log.write("transferCheck():开始事务");Thread.sleep(500);Accountaccount=(Account)session.get(Account.class,newLong(1));log.write("transferCheck():查询到存款余额为:balance="+account.getBalance());Thread.sleep(500);account.setBalance(account.getBalance()+100);log.write("transferCheck():汇入100元,把存款余额改为:"+account.getBalance());tx.commit();//当Hibernate执行update语句时,可能会抛出StaleObjectExceptionlog.write("transferCheck():提交事务");Thread.sleep(500);}catch(StaleObjectStateExceptione){if(tx!=null){tx.rollback();}e.printStackTrace();System.out.println("账户信息已被其他事务修改,本事务被撤销,请重新开始支票转账事务");log.write("transferCheck():账户信息已被其他事务修改,本事务被撤销");}PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 利用乐观锁协调并发的取款事务和支票转账事务PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn 实现乐观锁的其他方法n如果应用程序是基于已有的数据库,而数据库表中不包含代表版本或时间戳的字段,Hibernate提供了其他实现乐观锁的办法。把元素的optimistic-lock属性设为“all”:nHibernate会在update语句的where子句中包含Account对象被加载时的所有属性:updateACCOUNTSsetBALANCE=900whereID=1andNAME='Tom'andBALANCE='1000';PDF文件使用"pdfFactory"试用版本创建www.fineprint.com.cn

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
大家都在看
近期热门
相关文章
更多
相关标签
关闭