Commit db99fd74 authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

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
parent f829f20b
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -555,7 +555,10 @@ int mysql_update(THD *thd, ...@@ -555,7 +555,10 @@ int mysql_update(THD *thd,
if (select && select->skip_record(thd, &skip_record)) if (select && select->skip_record(thd, &skip_record))
{ {
error= 1; 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; break;
} }
if (!skip_record) if (!skip_record)
...@@ -801,8 +804,17 @@ int mysql_update(THD *thd, ...@@ -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(); table->file->unlock_row();
else
{
error= 1;
break;
}
thd->warning_info->inc_current_row_for_warning(); thd->warning_info->inc_current_row_for_warning();
if (thd->is_error()) if (thd->is_error())
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment