草庐IT

【MYSQL】binlog安全清理的两种方法

北冥友余 2024-04-05 原文

通常在交付MYSQL数据库前会将日志目录与数据文件分开,为其单独设立一个文件系统,这样便于掌握日志与数据的空间使用情况。如果不是业务突然增长,binlog会按照默认设置的过期时间自动被清理,但是有时候业务量增长是很突然的,比如上线了一个活动等,所以设置binlog自动清理是每个MYSQL管理员必须要做的一件事情。

两种binlog清理方法的选择

MYSQL8.0官方手册的说法,purge binary log 和 expire_logs_senconds 都可以安全清理binlog文件,那么到底该选择哪一种呢?
1、选择参数expire_logs_senconds。对于大公司、大企业来说,交付的数据库数量较多,数据库通常有统一的部署规范,这种情形就可使用本参数来设置所有的数据库binlog自清理周期,例如本公司大基线要求是7天。
2、选择命令purge binary log。这种方式比较适合临时清理一下的场景,比如自清理脚本。例如某应用binlog文件突增,触发自清理条件就会清理,但不会修改过期参数expire_logs_senconds,当业务量下来是binlog又会保留的久一点。

值得注意的是,官方手册中有一句话 “为了手动清理binlog日志文件,请用 purge binary log 命令

清理方法1(purge binary log)

清理时,PURGE BINARY LOGS和PURGE MASTER LOGS这两个命令任选其一即可,PURGE命令会根据mysql-bin.index的内容来确定被清理的binlog日志文件。

The PURGE BINARY LOGS statement deletes all the binary log files listed in the log index file prior to the specified log file name or date. BINARY and MASTER are synonyms. Deleted log files also are removed from the list recorded in the index file, so that the given log file becomes the first in the list.

Examples:

PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2019-04-02 22:46:26';

如果从库正在复制主库binlog的情况下,你执行PURGE命令,这时不会删除正在被占用的binlog日志文件;但时如果主从断掉的情况下,你执行PURGE 命令,就无法自动恢复主从同步。

PURGE BINARY LOGS is safe to run while replicas are replicating. You need not stop them. If you have an active replica that currently is reading one of the log files you are trying to delete, this statement does not delete the log file that is in use or any log files later than that one, but it deletes any earlier log files. A warning message is issued in this situation. However, if a replica is not connected and you happen to purge one of the log files it has yet to read, the replica cannot replicate after it reconnects.

清理方法2(expire_logs_senconds)

当启动数据库服务或者刷新binlog时,MYSQL会根据参数值binlog_expire_logs_seconds(默认30天)自动清理binlog文件。

Binary log files are automatically removed after the server’s binary log expiration period. Removal of the files can take place at startup and when the binary log is flushed. The default binary log expiration period is 30 days. You can specify an alternative expiration period using the binlog_expire_logs_seconds system variable. If you are using replication, you should specify an expiration period that is no lower than the maximum amount of time your replicas might lag behind the source.

自清理脚本(shell)

在这里附上我为本公司编写的binlog自清理脚本,脚本以crontab的形式部署在交付出去的MYSQL服务器上,包括主备机、单机。脚本中的清理命令虽然只有寥寥几行,但是附加的文件系统使用率、空间大小、数据库版本、同步延迟时间等检验条件以及邮件报警却丰富了脚本的多样性。

#!/bin/ksh
#本脚本必须使用系统用户执行
#功能:检查所有mysql8.0版本的单机或主库的binlog占用文件系统大小。若达到清理条件则开始执行清理脚本,清理前备份binlog文件,清理完邮件报警给数据库管理员。
#注意:部署时使用sh 脚本名,否则=~符号会报错。
export LC_ALL=C

manageruser=xxxxxx
managerpass=xxxxxx
useage_limited=90
idle_size_limited=10

mysql_host="xxx.xxx.xxx.xxx"
mysql_user=xxxxxx
mysql_pass=xxxxxx

