Die Grundstruktur meiner gespeicherten Prozedur ist:
BEGIN
.. Declare statements ..
START TRANSACTION;
.. Query 1 ..
.. Query 2 ..
.. Query 3 ..
COMMIT;
END
MySQL-Version: 5.1.61-0ubuntu0.11.10.1-log
Wenn 'Abfrage 2' fehlschlägt, wird derzeit das Ergebnis von 'Abfrage 1' festgeschrieben.
- Wie kann ich die Transaktion zurücksetzen, wenn eine der Abfragen fehlschlägt?
mysql
sql
stored-procedures
transactions
Priyank Kapasi
quelle
quelle
Antworten:
Schauen Sie sich http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html an
Grundsätzlich deklarieren Sie den Fehlerhandler, der den Rollback aufruft
START TRANSACTION; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; EXIT PROCEDURE; END; COMMIT;
quelle
Nur eine Alternative zum Code von 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
quelle
Hier ist ein Beispiel für eine Transaktion, die bei einem Fehler zurückgesetzt wird und den Fehlercode zurückgibt.
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 ;
Dies setzt voraus, dass Autocommit auf 0 gesetzt ist. Ich hoffe, dies hilft.
quelle
Dies ist nur eine Erklärung, die in anderen Antworten nicht angesprochen wird
Zumindest in neueren Versionen von MySQL wird Ihre erste Abfrage nicht festgeschrieben .
Wenn Sie es in derselben Sitzung abfragen, werden die Änderungen angezeigt. Wenn Sie es jedoch in einer anderen Sitzung abfragen, sind die Änderungen nicht vorhanden und werden nicht festgeschrieben .
Was ist los?
Wenn Sie eine Transaktion öffnen und eine darin enthaltene Abfrage fehlschlägt, bleibt die Transaktion geöffnet und die Änderungen werden weder festgeschrieben noch rückgängig gemacht .
So ACHTUNG , jede Tabelle / Zeile , die mit einer früheren Abfrage wie gesperrt wurde
SELECT ... FOR SHARE/UPDATE
,UPDATE
,INSERT
oder jede andere Sperrabfrage gesperrt hält , bis diese Sitzung getötet wird (und führt einen Rollback), oder bis eine nachfolgende Abfrage verpflichtet explizit (COMMIT
) oder implizit , wodurch die Teiländerungen dauerhaft werden (was Stunden später passieren kann, während sich die Transaktion in einem Wartezustand befindet).Aus diesem Grund besteht die Lösung darin, Handler sofort zu deklarieren,
ROLLBACK
wenn ein Fehler auftritt.Extra
Im Handler können Sie den Fehler auch mit erneut auslösen
RESIGNAL
, andernfalls wird die gespeicherte Prozedur "Erfolgreich" ausgeführt.BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; START TRANSACTION; #.. Query 1 .. #.. Query 2 .. #.. Query 3 .. COMMIT; END
quelle