理解事务处理事务处理的隔离级别,和使用JDBC进行事务处理

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

理解事务处理、事务处理的隔离级别,和使用JDBC进行事务处理事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性(ACID):原子性、一致性、隔离性和持久性,只有这样才能成为一个事务。原子性Atomic事务中包含的操作被看作一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。一致性Consistency只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。隔离Isolation事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并发事务的修改必须与其他并发事务的修改相互独立。持久性Durability事务完成之后,它对于系统的影响是永久性的。事务的并发控制如果不对事务进行并发控制,并发事务的无序执行将会破坏数据的完整性。事务并发执行可能导致的异常可以分为以下几种情况。Lostupdate(丢失更新)A和B事务并发执行,A事务执行更新后,提交;B事务在A事务更新后,B事务结束前也做了对该行数据的更新操作,然后回滚,则两次更新操作都丢失了。DirtyReads(脏读)A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据。Non-repeatableReads(非重复读)A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了。Secondlostupdates(第二类丢失更新,可以称为覆盖更新):是非重复读的一种特殊情况,即A事务更新数据,然后B事务更新该数据,A事务查询发现自己更新的数据变了。PhantomReads(幻像读)A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了。数据库的隔离级别一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。为了兼顾并发效率和异常控制,在标准SQL规范中,定义了4个事务隔离级别。ReadUncommitted(未提交读):即使一个更新语句没有提交,别的事务也可以读到这个改变。如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据。ReadCommitted(已提交读):更新语句提交以后别的事务才能读到这个改变。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。RepeatableRead(可重复读):在同一个事务里面先后执行同一个查询语句的时候,确保得到的结果是一样的。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。Serializable(串行化):事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。隔离级别对并发的控制各隔离级别对各种异常的控制能力如下表所示,其中Y表示会出现该种异常,N表示不会出现该种异常。丢失更新脏读非重复读覆盖更新幻像读未提交读YYYYY已提交读NNYYY可重复读NNNNY串行化NNNNNJDBC事务处理JDBC程序员要负责启动和结束事务,从而确保数据的逻辑一致性。程序员必须定义数据修改的顺序,使数据的修改与业务规则保持一致。程序员将这些修改语句放在一个事务中,使数据库引擎能够强制该事务的物理完整性。Connection接口定义了事务处理相关的方法:voidsetAutoCommit(booleanautoCommit)设置是否自动提交事务,默认为自动提交。setAutoCommit(false)开始一个事务。voidsetTransactionIsolation(intlevel)设置事务的隔离级别,事务隔离级别影响事务的并发执行能力。voidcommit()提交事务,使修改动作生效。voidrollback()回滚事务,撤销修改动作。JDBC事务处理的例子这个例子实现了系统内转账的功能,将付款账号的金额减去1000元,而收款账号的金额加上1000元。这要求两条update语句处于一个事务中,以确保操作的原子性。系统采用MySQL数据库,需要注意的是MySQL表的默认类型MyISAM是不支持事务的,需要使用表类型InnoDB来支持事务。账号表的名字是account,字段有账号account_number、开户人姓名name、账户金额money。以下SQL语句创建账号表并插入两条记录。createtableaccount(account_numbervarchar(30)primarykey,/*账号*/namevarchar(100),/*开户人姓名*/moneydouble/*账户金额*/)type=InnoDBdefaultcharactersetgbk;/*插入张三的账号,金额是1万元*/insertintoaccount(account_number,name,money)values('9558810111741234567','张三',10000.00);/*插入李四的账号,金额也是1万元*/insertintoaccount(account_number,name,money)values('9558810212854321789','李四',10000.00);以下Java程序(Transaction.java)实现转账的功能,将两条update语句放在一个事务里,确保这两条update语句要么全执行成功,要么全执行失败,从而保证数据的完整性。packagecn.oakcms;importjava.sql.*;publicclassTransaction{publicstaticvoidmain(String[]args){Connectionconn=null;//连接对象PreparedStatementpstmt=null;//预编译的SQL语句对象try{//加载MySQL驱动程序Class.forName(com.mysql.jdbc.Driver);//连接字符串Stringurl=jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=gbk;//建立数据库连接conn=DriverManager.getConnection(url,root,);//设置事务的隔离级别conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);//设置自动提交为false,开始事务conn.setAutoCommit(false);//带参数的更新语句Stringsql=updateaccountsetmoney=money+?whereaccount_number=?;//准备语句pstmt=conn.prepareStatement(sql);//绑定参数,执行更新语句,将张三的账户金额减去1000元pstmt.setDouble(1,-1000.00);pstmt.setString(2,9558810111741234567);pstmt.execute();//绑定参数,执行更新语句,将李四的账户金额增加1000元pstmt.setString(1,一千元);//绑定了非法参数pstmt.setString(2,9558810212854321789);pstmt.execute();//将抛出SQL异常//提交事务conn.commit();System.out.println(事务已提交,转账成功!);//关闭语句、连接pstmt.close();conn.close();}catch(Exceptione){try{conn.rollback();//回滚事务System.out.println(事务回滚成功,没有任何记录被更新!);}catch(Exceptionre){System.out.println(回滚事务失败!);}e.printStackTrace();}finally{if(pstmt!=null)try{pstmt.close();}catch(Exceptionignore){}if(conn!=null)try{conn.close();}catch(Exceptionignore){}}}}由于程序中第2条更新语句绑定了错误的参数“一千元”,将会抛出SQLException,程序在catch语句块中回滚事务。程序的输入如下:事务回滚成功,没有任何记录被更新!com.mysql.jdbc.MysqlDataTruncation:Datatruncation:TruncatedincorrectDOUBLEvalue:'һǧԪ'atcom.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3513)atcom.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3447)atcom.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951)atcom.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101)atcom.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2554)atcom.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1761)atcom.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1021)atcn.oakcms.Transaction.main(Transaction.java:57)

1 / 4
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功