1、MySQL的复制是将主数据库(master)的数据复制到从(slave)数据库上,专业一点讲就是将主数据库DDL和DML操做的二进制日志传到从库上,而后从库对这些二进制日志进行重作,使得主数据库与从数据库的数据保持同步。mysql
2、MySQL复制的一些优势:sql
3、MySQL复制处理数据的三种模式:数据库
查看二进制日志的格式:服务器
mysql> show global variables like 'binlog_format'; +---------------+-----------+ | Variable_name | Value | ---value的值有三种:statement,row,mixed +---------------+-----------+ | binlog_format | STATEMENT | +---------------+-----------+ 1 row in set (0.00 sec)
设置二进制日志的格式:session
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参数来解码查看。架构
4、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
5、搭建复制环境
因为本人苦逼学生一枚,只有一台电脑,因此只能在一台电脑上开启多个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 '1234567'; 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)
六、在从库设置它的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) ------------说明复制搭建已经成功------
6、半同步复制
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)
7、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:用来指定延时复制的时间隔间
8、复制的管理维护
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',' 736'); +--------------------------------------------+ | master_pos_wait('mysql-bin.000031',' 736') | +--------------------------------------------+ | 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.全部应用指向新的主库。