一、MySQL的复制是将主数据库(master)的数据复制到从(slave)数据库上,专业一点讲就是将主数据库DDL和DML操作的二进制日志传到从库上,然后从库对这些二进制日志进行重做,使得主数据库与从数据库的数据保持同步。

二、MySQL复制的一些优点:

  1. 可以将大部分的查询任务放在从库上进行,降低主库的负载,提高性能,但要注意实时性要求高的数据仍需在主库上读取。
  2. 如果主库出现了宕机,可以快速切换到从库上,提高了可用性。
  3. 可以在从库上进行数据备份,降低在备份期间对主库的影响。
  4. 将数据挖掘和分析等工作放在从库上进行,可以降低对主库的性能影响。

三、MySQL复制处理数据的三种模式:

  1. 基于语句复制:也称为SBR(Statement Based Replication),基于实际执行的SQL语句来进行复制的方案,BINLOG_FORMAT=STATEMENT。
  2. 基于行的复制:也叫RBR(Row Bases Replication),BINLOG_FORMAT=ROW。
  3. 混合复制模式:也成MBR,基于SQL语句复制和行的复制,BINLOG_FORMAT=MIXED。

查看二进制日志的格式:

mysql> show global variables like 'binlog_format';
+---------------+-----------+
| Variable_name | Value | ---value的值有三种:statement,row,mixed
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)

设置二进制日志的格式:

mysql> set global binlog_format='row';   --设置全局binlog_format,可以使用set session binlog_format='row'来设置当前会话的binlog_format
Query OK, 0 rows affected (0.00 sec)
mysql> show GLOBAL variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)

在SQL中查看日志文件中的事件:

mysql> show binlog events in 'mysql-bin.000027' from 107; --from指定从日志哪个位置开始
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
| mysql-bin.000027 | 107 | Query | 3306 | 175 | BEGIN |
| mysql-bin.000027 | 175 | Query | 3306 | 264 | use `test`; insert into t1 values (10) |
| mysql-bin.000027 | 264 | Query | 3306 | 333 | COMMIT |
| mysql-bin.000027 | 333 | Query | 3306 | 401 | BEGIN |
| mysql-bin.000027 | 401 | Query | 3306 | 495 | use `test`; update t1 set id=70 where id=60 |
| mysql-bin.000027 | 495 | Query | 3306 | 564 | COMMIT |
| mysql-bin.000027 | 564 | Stop | 3306 | 583 | |
+------------------+-----+------------+-----------+-------------+---------------------------------------------+
7 rows in set (0.00 sec)

基于SQL语句的二进制日志记录原始SQL操作,而基于ROW格式的二进制日志记录的是每行数据的变更,采用64位编码,使用mysqlbinlog查看时须搭配--base64-output='decode-rows' --vv参数来解码查看。

四、MySQL复制流程

MySQL复制基于二进制日志,开启二进制日志功能是必须的。当从库启动复制时(start slave),首先创建一个I/O线程连接主库,主库接着创建Binlog Dump线程读取二进制日志事件发送给从库的I/O线程,I/O线程获取数据后更新从库的中继日志Relay Log,然后从库的SQL线程读取中继日志中更新的数据库事件并应用,如下图所示:

可以使用SHOW PROCESSLIST命令在主库和从库上分别执行,查看主库BINLOG DUMP线程和从库SQL线程状态:

----------------------在主库上-------------
mysql> show processlist\G
*************************** 3. row ***************************
Id: 18
User: repl
Host: localhost:2275
db: NULL
Command: Binlog Dump
Time: 76
State: Master has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
3 rows in set (0.00 sec)
--------------------在从库上---------------
*************************** 2. row ***************************
Id: 27
User: system user
Host:
db: NULL
Command: Connect
Time: 301
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 28
User: system user
Host:
db: NULL
Command: Connect
Time: 246703
State: Slave has read all relay log; waiting for the slave I/O thread to update it
Info: NULL

五、搭建复制环境

由于本人苦逼学生一枚,只有一台电脑,所以只能在一台电脑上开启多个MySQL服务,开启过程如下所示:

  1.停止mysql服务

  2.copy mysql安装目录到指定目录E:\,这里随意,不要和原目录重叠即可

  3.copy mysql data数据文件到E:\data

  4.copy一份my.ini文件到上面指定的目录下

  5.修改复制后的配置文件my.ini,内容如下:

  [client]

  port=3307 #第一个数据库的默认端口是3306 这里需要另外启用一个端口

  # The TCP/IP Port the MySQL Server will listen on

  port=3307

  # Path to installation directory. All paths are usually resolved relative to this.

  basedir="E:\MySQL\MySQL Server 5.5\"         #第二个数据库basedir

  # Path to the database root

  datadir="E:\MySQL\MySQL Server 5.5\data\"    #第二个数据库datadir

  6.创建新的mysql服务

  mysqld install MySQLSLAVE  --defaults-file="E:\MySQL\MySQL Server 5.5\my.ini"

  7.修改注册表,如下:

  KEY_LOCAL_MACHINE-->SYSTEM-->CurrentControlSet-->Services

  找到刚才创建的MySQLSLAVE,将ImagePath修改成如下":

  "E:\MySQL\MySQL Server 5.5\bin\mysqld" --defaults-file="E:\MySQL\data\my.ini" mysqlsalve

