mysqlexpire_logs_days是怎么生效和计算出来的-成都快上网建站

mysqlexpire_logs_days是怎么生效和计算出来的

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)))  

...  

  }  

...  

  /* We know how many files to delete. Update index file. */  

  if ((error=update_log_index(&log_info, need_update_threads)))  

...  

  /* Read each entry from purge_index_file and delete the file. */  

  if (is_inited_purge_index_file() &&  

      (error= purge_index_entry(thd, decrease_log_space, FALSE)))  

...  

 

        purge_logs会将需要清理的binlog文件名放入purge_index_file(IO_CACHE)中,然后更新index文件,最后再调用purge_index_entry删除binlog文件:

int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,  

                                     bool need_mutex)  

{  

...  

  for (;;)  

  {  

...  

        if (!my_delete(log_info.log_file_name, MYF(0)))  

        {  

          if (decrease_log_space)  

            *decrease_log_space-= s.st_size;  

        }  

...  

}  

       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几秒。

注意:

expire_logs_days设置之后不会立即清除,触发条件是:

binlog大小超过max_binlog_size

手动执行flush logs

重新启动时


本文题目:mysqlexpire_logs_days是怎么生效和计算出来的
标题来源:http://kswjz.com/article/pidcjh.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流