新聞中心
MySQL主備復(fù)制是通過binlog完成的。在開啟binlog的情況下,expire_logs_days參數(shù)可以讓mysql自動(dòng)清理若干天前的binlog。
創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括丘北網(wǎng)站建設(shè)、丘北網(wǎng)站制作、丘北網(wǎng)頁(yè)制作以及丘北網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,丘北網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到丘北省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
那么expire_logs_days是在什么時(shí)候生效的呢?初步猜想實(shí)在每次產(chǎn)生一個(gè)新的binlog的時(shí)候去判斷一次。查了一下具體的實(shí)現(xiàn),確實(shí)是這樣的:
源碼(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);
}
...
}
如果設(shè)置了expire_logs_days,每次binlog rotate的時(shí)候都去計(jì)算一下purge_time(當(dāng)前時(shí)間-expire_logs_days;
這個(gè)計(jì)算似乎是可以省去的: expire_logs_days是以天為單位,范圍是0~99, 0表示不會(huì)清理,自然不會(huì)進(jìn)入if塊內(nèi):),
以99來計(jì)算,my_time(0) - 99*24*60*60>=0也是恒真的了),調(diào)用purge_logs_before_date(purge_time),
purge_logs_before_date會(huì)從log index文件中的第一個(gè)binlog文件開始循環(huán): 比較文件的最后修改時(shí)間,如果小于purge_time,
就放入數(shù)組to_log中。然后調(diào)用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的實(shí)現(xiàn):
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會(huì)將需要清理的binlog文件名放入purge_index_file(IO_CACHE)中,然后更新index文件,最后再調(diào)用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調(diào)用unlink()刪除binlog文件。至此,完成了自動(dòng)清理binlog的過程。另外當(dāng)mysql啟動(dòng)的時(shí)候,mysql也會(huì)執(zhí)行purge_logs_before_date(purge_time)的過程(其它的操作,如果會(huì)引起binlog rotate,自然也會(huì)觸發(fā)這個(gè)過程,如flush logs)。
梳理一下整個(gè)過程,不難發(fā)現(xiàn),在壓力比較大的mysql上或生產(chǎn)環(huán)境,我們不應(yīng)該啟動(dòng)這個(gè)參數(shù)(my.cnf中不顯式設(shè)置該參數(shù)或設(shè)置expire_logs_days=0):mysql每天產(chǎn)生十幾個(gè)或更多的binlog文件,啟用這個(gè)參數(shù)后,一次清理這么多文件,必定會(huì)導(dǎo)致磁盤io被占滿,mysql出現(xiàn)抖動(dòng)或hang住。因此建議自己編寫腳本,每次purge完一個(gè)binlog后,sleep幾秒。
注意:
expire_logs_days設(shè)置之后不會(huì)立即清除,觸發(fā)條件是:
binlog大小超過max_binlog_size
手動(dòng)執(zhí)行flush logs
重新啟動(dòng)時(shí)
本文題目:mysqlexpire_logs_days是怎么生效和計(jì)算出來的
分享路徑:http://fisionsoft.com.cn/article/pidcjh.html