前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL 复制 - 性能与扩展性的基石 3:常见问题及解决方案

MySQL 复制 - 性能与扩展性的基石 3:常见问题及解决方案

作者头像
北国风光
发布于 2019-04-11 04:43:07
发布于 2019-04-11 04:43:07
59200
代码可运行
举报
文章被收录于专栏:PHPer 进击PHPer 进击
运行总次数:0
代码可运行

主备复制过程中有很大可能会出现各种问题,接下来我们就讨论一些比较普遍的问题,以及当遇到这些问题时,如何解决或者预防问题发生。

1 数据损坏或丢失

问题描述:服务器崩溃、断电、磁盘损坏、内存或网络错误等问题,导致数据损坏或丢失。 问题原因:非正常关机导致没有把数据及时的写入硬盘。

这种问题,一般可以分为几种情况导致:

1.1 主库意外关闭

问题未发生,避免方案:设置主库的 sync_binlog 选项为 1。此选项表示 MySQL 是否控制 binlog 的刷新。当设置为 1 时,表示每次事务提交,MySQL 都会把 binlog 刷下去,是最安全,性能损耗也最大的设置问题已发生,解决方案:指定备库从下一个二进制日志的开头重新读日志。但是一些日志事件将永久性丢失。可以使用 Percona Toolkit 中的 pt-table-checksum 工具来检查主备一致性,以便于修复。

1.2 备库意外关闭

备库意外关闭重启时,会去读 master.info 文件以找到上次停止复制的位置。但是在意外关闭的情况下,这个文件存储的信息可能是错误的。此外,备库也可能会尝试重新执行一些二进制文件,这可能会导致唯一索引错误。我们可以通过 Percona Toolkit 中的 pt-slave-restart 工具,帮助备库重新执行日志文件

如果使用的是 InnoDB 表,可以在重启后观察 MySQL 的错误日志。InnoDB 在恢复过程中会打印出恢复点的二进制日志坐标,可以使用这个值来决定备库指向主库的偏移量。

1.3 主库二进制日志损坏

如果主库上的二进制日志损坏,除了忽略损坏的位置外,别无选择。在忽略存货位置后,我们可以通过 FLUSH LOGS 命令在主库开始一个新的日志文件,然后将备库指向该文件的开始位置。

1.4 备库中继日志损坏

如果主库上的日志是完好的,有两种解决方案: 1) 手工处理。找到 master binlog 日志的 pos 点,然后重新同步。

2) 自动处理。mysql5.5 考虑到 slave 宕机中继日志损坏这一问题,只要在 slave 的的配置文件 my.cnf 里增加一个参数 relay_log_recovery=1 即可。

1.5 二进制日志与 InnoDB 事务日志不同步

由于各种各样的原因,MySQL 的复制碰到服务器崩溃、断电、磁盘损坏、内存或网络错误时,很难恢复当时丢失的数据。几乎都需要从某个点开始重启复制。

2 未定义的服务器 ID

如果没有再 my.cnf 里定义服务器 ID,虽然可以通过 CHANGE MASTER TO 来设置备库,但在启动复制时会遇到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mysql> START SLAVE;
ERROR 1200 (HY000): The server us bit configured as slave; fix in config file or with CHANGE MASTER TO

这个报错可能会让人困惑。因为我们可能已经通过 CHANGE MASTER TO 设置了备库,并且通过 SHOW MASTER STATUS 也确认了,为什么还会有这样的报错呢?我们通过 SELECT @@server_id 可以获得一个值,要注意的是,这个值只是默认值,我们必须为备库显式地设置服务器 ID。也就是在 my.cnf 里显示的设置服务器 ID。

3 对未复制数据的依赖性

如果在主库上有备库上不存在的数据库或数据表,复制就很容易中断,反之亦然。 对于前者,假设在主库上有一个 single_master 表,备库没有。在主库上对此表进行操作后,备库在尝试回放这些操作时就会出现问题,导致复制中断。

对于后者,假设备库上有一个 single_slave 表,主库没有。在主库上执行创建 single_slave 表的语句时,备库在回放该建表语句时就会出现问题。

对于此问题,我们能做的就是做好预防:

  1. 主备切换时,尽量在切换后对比数据,查清楚是否有不一致的表或库。
  2. 一定不要在备库执行写操作。

4 丢失的临时表

临时表和基于语句的复制方式不相容。如果备库崩溃或者正常关闭,任何复制线程拥有的临时表都会丢失。重启备库后,所有依赖于该临时表的语句都会失败。

