网络服务器软件开发/中间件开发,关注ACE/ICE/boost

C++博客 首页 新随笔 联系 聚合 管理
  152 Posts :: 3 Stories :: 172 Comments :: 0 Trackbacks

       1.创建表测试表tb_test,如下:
--------------------------------------------------------------------
  CREATE TABLE `tb_test` (
  `id` int(32) NOT NULL COMMENT 'k',
  `name` varchar(32) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--------------------------------------------------------------------
其中id为主键,不能重复
      2.创建存储过程sp_test,如下:
-------------------------------------------------------------------
begin

  start transaction;
 insert into tb_test(id,name)  values (10000,'admin1');
 insert into tb_test(id,name)  values (10000,'admin2');

 commit;

end

---------------------------------------------------------------------
      3.现象:执行sp_test,由于id是唯一键,不能重复,所以sp_test中执行第二条insert语句时,会出现错误,后面的commit语句不会执行,也就不会提交,再次执行sp_test,报同样的错误,但观察数据表,admin1却已经被写到表里了
      4.解释:由于事务是针对当前连接的,第一次执行sp_test时,start transaction;开始了一个新的事物,第一个insert正确执行,第二个insert报错,存储过程返回,commit没有执行;第二次执行sp_test,start transaction暗含了结束该连接的上一个事务的语义,由于第一次执行时admin1被正确写入,此时提交,admin1就被真正的写到表里了。
      5.方案:第一种方案,把事物的开始,提交,回滚封装到程序里面,只在存储过程里面做具体的插入,更新操作,如果存储过程成功就提交,如果失败就回滚;第二种方案,在存储过程里面捕获异常,如果出现异常就回滚,否则就提交,具体代码为:

---------------------------------------------------------------------
begin
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
begin
rollback;
select -1;
end;

  start transaction;
 insert into tb_test(id,name)  values (10000,'admin1');
 insert into tb_test(id,name)  values (10000,'admin2');

 commit;

  select 0;
end

---------------------------------------------------------------------

这种方式,程序里面不会捕捉到任何异常,因为在存储过程里处理了,如果存储过程返回0表示成功,返回-1表示失败,如有必要也可以返回自增id
posted on 2010-09-16 15:57 true 阅读(1670) 评论(0)  编辑 收藏 引用 所属分类: mysql

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理