summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-03-07 11:57:14 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-03-07 11:57:14 +0200
commit8024f8c6b86b204c3475e562587640cf2b141683 (patch)
tree0289060248b1ce93079404063b5011e24748f04e
parentcb11b3fbe9d4dde776cb8f2c0d6f83a569655efc (diff)
downloadmariadb-git-8024f8c6b86b204c3475e562587640cf2b141683.tar.gz
MDEV-18272 InnoDB fails to rollback after exceeding FOREIGN KEY recursion depth
row_mysql_handle_errors(): Correct the wrong error handling for the code DB_FOREIGN_EXCEED_MAX_CASCADE that was introduced in https://github.com/mysql/mysql-server/commit/c0923d396aef46799883390e9dcf7bbf173e4a03 commit 35f5429eda94f2ce87e453653cd22298d5851cfa Author: Jimmy Yang <jimmy.yang@oracle.com> Date: Wed Oct 6 06:55:34 2010 -0700 Manual port Bug #Bug #54582 "stack overflow when opening many tables linked with foreign keys at once" from mysql-5.1-security to mysql-5.5-security again. rb://391 approved by Heikki No known test case exists for repeating the bug before MariaDB 10.2. The scenario should be that DB_FOREIGN_EXCEED_MAX_CASCADE is returned, then InnoDB wrongly skips the rollback to the start of the current row operation, and finally the SQL layer commits the transaction. Normally the SQL layer would roll back either the entire transaction or to the start of the statement. In the faulty scenario, InnoDB would leave the transaction in an inconsistent state, and the SQL layer could commit the transaction.
-rw-r--r--storage/innobase/row/row0mysql.c10
-rw-r--r--storage/xtradb/row/row0mysql.c10
2 files changed, 12 insertions, 8 deletions
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 8804e2c4e03..c16d1b8ea36 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -572,8 +573,7 @@ handle_new_error:
switch (err) {
case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) {
- trx_general_rollback_for_mysql(trx, NULL);
- break;
+ goto rollback;
}
/* fall through */
case DB_DUPLICATE_KEY:
@@ -586,6 +586,7 @@ handle_new_error:
case DB_TOO_MANY_CONCURRENT_TRXS:
case DB_OUT_OF_FILE_SPACE:
case DB_INTERRUPTED:
+ rollback_to_savept:
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
@@ -609,6 +610,7 @@ handle_new_error:
case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL:
+ rollback:
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
@@ -638,14 +640,14 @@ handle_new_error:
"InnoDB: you dump the tables, look at\n"
"InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr);
- break;
+ goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
" cascading foreign key constraints that exceed max"
" depth of %lu\n"
"Please drop excessive foreign constraints"
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
- break;
+ goto rollback_to_savept;
default:
fprintf(stderr, "InnoDB: unknown error code %lu\n",
(ulong) err);
diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c
index 5b01adf7c82..a17a8d59b83 100644
--- a/storage/xtradb/row/row0mysql.c
+++ b/storage/xtradb/row/row0mysql.c
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -574,8 +575,7 @@ handle_new_error:
switch (err) {
case DB_LOCK_WAIT_TIMEOUT:
if (row_rollback_on_timeout) {
- trx_general_rollback_for_mysql(trx, NULL);
- break;
+ goto rollback;
}
/* fall through */
case DB_DUPLICATE_KEY:
@@ -588,6 +588,7 @@ handle_new_error:
case DB_TOO_MANY_CONCURRENT_TRXS:
case DB_OUT_OF_FILE_SPACE:
case DB_INTERRUPTED:
+ rollback_to_savept:
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */
@@ -611,6 +612,7 @@ handle_new_error:
case DB_DEADLOCK:
case DB_LOCK_TABLE_FULL:
+ rollback:
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
@@ -640,14 +642,14 @@ handle_new_error:
"InnoDB: you dump the tables, look at\n"
"InnoDB: " REFMAN "forcing-innodb-recovery.html"
" for help.\n", stderr);
- break;
+ goto rollback_to_savept;
case DB_FOREIGN_EXCEED_MAX_CASCADE:
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
" cascading foreign key constraints that exceed max"
" depth of %lu\n"
"Please drop excessive foreign constraints"
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
- break;
+ goto rollback_to_savept;
default:
fprintf(stderr, "InnoDB: unknown error code %lu\n",
(ulong) err);