复制时出现找不到临时表的异常时,可以做:

  1. 直接跳过错误,或者手动地创建一个名字和结构相同的表来代替消失的的临时表。

临时表的特性:

  1. 只对创建临时表的连接可见。不会和其他拥有相同名字的临时表的连接起冲突;
  2. 随着连接关闭而消失,无须显式的移除它们。
4.1 更好使用临时表的方式

保留一个专用的数据库,在其中创建持久表,把它们作为伪临时表,以模拟临时表特性。只需要通过 CONNETCTION_ID() 的返回值,给临时表创建唯一的名字。

伪临时表的优劣势 优势:

  1. 更容易调试应用程序。可以通过别的连接来查看应用正在维护的数据;

劣势:

  1. 比临时表多一些开销。创建较慢伪临时表会较慢,因为表的 .frm 文件需要刷新到磁盘。

5 InnoDB 加锁读导致主备数据不一致

使用共享锁,串行化更新,保证备库复制时数据一致。

某些情况下,加锁读可以防止混乱。假设有两张表:tab1 没有数据,tab2 只有一行数据,值为 99。此时,有两个事务更新数据。事务 1 将 tab2 的数据插入到 tab1,事务 2 更新 tab2。

  1. 事务 1 使用获取 tab2 数据时,加入共享锁,并插入 tab1;
  2. 同时,事务 2 更新 tab2 数据时,由于写操作的排它锁机制,无法获取 tab2 的锁,等待;
  3. 事务 1 插入数据后,删除共享锁,提交事务,写入 binlog(此时 tab1 和 tab2 的记录值 都是 99);
  4. 事务 2 获取到锁,更新数据,提交事务,写入 binlog(此时 tab1 的记录值为 99,tab2 的记录值为 100)。

上述过程中,第二步非常重要。事务 2 尝试去更新 tab2 表,这需要在更新的行上加排他锁(写锁)。排他锁与其他锁不相容,包括事务 1 在行记录上加的共享锁。因此事务 2 需要等待事务 1 完成。备库在根据 binlog 进行复制时,会按同样的顺序先执行事务 1,再执行事务 2。主备数据一致。

同样的过程,如果事务 1 在第一步时没有加共享锁,流程就变成:

  1. 事务 1 无锁读取 tab2 数据,并插入 tab1(此时 tab1 和 tab2 的记录值 都是 99);
  2. 同时,事务 2 更新 tab2 数据,先与事务 1 提交事务,写入 binlog(此时 tab1 的记录值为 99,tab2 的记录值为 100);
  3. 事务 1 提交事务,写入 binlog(此时记录值无变化); mysqldump --single-transaction --all-databases --master-data=1 --host=server1 | mysql --host=server2 要注意的是,上述过程中,事务 2 先提交,先写入 binlog。在备库复制时,同样先执行事务 2,将 tab2 的记录值更新为 100。然后执行事务 1,读取 tab2 数据,插入 tab1,所以最终的结果是,tab1 的记录值和 tab2 的记录值都是 100。很明显,数据和主库有差异。

建议在大多数情况下将 innodb_unsafe_for_binlog 的值设置为 0。基于行的复制由于记录了数据的变化而非语句,因此不会存在这个问题。

6 复制延迟过大

产生延迟的两种方式

  1. 突然产生延迟,然后再跟上;
  2. 稳定的延迟增大

前者通常是由于一条执行时间过长的 SQL 导致,而后者即使在没有慢语句也会出现。

对于前者,我们可以通过备库上的慢查询日志来进行优化。在备库上开启 log_slow_slave_statement 选项,可以在慢查询日志中记录复制线程执行的语句。

而对于后者,没有针对性的解决方案,只能通过各种方式提高备库的复制效率。而当我们想去对备库做优化时,会发现,除了购买更快的磁盘和 CPU,并没有太多的调优空间。只能通过 MySQL 选项禁止某些额外的工作以减少备库的复制。可以通过下面几种方式:

  1. 使用 InnoDB 引擎时,设置 innodb_flush_log_at_trx_commit 值为 2,来使备库不要频繁的刷新磁盘,以提高事务提交效率。
  2. 禁止二进制日志记录。把 innodb_locks_unsafe_for_binlog 设置为 1,并把 MyISAM 的 delay_key_write 设置为 ALL。要注意的是,这些设置是以安全换取速度,在将备库提升为主库时,记得把这些选项设置回安全的值。
  3. 拆分效率较低的复制 SQL,分离复杂语句中的 SELECT 和 UPDATE 语句,降低复制消耗,提高效率。

