免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5707 | 回复: 3
打印 上一主题 下一主题

发现MYSQL事务ROLLBACK失效,有个好大的坑呀 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-11-03 15:35 |只看该作者 |倒序浏览
一直用POSTGRESQL,事务处理非常好,从没出现过问题。
今天玩了下MYSQL,版本5.6,测试事务处理时候,发现MYSQL有个好大的坑呀!
先上代码:
CREATE DEFINER=`root`@`localhost` PROCEDURE `po_instk`()
BEGIN
        declare exit handler for sqlexception rollback;

        start transaction;

    /*定义数据表:INSTK1*/
    drop table if exists instk1;   
        create  table instk1(
                doc_no varchar(30) ,
                tran_type varchar(10),
        CONSTRAINT pk_instk1 PRIMARY KEY (doc_no));
      
    insert into instk1 (doc_no,tran_type) values('INV-001','PO-IN');

/*定义数据表:INSTK2*/
    drop table if exists instk2;        
        create table instk2(
                doc_no varchar(30) ,
                part_no varchar(30),
                loc varchar(10),
                qty decimal(12,2),
        price decimal(12,2),
        CONSTRAINT pk_instk2 PRIMARY KEY (doc_no,part_no,loc));  

    insert into instk2(doc_no,part_no,loc,qty,price)   values('INV-001','A-001','CK01',10,1010);            
    insert into instk2(doc_no,part_no,loc,qty,price)   values('INV-001','A-001','CK01',10,1010);   /*此处故意与前一行重复*/
    insert into instk2(doc_no,part_no,loc,qty,price)   values('INV-001','A-002','CK01',10,21000);
    insert into instk2(doc_no,part_no,loc,qty,price)   values('INV-001','A-003','CK01',10,220);     
   
    commit;
  END


数据表INSTK2的前二行故意重复,违反主键约束,观察是否能回滚?
执行时候,发现事务ROLLBACK回滚死活都无效,总是能插入数据到表里去。
以为代码错误,把该段代码拷贝到POSTGRESQL里,稍微修改,结果POSTGRESQL拒绝提交,成功回滚,证明程序正确。

折腾了大半天,一直无法正确回滚,后来换个方法:不在存储过程里建表,先把表建好,只在里提交数据,结果发现,竟然可以成功回滚!
也就是说,如果事务处理时候里,包含DDL操作,比如建表命令,比如:CREATE TABLE ......,    POSTGRESQL事务处理则会出现问题,无法正常执行。
如果只有数据操作DML命令,比如INSERT ,UPDATE,DELETE才能成功执行。

在POSTGRESQL里,无论是否包含DML还是DDL命令,不论是临时表还是正式表,其提交和回滚均可以正常进行,
事务处理明显比MYSQL严谨,没有这样的大水坑。





论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2015-11-03 15:38 |只看该作者
比如:CREATE TABLE ......,    POSTGRESQL事务处理则会出现问题,无法正常执行。
如果只有数据操作DML命令,比如INSERT ,UPDATE,DELETE才能成功执行。
----------------------------------------------------------------------------------------
打错了,纠正:应该是: MYSQL事务处理则会出现问题,无法正常执行。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2015-11-03 16:01 |只看该作者
另外发现MYSQL的存储过程功能很弱:

1)比如没有 FOR  R IN  SELECT *  FROM TABLE LOOP这样的隐含游标循环,只有显式的游标循环,
显式的游标速度比隐含式慢很多,所以,MYSQL的游标处理效率会很慢。

2)没有ROWTYPE类型定义,对程序的类型长度只能硬定义,导致维护困难。一旦表结构数据类型长度有变动,这些对应的定义就得重新修改,简直是灾难。

3)没有行变量,比如POSTGRESQL的RECORD,处理游标时候,需要定义很多变量来一个个接收,非常麻烦,更没有类似ORACLE的索引表。

另外语法比较怪异,跟主流的写法很大差异。
比如:每定义一个变量,需要写一行的DECLARE,非常啰嗦。
没有CONTINUE,BREAK这样的跳转,用异常来处理:比如:declare  continue hander for  not found set v_notfound=1;感觉太怪异了,
没有数组处理,当需要传递数组参数和处理数组数据,就很费事了。



论坛徽章:
7
数据库技术版块每日发帖之星
日期:2015-11-17 06:20:00数据库技术版块每日发帖之星
日期:2015-11-18 06:20:00数据库技术版块每日发帖之星
日期:2015-11-30 06:20:00数据库技术版块每月发帖之星
日期:2016-01-07 23:03:06数据库技术版块每周发帖之星
日期:2016-01-07 23:06:31数据库技术版块每周发帖之星
日期:2016-01-07 23:06:47数据库技术版块每日发帖之星
日期:2016-01-14 06:20:00
4 [报告]
发表于 2015-11-14 11:38 |只看该作者
mysql中 DDL(除了truncate table)以外,都是隐式提交,也就是说,当执行了DDL语句后,会隐式执行commit操作。所以,在你的存储过程中,即使insert 语句出现了问题,表是不回滚的回复 1# tony_trh


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP