From e76d96c4adddd1ab2868339b82abb49ba7e17cda Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Tue, 15 Dec 2009 14:48:28 +0800 Subject: [PATCH] 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 --- sql/log.cc | 23 +++++++++++++++++------ 1 file 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()