复制环境搭建过程如下:

  1.修改主数据库的配置文件my.ini,修改内容如下:

server-id=3306
#主从复制是通过二进制文件来进行,所以要开启日志功能
log-bin=mysql-bin
#主机,读写都可以
read-only=0
#需要备份数据,多个写多行
binlog-do-db=test
#不需要备份的数据库,多个写多行
binlog-ignore-db=mysql

  2.修改从数据库的配置文件my.ini,修改内容如下:

#主从配置
server-id=3307
log-bin=mysql-bin
#如果从服务器发现主服务器断掉,重新连接的时间差(秒)
#master-connect-retry=60
#只复制某个库
replicate-do-db=test
#不复制某个库
replicate-ignore-db=mysql

  3.保持主从的test库初始状态一致

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.05 sec)
---首先锁定表为读有效,防止数据库有更新操作,然后利用COPY/CP命令将数据文件目录复制到从库数据目录下
---或者直接关闭mysql服务,手动复制数据文件目录到指定目录下
---拷贝完后,恢复写操作

 mysql> unlock tables;
 Query OK, 0 rows affected (0.00 sec)

 

  4.在主库上创建一个专门用来复制的用户repl

mysql> GRANT REPLICATION SLAVE ON *.* TO 'REPL'@'127.0.0.1' IDENTIFIED BY '';
Query OK, 0 rows affected (0.31 sec)

  5.重启主库,然后执行show master status,记下file和position字段对应的参数

mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000031 | 262 | test | mysql |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

  6、在从库设置它的master:

mysql> change master to master_host='127.0.0.1',master_port=3306,master_user='repl',master_password='asdf',master_log_file='mysql-bin.000031',master_log_pos=262;

Query OK, 0 rows affected (0.19 sec)
----这里的master_log_file和master_log_pos对应刚才show master status记下的参数。

  7.在从库上开启复制start slave

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec) --这里有个warning,是因为我已经开启了slave

  8.验证复制搭建是否成功

mysql> show processlist\G;
*************************** 2. row ***************************
Id: 27
User: system user
Host:
db: NULL
Command: Connect
Time: 6349
State: Waiting for master to send event
Info: NULL
*************************** 3. row ***************************
Id: 28
User: system user
Host:
db: NULL
Command: Connect
Time: 580
State: Slave has read all relay log; waiting for the slave I/O thread to update it
Info: NULL
3 rows in set (0.00 sec)
----以上信息表名slave已经连上了master,并开始接收和执行日志---

  9.使用show slave status来查看slave信息

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 127.0.0.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000031
Read_Master_Log_Pos: 262
Relay_Log_File: Lenovo-PC-relay-bin.000059
Relay_Log_Pos: 408
Relay_Master_Log_File: mysql-bin.000031
Slave_IO_Running: Yes --I/O线程已开启
Slave_SQL_Running: Yes --SQL线程也开启
Replicate_Do_DB: test
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 262
Relay_Log_Space: 714
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0 --I/O没有错误
Last_IO_Error:
Last_SQL_Errno: 0 --sql应用也没有错误
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 3306
1 row in set (0.00 sec)

  10.验证复制的正确性

-------在主库上的test库创建表cc------
mysql> create table cc (id int not null);
Query OK, 0 rows affected (0.10 sec) mysql> insert into cc values (10),(20);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
-------在从库上查看是否存在表cc-----
mysql> show tables like 'cc';
+---------------------+
| Tables_in_test (cc) |
+---------------------+
| cc |
+---------------------+
1 row in set (0.00 sec) mysql> select * from cc;
+----+
| id |
+----+
| 10 |
| 20 |
+----+
2 rows in set (0.00 sec)
------------说明复制搭建已经成功------

六、半同步复制

MySQL复制默认采用异步的同步机制,主库和从库的数据之间存在一定的延时,不能保证数据的一致性和及时性。因此有必要开启半同步复制,而半同步复制模式是由mysql插件来实现,主从库使用不同的插件(semisync_master.so/semisync_slave.so),安装插件如下所示。

检查mysql服务是否支持动态加载插件

mysql> show variables like '%dynamic_loading%';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| have_dynamic_loading | YES |
+----------------------+-------+
1 row in set (0.00 sec)
----也可以直接执行select @@have_dynamic_loading