总结

  1. 复制问题要分清楚是 master 的问题,还是 slave 的问题。
  2. master 问题找 binlog,slave 问题找 relaylog。

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=16s4qjbz9ahdf

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL 复制 - 性能与扩展性的基石 2:部署及其配置
正所谓理论造航母,现实小帆船。单有理论,不动手实践,学到的知识犹如空中楼阁。接下来,我们一起来看下如何一步步进行 MySQL Replication 的配置。
北国风光
2019/04/11
5940
MySQL 复制 - 性能与扩展性的基石 2:部署及其配置
MySQL 主从复制的问题及解决方案
MySQL 主从复制的问题及解决方案
Java架构师必看
2021/05/06
4660
MySQL 主从复制的问题及解决方案
MySQL 复制 - 性能与扩展性的基石 1:概述及其原理
MySQL 内置的复制功能是构建基于 MySQL 的大规模、高性能应用的基础,复制解决的基本问题是让一台服务器的数据与其他服务器保持同步。
北国风光
2019/04/11
4460
MySQL 复制 - 性能与扩展性的基石 1:概述及其原理
MySQL 复制 - 性能与扩展性的基石 4:主备切换
一旦使用 MySQL 的复制功能,就很大可能会碰到主备切换的情况。也许是为了迭代升级服务器,或者是主库出现问题时,将一台备库转换成主库,或者只是希望重新分配容量。不过出于什么原因,都需要将新主库的信息告诉其它备库。
北国风光
2019/04/22
8650
MySQL 复制 - 性能与扩展性的基石 4:主备切换
MySQL复制性能优化和常见问题分析
二进制日志文件并不是每次写的时候都会同步到磁盘,当发生宕机的时候,可能会有最后一部分数据没有写入到binlog中,这给恢复和复制带来了问题。当sync_binlog=1表示每写缓冲一次就同步到磁盘,表示同步写磁盘的方式来写binlog。也就是说每当向MySQL提交一次事务,MySQL将进行一次fsync之类的磁盘同步命令来将binlog_cache的数据强制刷到磁盘中sync_binlog的值默认为0,sync_binlog=0时表示采用操作系统机制进行缓冲数据同步。采用sync_binlog=1时,会增加磁盘IO的次数,会影响写入性能。sync_binlog=1时,并不是100%安全,会存在相应的问题。比如说使用Innodb引擎时,在一个事务发出commit前,会将binlog立即刷到磁盘中。如果这时候已经写入到binlog中,但是还没有提交就已经挂了,那么MySQL重启时,会将通过Redo log、Undo log将这个事务回滚掉,但是binlog已经记入了该事务信息,不能回滚掉。所以我们需要设置innodb_support_xa=1确保MySQL服务层的binlog和MySQL存储引擎层的Redo log、Undo log之间的数据一致性。
用户2032165
2018/12/07
1.2K0
MySQL复制性能优化和常见问题分析
《高性能Mysql》学习笔记(三)
即没有特别指明的类型,大多数时候mysql 引擎都支持这种索引(Archive 是例外, 5.1 之前不支持,之后支持单个自增列的索引)
阿东
2021/11/02
1.3K0
MySQL 复制原理详解
腾讯云开发者社区
2017/06/15
3.1K0
MySQL 复制原理详解
MySQL 8 复制(一)——异步复制
简单说,复制就是将来自一个MySQL数据库服务器(主库)的数据复制到一个或多个MySQL数据库服务器(从库)。传统的MySQL复制提供了一种简单的Primary-Secondary复制方法,默认情况下,复制是单向异步的。MySQL支持两种复制方式:基于行的复制和基于语句的复制。这两种方式都是通过在主库上记录二进制日志(binlog)、在从库重放中继日志(relylog)的方式来实现异步的数据复制。二进制日志或中继日志中的记录被称为事件。所谓异步包含两层含义,一是主库的二进制日志写入与将其发送到从库是异步进行的,二是从库获取与重放日志事件是异步进行的。这意味着,在同一时间点从库上的数据更新可能落后于主库,并且无法保证主从之间的延迟间隔。
用户1148526
2019/05/25
5.2K0
mysql复制
一、复制的意义 mysql的复制功能是构建基于MySql大规模,高性能应用的基础,我们可以通过为服务器配置一个或多个备库来进行数据同步;复制功能不仅有利于构建高性能的应用,同时也是高可用性,可扩展行,灾难恢复,备份以及数据仓库等工作的基础 二、复制的方式 Mysql支持3种方式:基于语句的复制、基于行的复制、混合复制。对应的binlog的格式也有三种:STATEMENT,ROW,MIXED (1)基于语句的复制(SBR) 每一条会修改数据的sql语句会记录到binlog中。优点是不需要记录每一条sql语句和
magicsoar
2018/02/06
2.7K0
MySQL Replication 主从复制全方位解决方案
    在了解主从复制之前必须要了解的就是数据库的二进制日志(binlog),主从复制架构大多基于二进制日志进行,二进制日志相关信息参考:http://www.cnblogs.com/clsn/p/8087678.html#_label6
