tony_trh 发表于 2015-11-03 15:35

发现MYSQL事务ROLLBACK失效,有个好大的坑呀

一直用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;   
        createtable 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严谨,没有这样的大水坑。





tony_trh 发表于 2015-11-03 15:38

比如:CREATE TABLE ......,    POSTGRESQL事务处理则会出现问题,无法正常执行。
如果只有数据操作DML命令,比如INSERT ,UPDATE,DELETE才能成功执行。
----------------------------------------------------------------------------------------
打错了,纠正:应该是: MYSQL事务处理则会出现问题,无法正常执行。

tony_trh 发表于 2015-11-03 16:01

另外发现MYSQL的存储过程功能很弱:

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

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

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

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



i6first 发表于 2015-11-14 11:38

mysql中 DDL(除了truncate table)以外,都是隐式提交,也就是说,当执行了DDL语句后,会隐式执行commit操作。所以,在你的存储过程中,即使insert 语句出现了问题,表是不回滚的回复 1# tony_trh


   
页: [1]
查看完整版本: 发现MYSQL事务ROLLBACK失效,有个好大的坑呀