diff options
author | He Zhenxing <zhenxing.he@sun.com> | 2009-12-15 14:48:28 +0800 |
---|---|---|
committer | He Zhenxing <zhenxing.he@sun.com> | 2009-12-15 14:48:28 +0800 |
commit | fb7214ae4b3d3c91da9653b34b35c2f61725aa31 (patch) | |
tree | 3160c5cf765a2fffd97a3bf3f13e3ba333e948f4 /sql/log.cc | |
parent | e813587b4042c95efa6bfd590b3fdbac47c7e8aa (diff) | |
download | mariadb-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.cc | 23 |
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() |