MySQL-15-复制

复制(Replication)解决的问题
  1. 数据分布
  2. 负载均衡和读写分离
  3. 备份
  4. 高可用性和故障切换
  5. 大表 DDL 避免锁表
  6. MySQL 升级测试
复制的工作原理
  1. 主库将数据更改记录到 binlog 中
  2. 备库将主库上的日志复制到自己的 relaylog 中
  3. 备库读取 relaylog 中的事件,将其在备库上重放
  4. 实现方式是:备库会启动一个 I/O 线程,I/O 线程会跟主库建立一个客户端连接,然后在主库上启动一个 binlog dump 线程,该线程不断把新的事件传送给备库
  5. 使用复制,需要在主库上增加一个配库使用的账号,该账号需要有REPLICATION SLAVE,REPLICATION CLIENT权限
复制的使用
  1. 配置 master
# 1) my.cnf 配置文件
[mysqld]
log-bin=mysql-bin
server-id=1
# 2) 获取主库 binlog 位点
mysql> SHOW MASTER STATUS;
File: mysql-bin.000001
Position:98
  1. 配置 slave 并开启复制
# 1) my.cnf 配置文件
[mysqld]
log_bin           = mysql-bin
server_id         = 2
relay_log         = mysql-relay-bin
log_slave_updates = 1
read_only         = 1
# 2) 设置主库和位点
mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.1',
    -> MASTER_PORT=3306
    -> MASTER_USER='repl',
    -> MASTER_PASSWORD='p4ssword',
    -> MASTER_LOG_FILE='mysql-bin.000001',
	-> MASTER_LOG_POS=98;
# 3) 检查位点是否设置正确
mysql> SHOW SLAVE STATUS\G
# 4) 开启复制
mysql> START SLAVE ;
  1. SHOW SLAVE STATUS 中各个位点信息的含义
Master_Log_File			# 目前拉取的主库文件
Read_Master_Log_Pos		# 目前拉取的主库文件位置
Relay_Log_File			# 当前执行的本库 relay log 文件
Relay_Log_Pos			# 当前执行的 relay log 文件位点
Relay_Master_Log_File	# 当前执行到的对应的主库文件的位置
复制的类型
  • 基于语句的复制
    1. 复制快,节约 binlog 空间
    2. 复杂场景下(使用函数或存储过程等)存在各种异常和 bug
  • 基于行的复制
    1. 简单灵活适应性强
    2. 数据有冗余,出错方便修复
    3. DDL 还是语句的复制
  • 混合性复制
    1. 适应性最强
    2. DDL 也是基于行的复制,binlog 会超级大
    3. 可以理解为,基于行复制的扩展
  • 基于 GTID 的复制
    1. 简单灵活,不用记录位点,会根据全局事务ID自动寻点
    2. 因为是基于事务的复制(也是基于行的),所以不支持非事务的存储引擎
    3. 可以理解为,基于行赋值的升级
复制异常
  • 写冲突,insert 的主键/唯一键已存在,处理的方式往往是:
    1. 记录下错误发生的表和对应主键
    2. 使用SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;跳过这次冲突
    3. 检查主备库中对应主键的记录是否一致
  • 写异常,update 前镜像不一致,导致数据更新失败:
    1. 使用基于行的复制时,update 操作在备库上会匹配前镜像,也就是带有 where 条件(见下节 binlog 文件结构)
    2. 当前镜像不匹配时,update 中最新的记录不会更新到备库
    3. 这种情况往往发生在位点错误或 binlog 丢失的情况下
binlog
  • 把 binlog 解析成可读文件
mysqlbinlog binlog.000001 --database=name --start-datetime=name  \
	--stop-datetime=name --start-position 245770410  \
	--stop-position 245793673 -f -v \
	--base64-output=decode-rows > tmpfile 
  • binlog 解析后的文件结构(update 操作)
