我的存储过程的基本结构是,
BEGIN .. Declare statements .. START TRANSACTION; .. Query 1 .. .. Query 2 .. .. Query 3 .. COMMIT; END
mysql版本:5.1.61-0ubuntu0.11.10.1-log当前,如果“查询2”失败,则提交“查询1”的结果。如果任何查询失败,如何回滚事务?
vaj7vani1#
只是rkosegi代码的另一种选择,
BEGIN .. Declare statements .. DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN .. set any flags etc eg. SET @flag = 0; .. ROLLBACK; END; START TRANSACTION; .. Query 1 .. .. Query 2 .. .. Query 3 .. COMMIT; .. eg. SET @flag = 1; .. END
syqv5f0l2#
下面是一个事务示例,它将在出现错误时回滚并返回错误代码。
DELIMITER $$ CREATE DEFINER=`root`@`localhost` PROCEDURE `SP_CREATE_SERVER_USER`( IN P_server_id VARCHAR(100), IN P_db_user_pw_creds VARCHAR(32), IN p_premium_status_name VARCHAR(100), IN P_premium_status_limit INT, IN P_user_tag VARCHAR(255), IN P_first_name VARCHAR(50), IN P_last_name VARCHAR(50) ) BEGIN DECLARE errno INT; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN GET CURRENT DIAGNOSTICS CONDITION 1 errno = MYSQL_ERRNO; SELECT errno AS MYSQL_ERROR; ROLLBACK; END; START TRANSACTION; INSERT INTO server_users(server_id, db_user_pw_creds, premium_status_name, premium_status_limit) VALUES(P_server_id, P_db_user_pw_creds, P_premium_status_name, P_premium_status_limit); INSERT INTO client_users(user_id, server_id, user_tag, first_name, last_name, lat, lng) VALUES(P_server_id, P_server_id, P_user_tag, P_first_name, P_last_name, 0, 0); COMMIT WORK; END$$ DELIMITER ;
这是假设autocommit设置为0。希望这有帮助。
ma8fv8wu3#
看一看http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html基本上,您声明了将调用回滚的错误处理程序
START TRANSACTION; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; EXIT PROCEDURE; END; COMMIT;
nhhxz33t4#
这只是一个解释,其他答案中没有提到至少在mysql的最新版本中,您的第一个查询没有提交。如果您在同一个会话下查询它,您将看到更改,但是如果您从不同的会话中查询它,更改不在那里,它们不会被提交。发生什么事?当您打开一个事务,而其中的查询失败时,该事务将保持打开状态,它不会提交或回滚更改。所以要小心,任何被前一个查询锁定的表/行 SELECT ... FOR SHARE/UPDATE , UPDATE , INSERT 或任何其他锁定查询,保持锁定,直到终止该会话(并执行回滚),或直到后续查询显式提交它( COMMIT )或者隐式地,从而使部分更改成为永久性的(这可能在事务处于等待状态的几个小时后发生)。这就是为什么解决方案需要立即声明处理程序 ROLLBACK 当错误发生时。额外的在处理程序内部,还可以使用 RESIGNAL ,否则存储过程将“成功”执行
SELECT ... FOR SHARE/UPDATE
UPDATE
INSERT
COMMIT
ROLLBACK
RESIGNAL
BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; START TRANSACTION; #.. Query 1 .. #.. Query 2 .. #.. Query 3 .. COMMIT; END
4条答案
按热度按时间vaj7vani1#
只是rkosegi代码的另一种选择,
syqv5f0l2#
下面是一个事务示例,它将在出现错误时回滚并返回错误代码。
这是假设autocommit设置为0。希望这有帮助。
ma8fv8wu3#
看一看http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html
基本上,您声明了将调用回滚的错误处理程序
nhhxz33t4#
这只是一个解释,其他答案中没有提到
至少在mysql的最新版本中,您的第一个查询没有提交。
如果您在同一个会话下查询它,您将看到更改,但是如果您从不同的会话中查询它,更改不在那里,它们不会被提交。
发生什么事?
当您打开一个事务,而其中的查询失败时,该事务将保持打开状态,它不会提交或回滚更改。
所以要小心,任何被前一个查询锁定的表/行
SELECT ... FOR SHARE/UPDATE
,UPDATE
,INSERT
或任何其他锁定查询,保持锁定,直到终止该会话(并执行回滚),或直到后续查询显式提交它(COMMIT
)或者隐式地,从而使部分更改成为永久性的(这可能在事务处于等待状态的几个小时后发生)。这就是为什么解决方案需要立即声明处理程序
ROLLBACK
当错误发生时。额外的
在处理程序内部,还可以使用
RESIGNAL
,否则存储过程将“成功”执行