一、MYSQL主从复制工作原理
主从同步机制:
1、外部数据更新,可以是web服务器,也可以是其他的更新语句。
2、数据增加,删除,更改一系列变化会记录到mysql的binlog中。
3、从服务器上的I/O线程读取主数据库上的binlog日志。
4、拷贝主数据库上的binlog日志到从数据库上的中继日志(relay log)。
5、从数据库上的SQL线程读取中继日志。
6、通过replay中继日志,在从数据库上再执行一遍。
这就是整个主从同步的一个过程。
二、实验步骤
系统:Centos6.4-x86_64
主服务器:node1:172.16.2.1
从服务器:node2:172.16.2.16
Mysql版本:mysql-5.5.33
Mysql的主从复制:
操作思路:
主服务器:
1.创建具有复制权限的用户帐号
2.设置server-id
3.启动二进制日志
从服务器:
1.启动中继日志
2.设置server-id
3.启动复制线程
同步主从服务器时间:用yum安装ansible的rpm包
[root@node1 ~]# vim /etc/ansible/hosts [hac] 172.16.2.1 172.16.2.16 [root@node1 ~]# ansible all -a 'ntpdate 172.16.0.1' 172.16.2.16 | success | rc=0 >> 22 Sep 20:40:50 ntpdate[2637]: step time server 172.16.0.1 offset 2676.843737 sec 172.16.2.1 | success | rc=0 >> 22 Sep 20:40:50 ntpdate[3045]: step time server 172.16.0.1 offset 2675.977884 sec [root@node1 ~]# ansible all -a 'date' 172.16.2.16 | success | rc=0 >> Sun Sep 22 20:41:15 CST 2013 172.16.2.1 | success | rc=0 >> Sun Sep 22 20:41:15 CST 2013
在主从服务器上安装Mysql过程不在介绍,请参考http://pangge.blog.51cto.com/6013757/1059896
安装过程注意文件权限要设置正确
配置主服务器:
1.编译配置文件:
[root@node1 ~]# vim /etc/my.cnf [mysqld] datadir = /mydata/data/ //数据存放目录 innodb_file_per_table = 1//设置每表单个表空间 log-bin=/mydata/data/mysql-bin //二进制日志存放位置,写绝对路径避免主从复制出现错误 server-id = 1 //server-id的值一定要和从服务器的server-id号区分开来
启动mysql服务
[root@node1 data]# service mysqld start
Starting MySQL..
2.创建具有复制权限的用户帐号
[root@node1 ~]# mysql mysql> grant replication client,replication slave on *.* to hailian@'172.16.%.%' identified by 'hailian'; Query OK, 0 rows affected (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.00 sec)
配置从服务器:
1.编辑配置文件
[root@node2 ~]# vim /etc/my.cnf [mysqld] datadir = /mydata/data/ //数据存放目录 innodb_file_per_table = 1//设置每表单个表空间 log-bin=/mydata/data/mysql-bin //二进制日志存放位置,写绝对路径避免主从复制出现错误 server-id = 20 //server-id的值一定要和从服务器的server-id号区分开来 relay-log=/mydata/data/relay-bin //中继日志 read-only=1 //从服务器设置为只读服务器
2.登录Mysql查看启动线程
[root@node2 ~]# mysql mysql> show processlist; +----+------+-----------+------+---------+------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+------+---------+------+-------+------------------+ | 1 | root | localhost | NULL | Query | 0 | NULL | show processlist | +----+------+-----------+------+---------+------+-------+------------------+ 1 row in set (0.00 sec) mysql> show slave status\G Empty set (0.00 sec) //说明从服务器还没有开始启用 mysql> help change master to Name: 'CHANGE MASTER TO' Description: Syntax: CHANGE MASTER TO option [, option] ... option: MASTER_BIND = 'interface_name' #将控制绑定到哪个接口上 | MASTER_HOST = 'host_name' #主服务器地址 | MASTER_USER = 'user_name' #具有复制权限的用户 | MASTER_PASSWORD = 'password' #具有复制权限用户的密码 | MASTER_PORT = port_num | MASTER_CONNECT_RETRY = interval | MASTER_HEARTBEAT_PERIOD = interval | MASTER_LOG_FILE = 'master_log_name' #指定从哪一个二进制日志文件开始复制 | MASTER_LOG_POS = master_log_pos #二进制日志事件的位置 | RELAY_LOG_FILE = 'relay_log_name' #中继日志 | RELAY_LOG_POS = relay_log_pos | MASTER_SSL = {0|1} #是否使用ssl功能 | MASTER_SSL_CA = 'ca_file_name' | MASTER_SSL_CAPATH = 'ca_directory_name' | MASTER_SSL_CERT = 'cert_file_name' | MASTER_SSL_KEY = 'key_file_name' | MASTER_SSL_CIPHER = 'cipher_list' | MASTER_SSL_VERIFY_SERVER_CERT = {0|1} | IGNORE_SERVER_IDS = (server_id_list)
配置从服务器连接主服务器
mysql> change master to master_host='172.16.2.1', -> master_user='hailian', -> master_password='hailian', -> master_log_file='mysql-bin.000004', -> master_log_pos=354; Query OK, 0 rows affected (0.02 sec)
启动从服务器线程
mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.2.1 Master_User: hailian Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 354 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 253 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: 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: 354 Relay_Log_Space: 403 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 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec)
测试
在主服务器上创建数据库testdb
mysql> create database testdb; Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec)
从服务器上进行查看
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec)
验证成功,实现了主从复制
三、如何在主服务器运行了一段时间后,实现主从复制
对从服务器从新进行初始化,其他配置不变
[root@node2 ~]# service mysqld stop Shutting down MySQL. [OK] [root@node2 mysql]# ./scripts/mysql_install_db --user=mysql --datadir=/mydata/data/ [root@node2 data]# chown -R mysql.mysql ./* [root@node2 ~]# service mysqld start Starting MySQL.. [ OK ]
首先在主服务器上完全备份数据,然后将数据导入到从服务器上
在主服务器上进行完全备份
[root@node1 data]# mysqldump -uroot --lock-all-tables --master-data=2 --events --all-databases > /root/all.sql
将备份好的数据复制到从服务器上
[root@node1 data]# scp /root/all.sql node2:/tmp
all.sql
将数据导入到从服务器的mysql中
mysql> source /tmp/all.sql; mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec)
此时查看主服务器上二进制日志文件及其事件位置
mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000005 | 182 | | | +------------------+----------+--------------+------------------+ 1 row in set (0.00 sec) mysql> show grants for hailian@'172.16.%.%'; +-------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for [email protected].%.% | +-------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'hailian'@'172.16.%.%' IDENTIFIED BY PASSWORD '*EAC0439681AAEB5A29A1B15EB26A89F369F943B7' | +-------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
在从服务器上配置连接主服务器
mysql> show slave status; Empty set (0.00 sec) mysql> change master to master_host='172.16.2.1', -> master_user='hailian', -> master_password='hailian', -> master_log_file='mysql-bin.000005', -> master_log_pos=182; Query OK, 0 rows affected (0.01 sec)
启动从服务器
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
查看从服务器状态
mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.2.1 Master_User: hailian Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000005 Read_Master_Log_Pos: 182 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 253 Relay_Master_Log_File: mysql-bin.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: 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: 182 Relay_Log_Space: 403 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 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec)
测试
在主服务上做一下修改
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec) mysql> use testdb; Database changed mysql> create table tb1(id int); Query OK, 0 rows affected (0.03 sec) mysql> insert into tb1 values (1),(2); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from tb1; +------+ | id | +------+ | 1 | | 2 | +------+ 2 rows in set (0.04 sec)
查看从服务器
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec) mysql> use testdb; Database changed mysql> show tables -> ; +------------------+ | Tables_in_testdb | +------------------+ | tb1 | +------------------+ 1 row in set (0.00 sec) mysql> select * from tb1; +------+ | id | +------+ | 1 | | 2 | +------+ 2 rows in set (0.03 sec)
验证成功,实现了主从复制
四、如何实现半同步复制
1、分别在主从节点上安装相关的插件
主节点上:
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; Query OK, 0 rows affected (0.02 sec) mysql> show global variables like '%semi%'; +------------------------------------+-------+ | 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 | +------------------------------------+-------+ 4 rows in set (0.00 sec)
从节点上:
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so'; Query OK, 0 rows affected (0.06 sec) mysql> show global variables like '%semi%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | OFF | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.00 sec)
2、启用半同步复制
在主服务上
mysql> SET GLOBAL rpl_semi_sync_master_enabled = ON;
Query OK, 0 rows affected (0.00 sec)
在从服务器上
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = ON;
Query OK, 0 rows affected (0.00 sec)
mysql> stop slave;
Query OK, 0 rows affected (0.02 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
3、确认半同步功能已经启用
在主服务上
mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | 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 global status like '%semi%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
测试
在主服务上
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 5 rows in set (0.00 sec) mysql> use testdb; Database changed mysql> create table tb2(name char(10)); Query OK, 0 rows affected (0.07 sec)
在从服务器上查看
mysql> use testdb; Database changed mysql> show tables; +------------------+ | Tables_in_testdb | +------------------+ | tb1 | | tb2 | +------------------+ 2 rows in set (0.00 sec) mysql> desc tb2; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | name | char(10) | YES | | NULL | | +-------+----------+------+-----+---------+-------+ 1 row in set (0.00 sec)
在主服务器上
mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 398 | | Rpl_semi_sync_master_net_wait_time | 398 | | Rpl_semi_sync_master_net_waits | 1 | | 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 | 293 | | Rpl_semi_sync_master_tx_wait_time | 293 | | Rpl_semi_sync_master_tx_waits | 1 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 1 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec) mysql> insert into tb2 values ('hailian'); Query OK, 1 row affected (0.00 sec) mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 439 | | Rpl_semi_sync_master_net_wait_time | 879 | | Rpl_semi_sync_master_net_waits | 2 | | 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 | 293 | | Rpl_semi_sync_master_tx_wait_time | 293 | | Rpl_semi_sync_master_tx_waits | 1 | | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | | Rpl_semi_sync_master_wait_sessions | 0 | | Rpl_semi_sync_master_yes_tx | 2 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec)
操作完成
注意要想实现半同步复制的永久有效,需要编辑配置文件,将设置的参数放到配置文件/etc/my.cnf中
五、基于ssl的mysql主从复制
在主服务器上自建CA,然后分为为主从服务器颁发证书,详细操作过程请参考http://lanlian.blog.51cto.com/6790106/1281720在这里就不再介绍
讲解配置过程
在主服务器上开启ssl功能
在[mydqld]字段中添加如下内容
ssl
ssl_ca = /etc/pki/CA/cacert.pem
ssl_cert = /usr/local/mysql/ssl/master.crt
ssl_key = /usr/local/mysql/ssl/master.key
重启服务后验证ssl是否开启成功
mysql> show global variables like '%ssl%'; +---------------+---------------------------------+ | Variable_name | Value | +---------------+---------------------------------+ | have_openssl | YES | | have_ssl | YES | | ssl_ca | /etc/pki/CA/cacert.pem | | ssl_capath | | | ssl_cert | /usr/local/mysql/ssl/master.crt | | ssl_cipher | | | ssl_key | /usr/local/mysql/ssl/master.key | +---------------+---------------------------------+ 7 rows in set (0.00 sec)
注意无论在master服务器还是在slave服务器上一定要修改ssl目录及其文件的属主属组为mysql
在主服务器上创建允许ssl连接的用户
mysql> grant replication client,replication slave on *.* to [email protected] identified by 'redhat' require ssl;
Query OK, 0 rows affected (0.03 sec)
从服务器上开启ssl功能
[mysqld] port = 3306 socket = /tmp/mysql.sock skip-external-locking key_buffer_size = 256M max_allowed_packet = 1M table_open_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size= 16M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 datadir = /mydata/data innodb_file_per_table = 1 ssl
验证ssl是否开启成功
mysql> show global variables like '%ssl%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | have_openssl | YES | | have_ssl | YES | | ssl_ca | | | ssl_capath | | | ssl_cert | | | ssl_cipher | | | ssl_key | | +---------------+-------+ 7 rows in set (0.01 sec)
从服务器连接主服务器
mysql> change master tomaster_host='172.16.2.1', -> master_user='lanlian', -> master_password='redhat', -> master_log_file='mysql-bin.000004', -> master_ssl=1, ->master_ssl_ca='/usr/local/mysql/ssl/cacert.pem', ->master_ssl_cert='/usr/local/mysql/ssl/slave.crt', -> master_ssl_key='/usr/local/mysql/ssl/slave.key'; mysql> show slave status\G *************************** 1.row *************************** Slave_IO_State: Master_Host: 172.16.18.7 Master_User: rpssl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 4 Relay_Log_File:relay-mysql.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: 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: 4 Relay_Log_Space: 107 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: Yes Master_SSL_CA_File:/usr/local/mysql/ssl/cacert.pem Master_SSL_CA_Path: Master_SSL_Cert:/usr/local/mysql/ssl/slave.crt Master_SSL_Cipher: Master_SSL_Key:/usr/local/mysql/ssl/slave.key Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert:No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0
8、启动从服务器线程:
mysql> start slave; mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.2.1 Master_User: lanlian Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 362 Relay_Log_File: relay-mysql.000002 Relay_Log_Pos: 508 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: 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: 362 Relay_Log_Space: 660 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: Yes Master_SSL_CA_File: /usr/local/mysql/ssl/cacert.pem Master_SSL_CA_Path: Master_SSL_Cert:/usr/local/mysql/ssl/slave.crt Master_SSL_Cipher: Master_SSL_Key: /usr/local/mysql/ssl/slave.key Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1 [root@node2 ssl]#mysql --ssl-ca=/usr/local/mysql/ssl/cacert.pem --ssl-cert=/usr/local/mysql/ssl/slave.crt--ssl-key=/usr/local/mysql/ssl/slave.key -urpssl -h172.16.2.1 �Cpredhat mysql> \s -------------- mysql Ver 14.14 Distrib5.5.33, for linux2.6 (x86_64) using readline 5.1 Connection id: 3 Current database: Current user: [email protected] SSL: Cipher inuse is DHE-RSA-AES256-SHA #基于ssl已可用 Current pager: stdout Using outfile: '' Using delimiter: ; Server version: 5.5.33-logMySQL Community Server (GPL) Protocol version: 10 Connection: 172.16.2.1via TCP/IP Server characterset: latin1 Db characterset: latin1 Client characterset: utf8 Conn. characterset: utf8 TCP port: 3306 Uptime: 29 min 24sec Threads: 3 Questions:14 Slow queries: 0 Opens: 33 Flush tables: 1 Open tables:26 Queries per second avg: 0.007
操作完成!
总结:以上是Mysql主从复制操作过程,深刻理解,熟练操作是非常必要的,不足之处多多指点!