summaryrefslogtreecommitdiff
path: root/sql/sql_update.cc
diff options
context:
space:
mode:
authorJon Olav Hauglid <jon.hauglid@oracle.com>2013-05-06 15:01:57 +0200
committerJon Olav Hauglid <jon.hauglid@oracle.com>2013-05-06 15:01:57 +0200
commitdb99fd7450b865c63ec8eaba1f0b33caae2da6a0 (patch)
tree5a1cf32766ed1162b841df2acc0133a0bd6bee76 /sql/sql_update.cc
parentf829f20b4e44d9f24ed20970354d1738163e8659 (diff)
downloadmariadb-git-db99fd7450b865c63ec8eaba1f0b33caae2da6a0.tar.gz
Bug#16757869: INNODB: POSSIBLE REGRESSION IN 5.5.31, BUG#16004999
The problem was that if UPDATE with subselect caused a deadlock inside InnoDB, this deadlock was not properly handled by the SQL layer. This meant that the SQL layer would try to unlock the row after InnoDB had rolled back the transaction. This caused an assertion inside InnoDB. This patch fixes the problem by checking for errors reported by SQL_SELECT::skip_record() and not calling unlock_row() if any errors have been reported. This bug is similar to Bug#13586591, but for UPDATE rather than DELETE. Similar issues in filesort/opt_range/ sql_select will be investigated and handled in the scope of Bug#16767929
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r--sql/sql_update.cc18
1 files changed, 15 insertions, 3 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5bc11e942f6..a29d474fbfc 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
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
@@ -555,7 +555,10 @@ int mysql_update(THD *thd,
if (select && select->skip_record(thd, &skip_record))
{
error= 1;
- table->file->unlock_row();
+ /*
+ Don't try unlocking the row if skip_record reported an error since
+ in this case the transaction might have been rolled back already.
+ */
break;
}
if (!skip_record)
@@ -801,8 +804,17 @@ int mysql_update(THD *thd,
}
}
}
- else
+ /*
+ Don't try unlocking the row if skip_record reported an error since in
+ this case the transaction might have been rolled back already.
+ */
+ else if (!thd->is_error())
table->file->unlock_row();
+ else
+ {
+ error= 1;
+ break;
+ }
thd->warning_info->inc_current_row_for_warning();
if (thd->is_error())
{