安装插件

mysql> install plugin  rpl_semi_sync_master soname 'semisync_master.dll';
ERROR 1125 (HY000): Function 'rpl_semi_sync_master' already exists --我已经安装了该插件

查看插件安装是否成功

mysql> select * from mysql.plugin;
+----------------------+---------------------+
| name | dl |
+----------------------+---------------------+
| rpl_semi_sync_master | semisync_master.dll |
+----------------------+---------------------+
1 row in set (0.03 sec)

从库也使用同样的方法安装semisync_slave插件

mysql> select * from mysql.plugin;
+---------------------+--------------------+
| name | dl |
+---------------------+--------------------+
| rpl_semi_sync_slave | semisync_slave.dll |
+---------------------+--------------------+
1 row in set (0.00 sec)

打开半同步复制,因为mysql默认是关闭的

mysql> show variables like '%semi_sync%';
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_no_slave | ON |
+------------------------------------+-------+
---------主库------
mysql> set global rpl_semi_sync_master_enabled=on;
Query OK, 0 rows affected (0.01 sec)
---------从库-------------
mysql> set global rpl_semi_sync_slave_enabled=on;
Query OK, 0 rows affected (0.00 sec)
----重启I/O线程
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.01 sec) mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

半同步复制配置完毕后,查看半同步复制的状态信息,在主库上执行show global status like '%semi_sync%';

mysql> show global status like '%semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 | --表示不是通过半同步复制及时响应的事务数
| Rpl_semi_sync_master_status | ON | --表示当前半同步复制已经打开
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 | --表示通过半同步模式复制到从库的事务数
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

半同步同步还有一个超时时间,超过了这个时间,主库将关闭半同步复制模式,改为异步复制。如果这时从库重新连接主库,主库将自动切换到半同步复制模式。查看超时时间

mysql> show variables like '%semi%time%';
+------------------------------+-------+
| Variable_name | Value |
+------------------------------+-------+
| rpl_semi_sync_master_timeout | 10000 | --10s
+------------------------------+-------+
1 row in set (0.00 sec)

七、MySQL复制主要启动参数

1.master_host,master_port,master_user,master_password这些参数主要用来记录需要复制的主库的地址,端口,用户,密码等信息,就不具体介绍了。

2.log_slave_updates:用来指定从库的更新操作是否记录到二进制日志中去,如果要搭建的是主-主复制,则该参数必须指定为ON(set global log_slave_updates=on或在配置文件中永久启动)

3.read-only:用来限制普通用户对从库的更新操作,只接收超级用户的更新操作。

4.master_connect_retry:指定当和主库丢失连接时重试的时间间隔,默认为60。

5.replicate_do_db,replicate_ignore_db,replicate_do_table,replicate_ignore_table:这些参数用来指定复制的数据库或表,比如指定复制的表为replicate_do_table=test.cc,其他的表则不会复制。

6.slave_skip_errors:用来指定从库复制中可以跳过的错误号或跳过全部错误,slave_skip_errors=[err_code1,err_code2...|all]

7.master_delay:用来指定延时复制的时间隔间

八、复制的管理维护

1.查看从库状态

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 127.0.0.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000031
Read_Master_Log_Pos: 736
Relay_Log_File: Lenovo-PC-relay-bin.000060
Relay_Log_Pos: 442
Relay_Master_Log_File: mysql-bin.000031
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: test
Replicate_Ignore_DB: mysql
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
----截取部分信息

2.主库和从库同步

-----在主库上执行-----
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
-----在从库上执行-----
mysql> select master_pos_wait('mysql-bin.000031','');
+--------------------------------------------+
| master_pos_wait('mysql-bin.000031','') |
+--------------------------------------------+
| 0 |
+--------------------------------------------+
1 row in set (0.03 sec)
--master_pos_wait的参数值可以在主库执行show master status得到
--该select语句会阻塞到从库达到指定的日志文件的偏移量后,返回0,表示与主库同步了
--完了之后在主库上执行unlock tables

3.从库复制出现错误

在从库应用中继日志时,可能会出现一些错误,例如表结构不对,函数不存在等,如果是不太重要的错误,则可使用sql_slave_skip_counter变量来忽略更新失败的语句。示例如下:

mysql> stop slave;
Query OK, 0 rows affected (0.02 sec) mysql> set global sql_slave_skip_counter=1;
----如果是autoincrement或last_insert_id()则为2 mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

4.主-主复制时自增变量冲突的问题

主-主复制需要定制auto_increment_increnment和auto_increment_offset的值来避免重复冲突,这两个变量的值默认为1,这也是重复冲突的源头

mysql> show variables like 'auto_increment_%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
2 rows in set (0.00 sec)

采用以下的设置可以避免重复

master1:auto_increment_increment=2,auto_increment_offset=1
master1:auto_increment_increment=2,auto_increment_offset=0