惨绿少年
2019/05/24
8830
MySQL 8 复制(六)——拓扑与性能
可以在任意个主从库之间建立复杂的复制拓扑结构,如普通的一主一(多)从、双(多)主复制、级联复制,MySQL 5.7.2后新增的多源复制,特殊场景下使用的Blackhole引擎与日志服务器等等。复制中的MySQL服务器须要遵循以下基本原则:
用户1148526
2019/07/11
1.8K0
MySQL 8 复制(六)——拓扑与性能
MySQL 8 复制(十)——组复制性能与限制
组复制的基本保证是,只有在组中的大多数节点接收到事务并且就并发事务的相对顺序达成一致之后,才会提交事务。其对事务的基本处理流程为:
用户1148526
2019/08/14
2.3K0
MySQL常见配置参数及命令
wait_timeout:客户端连接自动断开连接时间(默认值是28800s,8个小时),自动断开的操作是“Server层的连接器做的”,断开后需要重新连接;
向着百万年薪努力的小赵
2022/12/02
8510
mysql主从同步(2)-问题梳理
之前部署了Mysql主从复制环境(Mysql主从同步(1)-主从/主主环境部署梳理),在mysql同步过程中会出现很多问题,导致数据同步异常。 以下梳理了几种主从同步中可能存在的问题: 1)slave运行过慢不能与master同步,也就是MySQL数据库主从同步延迟 MySQL数据库slave服务器延迟的现象是非常普遍的,MySQL复制允许从机进行SELECT操作,但是在实际线上环境下,由于从机延迟的关系,很难将读取操作转向到从机。这就导致了有了以下一些潜规则:“实时性要求不高的读取操作可以放到slave服
洗尽了浮华
2018/01/23
2.4K0
MySQL主从复制能完美解决数据库单点问题吗?
2、从库的IO线程在指定位置读取主库binlog内容存储到本地的中继日志(Relay Log)中
lyb-geek
2019/10/31
2.2K0
MySQL 8 复制(二)——半同步复制
直到目前的最新版本为止,MySQL缺省依然使用异步复制策略。简单说所谓异步复制,指的是主库写二进制日志、从库的I/O线程读主库的二进制日志写本地中继日志、从库的SQL线程重放中继日志,这三步操作都是异步进行的。如此选择的主要理由是出于性能考虑,与同步复制相比,异步复制显然更快,同时能承载更高的吞吐量。但异步复制的缺点同样明显,不能保证主从数据实时一致,也无法控制从库的延迟时间,因此它不适于要求主从数据实时同步的场景。例如,为了分解读写压力,同一程序写主库读从库,但要求读到的数据与读主库的相同,异步复制不满足这种强数据一致性需求。异步复制的另一个问题是可能会有数据丢失,例如主库宕机时,已经提交的事务可能还没有传到从库上,如果此时强行主从切换,可能导致新主库上的数据不完整。
用户1148526
2019/05/25
5.4K0
高性能Mysql主从架构的复制原理及配置详解
Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
用户7353950
2022/05/11
5180
高性能Mysql主从架构的复制原理及配置详解
mysql读写分离延迟问题_MySQL读写分离后的延迟解决方案
根据上图可以看到QPS:10.73k,实际上真实的并发大量数据到达的时候,我这里最高的QPS是将近15k.而目前单个数据库分片(实例)4CPU8G内存的配置下,最高的性能是7k的QPS。
全栈程序员站长
2022/09/02
1.3K0
MySQL 主从复制解决了什么问题?出现同步延迟如何解决?
日志文件中记录的到底是什么呢?mysql支持了两种日志格式,这两种日志格式也体现了各自的复制方式
民工哥
2021/05/11
1.1K0
redis主从复制原理是同步还是异步_kubernetes高可用架构
在mysql5.4.1之前只存在这种复制模式,在mysql5.7前默认使用这种格式。
全栈程序员站长
2022/09/22
7790
redis主从复制原理是同步还是异步_kubernetes高可用架构
推荐阅读
相关推荐
MySQL 复制 - 性能与扩展性的基石 2:部署及其配置
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验