BEGIN
/*!*/;
# at 92105505
# at 92105582
#160525 19:44:50 server id 101717547  end_log_pos 92105582      Table_map: `im_user_data_0005`.`im_user_cfg_tbl` mapped to number 1450
#160525 19:44:50 server id 101717547  end_log_pos 92106296      Update_rows: table id 1450 flags: STMT_END_F
BINLOG '
MpBFVxMrFhAGTQAAAG5rfQUAAKoFAAAAAAEAEWltX3VzZXJfZGF0YV8wMDA1AA9pbV91c2VyX2Nm
Z190YmwACAMP/AMBAQwMA0AAA8Q=
(二进制信息略)
'/*!*/;
### UPDATE im_user_data_0005.im_user_cfg_tbl
### WHERE
###   @1=222 /* INT meta=0 nullable=0 is_null=0 */
###   @2='xxxxx' /* VARSTRING(64) meta=64 nullable=0 is_null=0 */
###   @3='xxxxx' /* MEDIUMBLOB/MEDIUMTEXT meta=3 nullable=1 is_null=0 */
###   @4=222 /* INT meta=0 nullable=0 is_null=0 */
###   @5=1 /* TINYINT meta=0 nullable=0 is_null=0 */
###   @6=1 /* TINYINT meta=0 nullable=0 is_null=0 */
###   @7=2012-07-12 11:22:13 /* DATETIME meta=0 nullable=1 is_null=0 */
###   @8=2016-05-24 20:23:03 /* DATETIME meta=0 nullable=1 is_null=0 */
### SET
###   @1=1111 /* INT meta=0 nullable=0 is_null=0 */
###   @2='xxxxx' /* VARSTRING(64) meta=64 nullable=0 is_null=0 */
###   @3='xxxxx' /* MEDIUMBLOB/MEDIUMTEXT meta=3 nullable=1 is_null=0 */
###   @4=1111 /* INT meta=0 nullable=0 is_null=0 */
###   @5=1 /* TINYINT meta=0 nullable=0 is_null=0 */
###   @6=1 /* TINYINT meta=0 nullable=0 is_null=0 */
###   @7=2012-07-12 11:22:13 /* DATETIME meta=0 nullable=1 is_null=0 */
###   @8=2016-05-25 19:44:50 /* DATETIME meta=0 nullable=1 is_null=0 */
# at 92106296
#160525 19:44:50 server id 101717547  end_log_pos 92106323      Xid = 3286612943
COMMIT/*!*/;
常见的拓扑结构

  每一个 MySQL 实例都可以即做主库由做备库,一个主库可以有多个备库,一个备库只能有一个主库。
  理论上 MySQL 可以支持各种复杂(网状)的复制拓扑结构,但是不同的业务场景会限制复制拓扑的设计。

  • 主主结构
    1. 两个互为主库,但是应用只写其中一个,另一个可以作为热备份,或者作为只读库分担读流量
    2. 使用灵活,运维方便(因为切换方便)
      在这里插入图片描述
  • 一主多备
    1. 在读流量极大的情况下,需要这种一个主库(提供数据更新服务)多个备库(提供数据查询服务)的结构
    2. 这种结构运维的难点是主库 Crash 后,需要重新选择一个数据最完整的备库作为新的主库
      在这里插入图片描述
主备一致性保证
  • XA 事务(全同步):
    1. 为了保证 InnoDB redo log 与 MySQL binlog 的一致性
    2. Commit流程: InnoDB prepare->Binlog commit->InnoDB commit
    3. 提高并发度的方式: Group Commit,合并提交
    4. 相关参数
MySQL: sync_binlog 
InnoDB: innodb_flush_log_at_trx_commit
  • semi-sync (半同步)
    1. 半同步介于异步和全同步(sync_binlog 打开)之间
    2. 主库只需要等待至少一个从库节点收到并且 Flush Binlog 到 Relay Log 文件即可
    3. 半同步保证了主备的最终一致性,同时降低了主库事务 commit 的等待时间
参考资料

《高性能MySQL(第3版)》

发布了18 篇原创文章 · 获赞 1 · 访问量 924

猜你喜欢

转载自blog.csdn.net/ManWZD/article/details/104076885