mysql事物处理代码_Mysql事务处理有关问题

mysql事务处理问题

今天和同学讨论起数据库事务处理的问题,感觉讨论中明白了一些,有些知识看过了,但是没有实际使用还是不理解。

事务处理就是将一系列操作当做一个原子操作,要么全部执行成功,如果执行失败则保留执行期的状态。通过提交和回滚机制来实现操作,如果全部执行成功通过提交执行commit结果就会记录到数据库中,如果执行失败通过回滚操作rollback将发生错误之前的所有错误消除,回退到原来状态。

事务都应该具备ACID特征。所谓ACID是Atomic(原子性),Consistent(一致性),Isolated(隔离性),Durable(持续性)四个词的首字母所写,下面以“银行转帐”为例来分别说明一下它们的含义:

原子性:组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。换句话说,事务是不可分割的最小单元。比如:银行转帐过程中,必须同时从一个帐户减去转帐金额,并加到另一个帐户中,只改变一个帐户是不合理的。

一致性:在事务处理执行前后,数据库是一致的。也就是说,事务应该正确的转换系统状态。比如:银行转帐过程中,要么转帐金额从一个帐户转入另一个帐户,要么两个帐户都不变,没有其他的情况。

隔离性:一个事务处理对另一个事务处理没有影响。就是说任何事务都不可能看到一个处在不完整状态下的事务。比如说,银行转帐过程中,在转帐事务没有提交之前,另一个转帐事务只能处于等待状态。

持续性:事务处理的效果能够被永久保存下来。反过来说,事务应当能够承受所有的失败,包括服务器、进程、通信以及媒体失败等等。比如:银行转帐过程中,转帐后帐户的状态要能被保存下来。

注意Mysql支持的存储引擎中,默认为MyISAM,是不支持事务处理的,一般都有InnoDB,是支持事务型的。

(1)如果对一个表进行操作的时候需要事务支持,需要配置存储引擎为InnoDB等支持事务型的。

create table XX() engine=InnoDB;

(2)默认情况下,mysql是自动提交模式(autocommit=1),此时会在每一条语句执行完毕后将所做修改立即提交,此时的commit相当于没用的,rollback只对前一句语句起作用,其实也没用,一条mysql语句默认也是原子操作,没必要。

如果设置默认事务处理,需要将自动提交模式关闭即将autocommit设置为0.

set autocommit=0;     设置模式为关闭

select @@autocommit;  查看值是否已经改变

注意,如果在客户端设置的话,设置完,之后断掉连接后再重连又恢复默认设置。每个客户端只能设置客户自己的。

(3)如果自动提交模式是打开的,则需使用语句:

start transaction;   开始事务处理

XX1;

XX2;

commit;  /  rollback;

来开始事务处理;而如果设置为关闭,则无需使用start transaction,连续语句就为事务指导rollback或者commit。

(4)注意创建、改变、删除数据库或者其中的数据定义语言以及锁有关的都不能成为事务的一部分,如下面:

start transaction; insert into test1 values("8"); create table test2(i int); insert into test1 values("8"); rollback;

欢迎大家阅读《Mysql事务处理有关问题》,跪求各位点评,by 搞代码

执行一个事务处理,当执行到要创建表时,mysql会自动提交,然后再执行创建语句。如果test1的i为主键,则第三条语句出错,回滚时test1还是插入成功,且创建了表test2.

(5)python中使用数据库,最好采用这种形式,

import MySQLdb try: conn = MySQLdb.connect(host="localhost",user="root",passwd="your passwd",db="dbName") except MySQLdb.Error,e: print "Mysql Error %d: %s" % (e.args[0], e.args[1]) else: pass #conn.close()

try: cur=conn.cursor() cur.execute('set autocommit=0') #cur.execute('start transaction') cur.execute('insert into test1 values("8")') cur.execute('insert into test1 values("8")') except MySQLdb.Error,e: conn.rollback() print "Mysql Error %d: %s" % (e.args[0], e.args[1]) else: conn.commit() cur.close() conn.close()

(6)并行处理问题

Mysql是一个多用户的系统,有多用户在同一时间访问统一数据表,MySIAM采用的是数据表级的锁定标记,来保证同一时间只有一个用户访问此表;Innodb采用了数据行级的访问机制,即两个用户可以对同一个表中不同行的数据同时进行修改,而如果是同一行,则先来的用户先锁住此行,操作结束释放锁后,下一个用户才能操作。

(7)事务处理的隔离性问题

InnoDB默认的隔离级别是repeatable read,如果某个用户两次执行同一个select语句,其结果是可重复的,如果在事务期间有用户对所要读取的数据进行了操作,那么也不会有显示,比如一个存储引擎为innodb的表,如果有一个客户用事务来select读取表数据,另一个用户此时对表做了一个插入之类的操作,第一个用户再进行同样的select读取时,显示数据是没有变化的。

(8)多语句操作非原子操作

如上面(6)中会出现一个问题,如果是一个事务操作,读取数据后,想对数据进行操作,但是可能有另外一个人对此做了操作,那再对此数据进行操作就不对了。

此时需要明确加锁来锁住表,防止别人更改数据,执行结束后释放锁。

lock tables XX write;

XXXXXX;

unlock tables;

也可以使用相对更新代替绝对更新,相对于当前值进行更新,不根据上次的值算出一个绝对值进行更新。这样避免了多条语句的非原子操作。

set a = a - 3 XXXXXXXXXXX;





1楼svap1昨天 21:29

写的详细,赞。

原创文章,转载请注明: 转载自搞代码

e7ce419cf2d6ad34d01da2ceb8829eed.png

微信 赏一包辣条吧~

023a57327877fb4402bcc76911ec18ea.png

支付宝 赏一听可乐吧~

关于mysql事务处理 public static void StartTransaction(Connection con, String[] sqls) throws Exception { if (sqls == null) { return; } Statement sm = null; try { // 事务开始 System.out.println("事务处理开始!"); con.setAutoCommit(false); // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库 sm = con.createStatement(); // 创建Statement对象 //依次执行传入的SQL语句 for (int i = 0; i < sqls.length; i++) { sm.execute(sqls[i]);// 执行添加事物的语句 } System.out.println("提交事务处理!"); con.commit(); // 提交给数据库处理 System.out.println("事务处理结束!"); // 事务结束 //捕获执行SQL语句组中的异常 } catch (SQLException e) { try { System.out.println("事务执行失败,进行回滚!\n"); con.rollback(); // 若前面某条语句出现异常时,进行回滚,取消前面执行的所有操作 } catch (SQLException e1) { e1.printStackTrace(); } } finally { sm.close(); } } 通常都是上述的写法, 在mysql 不支持事务的时候 , 中间的 setAutoCommit 的事务操作是不是都不生效. 现在innoDB支持 事务了, 上述的 java 代码是否能实现 以下的 事务隔离的 操作, 在修改的时候处于锁定状态 或者 只可以通过存储过程来实现, 单行的锁定 BEGIN; SELECT book_number FROM book WHERE book_id = 123 FOR UPDATE; --这里for update , 以前用Oracle的时候也是有这个行锁 // ... UPDATE book SET book_number = book_number - 1 WHERE book_id = 123; COMMIT;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值