MySQL relay_log_purge=0 时的风险

本文探讨了在MySQL复制环境中禁用Relay Log自动清理(relay_log_purge=0)所带来的潜在数据一致性风险,尤其是在使用--relay-log-recovery选项时。文章详细解释了在MySQL崩溃或重启后,可能导致的数据重复或丢失问题,并提供了确保复制过程Crash-safe的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候,我们希望将 MySQL 的 relay log 多保留一段时间,比如用于高可用切换后的数据补齐,于是就会设置 relay_log_purge=0,禁止 SQL 线程在执行完一个 relay log 后自动将其删除。但是在官方文档关于这个设置有这么一句话:

Disabling purging of relay logs when using the --relay-log-recovery option risks data consistency and is therefore not crash-safe.


究竟是什么样的风险呢?查找了一番后,基本上明白了原因。

首先,为了让从库是 crash safe 的,必须设置 relay_log_recovery=1,这个选项的作用是,在 MySQL 崩溃或人工重启后,由于 IO 线程无法保证记录的从主库读取的 binlog 位置的正确性,因此,就不管 master_info 中记录的位置,而是根据 relay_log_info 中记录的已执行的 binlog 位置从主库下载,并让 SQL 线程也从这个位置开始执行。MySQL 启动时,相当于执行了 flush logs ,会新开一个 relay log 文件,新的 relay log 会记录在新的文件中。如果默认情况 relay_log_purge=1 时,SQL 线程就会自动将之前的 relay log 全部删除。而当 relay_log_purge=0 时,旧的 relay log 则会被保留。虽然这并不会影响从库复制本身,但还是会有地雷:

由于崩溃或停止 MySQL 时,SQL 线程可能没有执行完全部的 relay log,最后一个 relay log 中的一部分数据会被重新下载到新的文件中。也就是说,这部分数据重复了两次。
如果 SQL 跟得很紧,则可能在 IO 线程写入 relay log ,但还没有将同步到磁盘时,就已经读取执行了。这时,就会造成新的文件和旧的文件中少了一段数据。
如果我们读取 relay log 来获取数据,必须注意这一点,否则就会造成数据不一致。而保留 relay log 的目的也在于此。因此,在处理 relay log 时必须格外小心,通过其中 binlog 头信息来确保正确性。
关于如何配置 crash safe 的复制本身的配置,可以参照:
http://blog.itpub.net/22664653/viewspace-1752588/
http://www.innomysql.net/article/34.html

参考资料:
http://blog.booking.com/better_crash_safe_replication_for_mysql.html
https://bugs.mysql.com/bug.php?id=73038
http://bugs.mysql.com/bug.php?id=74324

参考博文:

http://blog.youkuaiyun.com/jiao_fuyou/article/details/51073945

[client] port=3306 [mysql] no-beep default-character-set = utf8mb4 [mysqld] init_connect='SET autocommit=0;' init_file=E:\\MySQL\\init.sql # 基础配置 port=3306 datadir=E:\MySQL\Data default-storage-engine=INNODB server-id=1 lower_case_table_names=1 secure-file-priv="C:/ProgramData/MySQL/MySQL Server 8.2/Uploads" # 修复连接问题的关键设置 bind-address=0.0.0.0 # 允许所有IP连接 skip_name_resolve=ON # 禁用DNS反向解析 # 认证策略修复 authentication_policy=mysql_native_password, # 字符集 character-set-server=utf8mb4 collation-server=utf8mb4_0900_ai_ci # SQL模式 sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" # 日志配置 log-output=FILE general-log=0 general_log_file="XIANJH.log" slow-query-log=1 slow_query_log_file="XIANJH-slow.log" long_query_time=3 log-error="XIANJH.err" log-bin="XIANJH-bin" binlog_expire_logs_seconds=604800 # 内存优化 max_connections=300 table_open_cache=5000 table_open_cache_instances=16 temptable_max_ram=2G tmp_table_size=512M max_heap_table_size=512M internal_tmp_mem_storage_engine=TempTable # InnoDB优化 innodb_buffer_pool_size=40G innodb_log_file_size=2G innodb_buffer_pool_instances=16 innodb_log_buffer_size=256M innodb_redo_log_capacity=4G innodb_flush_log_at_trx_commit=2 innodb_autoinc_lock_mode=2 bulk_insert_buffer_size=256M innodb_doublewrite=ON innodb_io_capacity=8000 innodb_io_capacity_max=16000 innodb_use_native_aio=ON innodb_flush_method=normal # 线程优化 innodb_thread_concurrency=0 innodb_parallel_read_threads=10 innodb_read_io_threads=10 innodb_write_io_threads=10 thread_cache_size=50 innodb_purge_threads=4 # 连接与网络 max_allowed_packet=256M net_buffer_length=32K max_connect_errors=1000 wait_timeout=300 interactive_timeout=300 # 文件与缓存 open_files_limit=10000 innodb_open_files=5000 innodb_file_per_table=ON innodb_autoextend_increment=128 # 查询优化 join_buffer_size=4M sort_buffer_size=4M read_buffer_size=1M read_rnd_buffer_size=1M # 性能与安全 performance_schema=ON innodb_checksum_algorithm=0 innodb_old_blocks_time=1000 innodb_stats_on_metadata=0 flush_time=0 # 复制相关 binlog_row_event_max_size=8K sync_source_info=10000 sync_relay_log=10000 # MySQL X Protocol loose_mysqlx_port=33060 这是我目前的my.ini的配置,我电脑是WIN10的操作系统,MYSQL版本是8.2,CPU是10核20线程的E5 2666V3,运存是4通道共64G服务器DD3内存,硬盘是SATA协议的1T SSD
最新发布
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值