datetime=`date +"%Y%m%d_%H%M%S"`
yesterday=`date '+%Y-%m-%d %H:%M:%S' -d '1 days ago'`
ipaddr=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v 0.0.0.0|grep -v inet6|awk '{print $2}'|tr -d "addr:"`

function getFileSystem(){
	F_PATH=/data/mysql_8.0_3306/log/bin_log
	FS_RESULT="/"
	for fs in `df |grep "/"|awk '{print $6}'`
	do
		if [[ $F_PATH/ =~ ${fs}/ ]]; then
			 FS_RESULT=$fs
		fi
	done
	echo $FS_RESULT
}

function get_binlog_useage(){
	useage=`df -h|grep $1|awk '{print $5}'|awk -FG '{print $1}'|awk '{print int($0)}'|sed -n '1p'`
	echo $useage
}

function get_binlog_idle_size(){
	idle=`df -h|grep $1|awk '{print $4}'|awk -FG '{print $1}'|awk '{print int($0)}'|sed -n '1p'`
	echo $idle
}

function get_behind_seconds(){
	standbyip=$(get_standby_ip $ipaddr)
	#echo "${standbyip}"
	if [ ! -n "${standbyip}" ]; then
        echo "单机或者备库[$ipaddr],可直接清理..."
		#echo 0
	else
		SECONDS_BEHIND_MASTER=$(mysql --connect-timeout=5 -h${standbyip} -u${manageruser} -p${managerpass} -e "SHOW SLAVE STATUS\G"| grep "Seconds_Behind_Master" | awk -F": " {' print $2 '})
		echo $SECONDS_BEHIND_MASTER
	fi
}

function get_standby_ip(){
	standby_ip=$(mysql --connect-timeout=5 -h$mysql_host -u$mysql_user -p$mysql_pass  -e "select distinct standby from iomp.ZJFH_MYSQL_LISTS where standby is not null and ip='$1';")
	echo $standby_ip|awk {'print $2'}
}

function backup_binlog_before_clean(){
	mkdir -p /data/mysql_8.0_3306/temp
	mount xxx.xxx.xxx.xxx:/appm/aixinst/mysql_install/Mysqlbinlog /data/mysql_8.0_3306/temp
	iptime="${ipaddr}_${datetime}"
	localdir=/data/mysql_8.0_3306/temp/${iptime}
	mkdir -p $localdir
	chown -R mysql:mysql $localdir
	cd $(find /data -name "bin_log")
	cp mysql-bin.* $localdir
	umount /data/mysql_8.0_3306/temp
	echo "mysqlbinlog backup dir: \\\\xxx.xxx.xxx.xxx\appm\aixinst\mysql_install\Mysqlbinlog\\${iptime}"
	echo
}

function clean_binlog(){
	echo '清理前binlog大小:'
	mysql -u$manageruser -p$managerpass -e "show binary logs;"
	echo
	mysql -u$manageruser -p$managerpass -e "purge binary logs before '${yesterday}';"
	echo '清理后binlog大小:'
	mysql -u$manageruser -p$managerpass -e "show binary logs;"
	
}

function send_mails()
{
	#test url
	#url="http://xxx.xxx.xxx.xxx:8080/iomp/probe/send"
	#production url
	url=http://xxx.xxx.xxx.xxx:8080/xxx/probe/send
	appcode="00000021"
	eagleappno="00000021"
	probetype="01"
	probedes="mysql_binlog_file_has_been_auto_clean[${ipaddr}]."   
	probetime=`date +"%Y%m%d%H%M%S"`    
	subappcode="1"
	echo "probetime:${datetime}, probedes: ${probedes}."
	command="curl $url -X POST -d 'appcode=$appcode&eagleappno=$eagleappno&probetype=$probetype&probetime=$probetime&subappcode=$subappcode' --data-urlencode probedes=$probedes"
    echo $command 
    eval $command
}

#清理条件?binlog使用率大于90或 binlog剩余空间小于10G
fileSystem=$(getFileSystem)
useage=$(get_binlog_useage ${fileSystem})
idle_size=$(get_binlog_idle_size ${fileSystem})
if [ $useage -gt $useage_limited ] || [ $idle_size -lt $idle_size_limited ]; then
	echo "binlog文件系统使用率或剩余大小满足清理条件,开始清理..."
else
	echo "binlog文件系统使用率[$useage]或剩余大小[$idle_size]充足,无需清理。"
	exit 1
fi

#清理内容?binlog时期在1天前的都备份后删除掉,修改binlog_expire_logs_seconds=86400可实现。
. /home/mysql/.profile
version=$(mysql -u$manageruser -p$managerpass  -e "select version();")
echo $version |grep "8.0"
if [ $?==0 ]; then
	echo "mysql版本为8.0,程序继续..."
else
	echo "mysql版本为5.7或5.5, 脚本暂不支持, 程序已退出..."
	exit 1
fi

delaytime=$(get_behind_seconds)
echo "Seconds_Behind_Master:${delaytime}"
if [ $delaytime -gt 86400 ]; then
	echo "主从延迟[$delaytime]超过86400秒(一天),不在本程序处理范围内,程序已停止,请手动处理..."
	exit 1
else
	echo "binlog文件系统使用率或剩余大小满足清理条件,开始清理..."
fi

alertcontent="本次共清理x个mysql-bin文件,空出x空间"
#备份、清理、邮件通知
backup_binlog_before_clean
clean_binlog
send_mails


有关【MYSQL】binlog安全清理的两种方法的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  10. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

随机推荐