5.提高复制性能

方案一:采用一主多从的复制架构,利用replicate_do_db,replicate_ignore_db等参数使得不同的从库复制不同的库/表,降低每个从库的写入压力。

方案二:利用5.6版本的多线程并发复制,通过设置变量slave_parallel_workers来实现。

stop slave
set global slave_parallel_works=2;
start slave;
---或者在my.ini中天加slave_parallel_workers=2

6.主从切换

1.在每个从库上执行stop slave io_thread,停止接收日志,接着执行show processlist,如果state字段值为Has read all relay log,表示更新都应用完毕。

2.在需要提升为主库的从库上执行stop slave,reset slave和reset master,将从库重置成主库。

3.其他的从库执行都执行stop slave,然后执行change master to master_host=新的主库地址。

4.所有应用指向新的主库。

MySQL学习笔记十七:复制特性的更多相关文章

  1. mysql学习笔记4---mysql 复制---源代码

    mysql: c:底层 C++:相对上层 主备复制:主库通知备库来取 MYSQL复制源代码代码:SQL文件夹 int start_slave_thread( #ifdef HAVE_PSI_INTER ...

  2. mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记

    mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...

  3. 一千行MySQL学习笔记 (转)

    出处:  一千行MySQL学习笔记 /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权 ...

  4. MySQL学习笔记一

    MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...

  5. MySQL学习笔记-事务相关话题

    事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...

  6. MySQL学习笔记-数据库文件

    数据库文件 MySQL主要文件类型有如下几种 参数文件:my.cnf--MySQL实例启动的时候在哪里可以找到数据库文件,并且指定某些初始化参数,这些参数定义了某种内存结构的大小等设置,还介绍了参数类 ...

  7. MySQL学习笔记-cache 与 buffer

    Cache和Buffer是两个不同的概念,简单的说,Cache是加速"读",而 buffer是缓冲"写",前者解决读的问题,保存从磁盘上读出的数据,后者是解决写 ...

  8. MySQL学习笔记-大纲

    软件程序性能测试在之前<品味性能之道>系列中已经大量提到,讲解了很多测试方法.测试观念.测试思想等等.最近准备深入MySQL进行学习并总结.分别查阅<MySQL性能调优与架构设计&g ...

  9. 数据库MySQL学习笔记高级篇

    数据库MySQL学习笔记高级篇 写在前面 学习链接:数据库 MySQL 视频教程全集 1. mysql的架构介绍 mysql简介 概述 高级Mysql 完整的mysql优化需要很深的功底,大公司甚至有 ...

随机推荐

  1. C#调用Win32API

    Win32API.cs   using System;using System.Drawing;using System.Runtime.InteropServices;using Lordal.Wi ...

  2. 安装zabbix-3.0.3+nginx-1.10.1+php-5.6.22

    好久没有接触监控类的软件了,今天抽空搭建了下最新的版本 首先系统环境 zabbix-server-1 192.168.11.11   centos6.7 mysql-server    192.168 ...

  3. wex5中的星星评分

    新建一个空白的.w文件,然后在页面上放5个img星星图片 重要的是图片路径不能是绝对路径,要用相对路径,不然js操作的时候会出bug 添加两个label标签(标签随你挑,在这我就用label) 你到时 ...

  4. Where product development should start

    We all need to know our customers in order to create products they’ll actually buy. This is why the  ...

  5. 第一天---HTML基础学习

    HTML(hyper text markup language) HTML不是一种编程语言,而是一种标记语言(markup language),标记语言是一套markup tag(标记标签),HTML ...

  6. javascript模块化编程(三):require.js用法

    本文来自阮一峰 这个系列的第一部分和第二部分,介绍了Javascript模块原型和理论概念,今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require ...

  7. bzoj3048+3049+3050

    这套月赛题不是特别难 T1:离散化+单调队列,队列里出现数的种类不超过K+1,找最大的num[a[i]] T2:一眼可以看出BFS+状压DP,还要SPFA预处理出各个块之间的dis T3:线段树,没什 ...

  8. Win7网上邻居提示未授予用户在此计算机上的请求登录类型解决办法

        内容简介 装了Win7之后很多人遇到这样的问题,网上邻居访问Win7的电脑时出现“未授予用户在此计算机上的请求登录类型”问题.打开“控制面板”--“管理工具”--“本地安全策略”--“本地策略 ...

  9. Replace 删除、替换函数精解示例

    '************************************************************************* '**模 块 名:Replace函数精解示例 '* ...

  10. Web Api 与 Andriod 接口对接开发经验

    最近一直急着在负责弄Asp.Net Web Api 与 Andriod 接口开发的对接工作! 刚听说要用Asp.Net Web Api去跟 Andriod 那端做接口对接工作,自己也是第一次接触Web ...