summaryrefslogtreecommitdiff
path: root/sql/mdl.cc
diff options
context:
space:
mode:
authorDmitry Lenev <dlenev@mysql.com>2010-02-15 13:23:34 +0300
committerDmitry Lenev <dlenev@mysql.com>2010-02-15 13:23:34 +0300
commit22bc48b2802143e5cebcd7f12c823259c10de265 (patch)
tree34f7770c9a35a8f2e093f9073c804ce696ae9071 /sql/mdl.cc
parent0ec868ca0e2d3ea60835d7c8fa7b951182b497b1 (diff)
downloadmariadb-git-22bc48b2802143e5cebcd7f12c823259c10de265.tar.gz
Fix for bug #51134 "Crash in MDL_lock::destroy on a concurrent
DDL workload". When a RENAME TABLE or LOCK TABLE ... WRITE statement which mentioned the same table several times were aborted during the process of acquring metadata locks (due to deadlock which was discovered or because of KILL statement) server might have crashed. When attempt to acquire all locks requested had failed we went through the list of requests and released locks which we have managed to acquire by that moment one by one. Since in the scenario described above list of requests contained duplicates this led to releasing the same ticket twice and a crash as result. This patch solves the problem by employing different approach to releasing locks in case of failure to acquire all locks requested. Now we take a MDL savepoint before starting acquiring locks and simply rollback to it if things go bad.
Diffstat (limited to 'sql/mdl.cc')
-rw-r--r--sql/mdl.cc11
1 files changed, 8 insertions, 3 deletions
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 245d6d8a018..e493b42ca69 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -1532,6 +1532,7 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
{
MDL_request_list::Iterator it(*mdl_requests);
MDL_request **sort_buf, **p_req;
+ MDL_ticket *mdl_svp= mdl_savepoint();
ssize_t req_count= static_cast<ssize_t>(mdl_requests->elements());
if (req_count == 0)
@@ -1565,12 +1566,16 @@ bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
return FALSE;
err:
- /* Release locks we have managed to acquire so far. */
+ /*
+ Release locks we have managed to acquire so far.
+ Use rollback_to_savepoint() since there may be duplicate
+ requests that got assigned the same ticket.
+ */
+ rollback_to_savepoint(mdl_svp);
+ /* Reset lock requests back to its initial state. */
for (req_count= p_req - sort_buf, p_req= sort_buf;
p_req < sort_buf + req_count; p_req++)
{
- release_lock((*p_req)->ticket);
- /* Reset lock request back to its initial state. */
(*p_req)->ticket= NULL;
}
my_free(sort_buf, MYF(0));