summaryrefslogtreecommitdiff
path: root/sql/log.cc
diff options
context:
space:
mode:
authorHe Zhenxing <zhenxing.he@sun.com>2009-12-15 14:48:28 +0800
committerHe Zhenxing <zhenxing.he@sun.com>2009-12-15 14:48:28 +0800
commitfb7214ae4b3d3c91da9653b34b35c2f61725aa31 (patch)
tree3160c5cf765a2fffd97a3bf3f13e3ba333e948f4 /sql/log.cc
parente813587b4042c95efa6bfd590b3fdbac47c7e8aa (diff)
downloadmariadb-git-fb7214ae4b3d3c91da9653b34b35c2f61725aa31.tar.gz
bug#49536 - deadlock on rotate_and_purge when using expire_logs_days
Problem is that purge_logs implementation in ndb (ndbcluster_binlog_index_purge_file) calls mysql_parse (with (thd->options & OPTION_BIN_LOG) === 0)) but MYSQL_BIN_LOG first takes LOCK_log and then checks thd->options Solution in this patch, changes so that rotate_and_purge does not hold LOCK_log when calling purge_logs_before_date. I think this is safe as other "purge"-function(s) is called wo/ holding LOCK_log, e.g purge_master_logs
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc23
1 files changed, 17 insertions, 6 deletions
diff --git a/sql/log.cc b/sql/log.cc
index f795cdab2ca..1adf92e709c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -4481,6 +4481,9 @@ bool general_log_write(THD *thd, enum enum_server_command command,
void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
{
+#ifdef HAVE_REPLICATION
+ bool check_purge= false;
+#endif
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
pthread_mutex_lock(&LOCK_log);
if ((flags & RP_FORCE_ROTATE) ||
@@ -4488,16 +4491,24 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
{
new_file_without_locking();
#ifdef HAVE_REPLICATION
- if (expire_logs_days)
- {
- time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
- if (purge_time >= 0)
- purge_logs_before_date(purge_time);
- }
+ check_purge= true;
#endif
}
if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
pthread_mutex_unlock(&LOCK_log);
+
+#ifdef HAVE_REPLICATION
+ /*
+ NOTE: Run purge_logs wo/ holding LOCK_log
+ as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
+ */
+ if (check_purge && expire_logs_days)
+ {
+ time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
+ if (purge_time >= 0)
+ purge_logs_before_date(purge_time);
+ }
+#endif
}
uint MYSQL_BIN_LOG::next_file_id()