首页 > 数据库 > MySQL > 正文

mysql expire_logs_days是如何生效和计算出来的

2024-07-24 12:35:18
字体:
来源:转载
供稿:网友
  mysql主备复制是通过binlog完成的。在开启binlog的情况下,expire_logs_days参数可以让mysql自动清理若干天前的binlog。
 
  那么expire_logs_days是在什么时候生效的呢?初步猜想实在每次产生一个新的binlog的时候去判断一次。查了一下具体的实现,确实是这样的:
 
  源码(5.1.58, log.cc)
 
  int MYSQL_BIN_LOG::rotate_and_purge(uint flags)  
 
  {  
 
  ...  
 
    if (!error && 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);  
 
    }  
 
  ...  
 
  }  
 
  如果设置了expire_logs_days,每次binlog rotate的时候都去计算一下purge_time(当前时间-expire_logs_days;
 
  这个计算似乎是可以省去的: expire_logs_days是以天为单位,范围是0~99, 0表示不会清理,自然不会进入if块内:),
 
  以99来计算,my_time(0) - 99*24*60*60>=0也是恒真的了),调用purge_logs_before_date(purge_time),
 
  purge_logs_before_date会从log index文件中的第一个binlog文件开始循环: 比较文件的最后修改时间,如果小于purge_time,
 
  就放入数组to_log中。然后调用purge_logs,清理所有满足条件的binlog。
 
  int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)  
 
  {  
 
  ...  
 
    MY_STAT stat_area;  
 
  ...  
 
    pthread_mutex_lock(&LOCK_index);  
 
    to_log[0]= 0;  
 
    if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))  
 
      goto err;  
 
    
 
    while (strcmp(log_file_name, log_info.log_file_name) &&  
 
       !is_active(log_info.log_file_name) &&  
 
           !log_in_use(log_info.log_file_name))  
 
    {  
 
  ...  
 
        if (stat_area.st_mtime < purge_time)   
 
          strmake(to_log,   
 
                  log_info.log_file_name,   
 
                  sizeof(log_info.log_file_name) - 1);  
 
        else  
 
          break;  
 
  ...  
 
     }  
 
     
 
  下面看一下purge_logs的实现:
 
  int MYSQL_BIN_LOG::purge_logs(const char *to_log,   
 
                            bool included,  
 
                            bool need_mutex,   
 
                            bool need_update_threads,   
 
                            ulonglong *decrease_log_space)  
 
  {  
 
  ...  
 
    while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&  
 
           !is_active(log_info.log_file_name) &&  
 
           !log_in_use(log_info.log_file_name))  
 
    {  
 
      if ((error= register_purge_index_entry(log_info.log_file_name)))  
  
         my_delete调用unlink()删除binlog文件。至此,完成了自动清理binlog的过程。另外当mysql启动的时候,mysql也会执行purge_logs_before_date(purge_time)的过程(其它的操作,如果会引起binlog rotate,自然也会触发这个过程,如flush logs)。
 
         梳理一下整个过程,不难发现,在压力比较大的mysql上或生产环境,我们不应该启动这个参数(my.cnf中不显式设置该参数或设置expire_logs_days=0):mysql每天产生十几个或更多的binlog文件,启用这个参数后,一次清理这么多文件,必定会导致磁盘io被占满,mysql出现抖动或hang住。因此建议自己编写脚本,每次purge完一个binlog后,sleep几秒。

(编辑:武林网)

上一篇:mysql -e细说

下一篇:mysqlsla迅速入门

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表