事务来实现 ?????
这里事务该如何进行改写下面的 存储过程
CREATE PROCEDURE `ba`(id int)
beginlock table ba2 read;
update ba2 a, (select max(a) as aa from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
unlock tables;
end;
(附后 CREATE TABLE `ba2` (
`b` int(11) default NULL,
`a` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; )[ 本帖最后由 liyihongcug 于 2010-1-26 15:38 编辑 ]
这里事务该如何进行改写下面的 存储过程
CREATE PROCEDURE `ba`(id int)
beginlock table ba2 read;
update ba2 a, (select max(a) as aa from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
unlock tables;
end;
(附后 CREATE TABLE `ba2` (
`b` int(11) default NULL,
`a` int(11) NOT NULL auto_increment,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; )[ 本帖最后由 liyihongcug 于 2010-1-26 15:38 编辑 ]
begin
START TRANSACTION ;
update ba2 a, (select max(a) as aa from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
COMMIT;
end;
我的mysql是5.1版本,表是innoDB
procedure1:
set autocommit = 0;
start transaction;
****
commit;procedure2:
update a set a.b = 1 where id =1;
问题1:
mysql默认autocommit =1
如果执行了procedure1后,会不会对下次执行procedure2有影响??
就是说执行了procedure1后,procedure2执行时autocommit是不是还是1???
问题2:
mysql是不是对如下存储过程自动执行事务?
procedure3:
update a set a.id = 1 where id =2;
update b set b.id = 1 where id =2; * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP回复次数:43 * wwwwb用户头像
* wwwwb
*
*
* 等 级:
* 9 10 16
#1楼 得分:0回复于:2009-05-06 10:17:13
1、应该只是在SP1中有用,除非在连接后直接设置set autocommit=0;
2、如果没有设置set autocommit=1,应该是直接执行SQL语句,存入表中。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP精华推荐:vfp导出excel的方法探讨 * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#2楼 得分:0回复于:2009-05-06 10:17:25
问题1:
如果执行了procedure1后,会不会对下次执行procedure2有影响??
会影响就是说执行了procedure1后,procedure2执行时autocommit是不是还是1???
是0在同一个connection中是同一个autocommit变量。任何时候的修改都会影响后面的。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP精华推荐:关于mysql 的btree索引(ACMAIN_CHM请进) * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#3楼 得分:0回复于:2009-05-06 10:18:49
问题2:
mysql是不是对如下存储过程自动执行事务?不是,要看你的autocommit设置,如果是ON, 则每句SQL后都会自动提交。如果是OFF,则要等到commit;或者DDL等之关的语句来隐式提交。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP精华推荐:征集MySQL 乱码现象 * wwwwb用户头像
* wwwwb
*
*
* 等 级:
* 9 10 16
#4楼 得分:50回复于:2009-05-06 10:19:00
2、如果没有设置set autocommit=0,应该是直接执行SQL语句,存入表中
将立刻将更新存储到磁盘上。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP精华推荐:一个貌似高深的MDX计算问题(价格指数) * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#5楼 得分:0回复于:2009-05-06 10:23:43
谢谢各位高手 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP精华推荐:[讨论下]:数据类型的比较与选择 * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#6楼 得分:50回复于:2009-05-06 10:27:48
其实你自己做个测试就知道了。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * wwwwb用户头像
* wwwwb
*
*
* 等 级:
* 9 10 16
#7楼 得分:0回复于:2009-05-06 10:31:53
1、在SP1中设置后,autocommit变更为你的设置值,但重新启动后恢复为
MYSQL默认值 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#8楼 得分:0回复于:2009-05-06 10:36:39
重启当然会恢复my.ini文件中的值或者你启动命令参数中的值了。但对这个问题
如果执行了procedure1后,会不会对下次执行procedure2有影响??同一connection 中你做个实现就很容易知道了。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#9楼 得分:0回复于:2009-05-06 10:59:19
做了个小试验
在ems sql manager 2007 for mysql
pro1:
name :test1
para: _name varchar(10) _id intset autocommit = 0;
start transaction;
update product set name = _name where id = _id;
update product set code =_name where id=_id;
commit;pro2:
name :test2
para: _name varchar(10) _id intupdate product set name = _name where id = _id;
update product set code =_name where id=_id;先调用test1
call test1('test1',3)
执行成功
id 为3 的产品 name 和 code 改为test1再试用 test2
call test2('test2',3)id 为3 的产品name 和 code 也被改为了test2
按照上面的说法,调用 test2时应该改不了啊?
还是我测试有问题?? * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#10楼 得分:0回复于:2009-05-06 11:05:46
在SP2中没有显式 start transaction * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#11楼 得分:0回复于:2009-05-06 11:07:48
又试了一次
1.call `test1`('test1',3) ;
2.rollback;3.call `test2`('test2',3) ;
4.rollback;
执行 name code
1 test1 test1
3 test2 test2
一起执行 name code
1,2 test1 test1
3, 4 test1 test1//没有变成test2 test2
1,2,3,4 test1 test1 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#12楼 得分:0回复于:2009-05-06 11:08:52
表引擎是什么? * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#13楼 得分:0回复于:2009-05-06 11:14:01
我现在做这个试验的目的是
我有的procedure 有
set autocommit =0;
start transaction;
commit;有的procedure 没有
可能直接就是
create prcedure p
begin
update table set a =1 where id = 2;
end
没有进行事务处理没有进行事务处理的还很多
我在试验要不要把每个像这种一条语句的存储过程加上事务处理
像下面这样
create prcedure p
begin
start transaction;
update table set a =1 where id = 2;
commit;
end * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#14楼 得分:0回复于:2009-05-06 11:15:26
InnoDB * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#15楼 得分:0回复于:2009-05-06 11:46:05
最好显式
start transaction;
.....
commit; * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#16楼 得分:0回复于:2009-05-06 11:57:42
现在我没有加start transaction;
只有commit;
应该没有问题吧 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#17楼 得分:0回复于:2009-05-06 12:23:50
一个简单的试验,你可以看到在 p1中设置的autocommit=0,运行完p1,p2后然后rollback会把p1,p2把插入的记录全部回滚掉。SQL code mysql> create table tab1 ( -> id int primary key -> ) ENGINE=InnoDB ; Query OK, 0 rows affected (0.09 sec) mysql> insert into tab1 values (1); Query OK, 1 row affected (0.08 sec) mysql> select * from tab1; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) mysql> mysql> CREATE PROCEDURE p1 () -> BEGIN -> set @@autocommit =0; -> insert into tab1 values (11); -> end -> // Query OK, 0 rows affected (0.00 sec) mysql> CREATE PROCEDURE p2 () -> begin -> insert into tab1 values (12); -> end -> // Query OK, 0 rows affected (0.00 sec) mysql> delimiter ; mysql> mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec) mysql> call p1(); Query OK, 1 row affected (0.00 sec) mysql> select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 0 | +--------------+ 1 row in set (0.00 sec) mysql> call p2(); Query OK, 1 row affected (0.00 sec) mysql> select * from tab1; +----+ | id | +----+ | 1 | | 11 | | 12 | +----+ 3 rows in set (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.05 sec) mysql> select * from tab1; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) mysql> * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#18楼 得分:0回复于:2009-05-06 12:48:48
谢谢,
对于set autocommit = 0;
如果执行成功需要 commit;
如果不成功,要不要显示 执行rollback?如果需要的话,根据什么来判断多个update 或 delete 都执行成功了呢?
感觉mysql手册讲得不详细 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#19楼 得分:0回复于:2009-05-06 13:02:50
执行的结果可以在你的程序中进行判断,如C++你可以直接通过try catch 来捕获错误。在catch 中进行 rollbck * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#20楼 得分:0回复于:2009-05-06 13:17:59
我是想在存储过程里直接判断是否成功,成功commit;失败rollback;不知道有没有什么系统变量或其他的来进行判断 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#21楼 得分:0回复于:2009-05-06 13:25:54
你可以用 ROW_COUNT() 来确认多少条记录被更新,删除,插入。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#22楼 得分:0回复于:2009-05-06 13:30:35
ROW_COUNT() 函数
或者
error_count 变量 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#23楼 得分:0回复于:2009-05-06 13:57:04
1、只有InnoDB支持事务;
2、我是想在存储过程里直接判断是否成功执行成功是指SQL语句吧?即SQL语句没有问题还是执行SQL语句的结果?前者:可以用捕获错误方法得到,
· Handler type (CONTINUE, EXIT)//处理类型,继续或退出
· Handler condition (SQLSTATE, MySQL error code, named condition) //触发条件
· Hander actions(错误触发的操作)
后者:ROW_COUNT() * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#24楼 得分:0回复于:2009-05-06 14:08:19
比如
procedurebegin
update ...
update ...
delete ...
if 三个语句都没有问题,成功执行,
commit;
else
//其中一个有问题
rollback;
end
我用error_count时有问题,假如你一个有问题,后面二个没问题,error_count还是0而不是1 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#25楼 得分:0回复于:2009-05-06 14:15:53
error_count要分别取值,
update ...
set @i=error_count
update ...
set @i1=error_count
delete ..
set @i2=error_count
分别判断 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#26楼 得分:0回复于:2009-05-06 14:31:40
标准的做法手册上有.
没有必要分开取值判断,并且也没有任何意义,。因为@@error_count是session级的。不会被自动清零。
所以你只需在最后procedurebegin
update ...
update ...
delete ...if 三个语句都没有问题,成功执行,
if @@error_count>0 then
commit;
else
//其中一个有问题
rollback;
end * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#27楼 得分:0回复于:2009-05-06 14:39:52
procedurebegin
update ...
update ...
delete ...if 三个语句都没有问题,成功执行,
if @@error_count>0 then
commit;
else
//其中一个有问题
rollback;
end现在就是按照这种方法做的,不知道什么地方出了问题,还要继续检查
如果第一个update成功,后面的不成功
不能对其进行回滚
但是在call procedure之后,执行rollback;这时候可以回滚 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#28楼 得分:0回复于:2009-05-06 14:46:06
三条语句中,每条执行完后,执行
SELECT @@error_count INTO v_ErrorCount;
IF ( v_ErrorCount <> 0 )
ROLLBACK TRANSACTION;
ELSE
COMMIT TRANSACTION;
END IF;
END IF; * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#29楼 得分:0回复于:2009-05-06 14:49:15
上面的写错了if @@error_count=0 then commit; * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#30楼 得分:0回复于:2009-05-06 14:50:48
update ...
SELECT @@error_count INTO v_ErrorCount;
SELECT v_ErrorCount;
update ...
SELECT @@error_count INTO v_ErrorCount;
SELECT v_ErrorCount;
delete ...
SELECT @@error_count INTO v_ErrorCount;
SELECT v_ErrorCount;
结果如何 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#31楼 得分:0回复于:2009-05-06 14:50:49
发表于:2009-05-06 14:46:0628楼 得分:0
三条语句中,每条执行完后,执行
SELECT @@error_count INTO v_ErrorCount;
IF ( v_ErrorCount <> 0 )
ROLLBACK TRANSACTION;
ELSE
COMMIT TRANSACTION;
END IF;
END IF; 不可以这样做,这样就失去原子性了
我需要它们要生一起生,要死一起死 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#32楼 得分:0回复于:2009-05-06 14:51:08
if @@error_count>0 then改成if @@error_count=0 then如果error_count>0 则说明有错误发生。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#33楼 得分:0回复于:2009-05-06 14:53:08
引用 31 楼 jojophak 的回复:
发表于:2009-05-06 14:46:0628楼 得分:0
三条语句中,每条执行完后,执行
SELECT @@error_count INTO v_ErrorCount;
IF ( v_ErrorCount <> 0 )
ROLLBACK TRANSACTION;
ELSE
COMMIT TRANSACTION;
END IF;
END IF;不可以这样做,这样就失去原子性了
我需要它们要生一起生,要死一起死
你把ROLLBACK TRANSACTION、COMMIT TRANSACTION去掉,目的是检查
v_ErrorCount中的值是多少。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#34楼 得分:0回复于:2009-05-06 15:01:40
测试了一下,在MYSQL中,
执行完SQL语句后,select @@error_count看看结果,这个值
是要随语句执行是否正确而改变的。
比如:
select * from t5;
T5不存在,则@@error_count=1
再执行
select * from t4;
T4存在,则@@error_count=0 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#35楼 得分:0回复于:2009-05-06 15:04:39
故30楼的判断是正确的 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#36楼 得分:0回复于:2009-05-06 15:04:59
需要用到异常处理,对msyql不太熟,问题解决了再回来 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#37楼 得分:0回复于:2009-05-06 15:07:51
在23楼就问过,是SQL语句有问题还是执行结果有问题? * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * ACMAIN_CHM用户头像
* ACMAIN_CHM
* (acmain)
*
* 等 级:
* 6
#38楼 得分:0回复于:2009-05-06 15:08:26
引用 31 楼 jojophak 的回复:
发表于:2009-05-06 14:46:0628楼 得分:0
三条语句中,每条执行完后,执行
SELECT @@error_count INTO v_ErrorCount;
IF ( v_ErrorCount <> 0 )
ROLLBACK TRANSACTION;
ELSE
COMMIT TRANSACTION;
END IF;
END IF; 不可以这样做,这样就失去原子性了
我需要它们要生一起生,要死一起死
你的错误是指什么语句错误还是没有值被更新? 列举一个可能的错误。
估计你是想用ROW_COUNT() * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#39楼 得分:0回复于:2009-05-06 15:14:57
不好意思,刚才没注意看到,应该就用23楼捕获错误的方法 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#40楼 得分:0回复于:2009-05-06 15:45:37
谢谢2位耐心解答,问题已经解决,使用异常捕获。
我也会向你们学习,耐心帮助他人
再次感谢 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * WWWWA用户头像
* WWWWA
* (aaaa)
*
* 等 级:
* 2 8 7
#41楼 得分:0回复于:2009-05-06 15:46:47
共享一下吧,代码呵呵 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * wangzi6hao用户头像
* wangzi6hao
*
*
* 等 级:
*
#42楼 得分:0回复于:2009-07-13 18:13:59
嗯,几位真有耐心,我也学到了很多东西,谢谢大家。 * 对我有用[0]
* 丢个板砖[0]
* 引用
* 举报
* 管理
* TOP * jojophak用户头像
* jojophak
* (我不是随便的人)
*
* 等 级:
*
#43楼 得分:0回复于:2009-07-25 11:29:15
实际应用是在程序中使用的事务,遇到的这个问题就用简单的异常处理解决的
update ...
update ...
delete ...if 三个语句都没有问题,成功执行,
if @@error_count=0 then
commit;
else
//其中一个有问题
rollback;
end 所以 2楼的因该修改为下面的例子:
REATE PROCEDURE `ba`(id int)
begin
START TRANSACTION ;
update ba2 a, (select max(a) as aa from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
if @@error_count=0 then
commit;
else
//其中一个有问题
rollback;
end