目录
1、概述
2、主从时间同步
3、主从服务器mysql部署
4、配置、启动从服务
5、测试
6、总结
1、概述
mysql内建的复制功能是mysql应用的“水平扩展”的架构,是mysql高性能运用的基础,为一个服务器配置一个或多个备库来进行数据的同步(准备的说不应该说是“同步”,因为主从服务器的数据根本不可能做同步)。在这样一个分布式的架构中各个服务器间时间应该同步才是,能为后期日志的统计分析提供更为准备的信息,这样才能准确反应出某个时间点我们系统的访问情况。
主从复制是一种异步复制的模型,说成“主从同步”是不精确的,应说是“主从复制”,先有主,再有从。因mysql主从复制原理的限定,在从库上只有一个sq线程(即使在mysql5.6中支持多线程,但也是针对库级别的)来重放中继日志中的事件,这种在主服务器能并发的查询请求在从服务器就成了串行化来执行,这是一个从服务器会慢于主服务器的一个原因。
对主从服务器在硬件选择上的建议:如果在规划主从时考虑到有可能会把从服务器提升为主服务器,那主从服务器硬件配置建议完全相同,应选择核多、主频高的CPU,频率高、总容量大的内存,多块高速的SAS硬盘(或SSD)及带有BBU的RAID卡,在RAID级别上建议选择raid10或raid50;如果从库只是用来作为主库的一个副本,以便于数据的备份,那从服务器的CPU没必要与主服务一个规格,但硬盘的IO这一块还是不要太差,IO高有助于事务的重放效率,在一定程度上能缩小与主库的时间差。
2、主从时间同步
主服务器配置成一ntpd服务器,自身与外网的ntpd服务进行时间校准,而又对从服务器提供时间校准服务。在生产环境中最好不要用ntpdate来强行调整服务器的时间,这样会对让服务器的时间产生空白区,注意,ntpdate工具是调整时间,而不是像ntpd工具一样是校准时间,两者的差别是挺大的。
主服务器基础环境:
[[email protected] ~]# cat /etc/issue CentOS release 6.4 (Final) Kernel \r on an \m [[email protected] ~]# uname -r 2.6.32-358.el6.x86_64 [[email protected] ~]# ifconfig | grep Bcast #从服务器的系统与主服务器相同,只是IP地址是192.168.0.202 inet addr:192.168.0.201 Bcast:192.168.0.255 Mask:255.255.255.0
安装配置主服务器成为ntpd时间服务器:
[[email protected] ~]# yum -y install ntp [[email protected] ~]# service ntpd start #启用服务后等个1-3分钟,就可用ntpq -p命令查看是否能与远程ntpd服务器连接 [[email protected] ~]# vi /etc/ntp.conf #配置ntp配置文件,使其成为从服务器的时间服务器 ……略…… # Hosts on local network are less restricted. #restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap restrict 192.168.0.0 mask 255.255.255.0 nomodify notrap #复制上边一行并启用,把ip修改成本地地址段 #外部时间服务器不可用时,以本地时间作为时间服务 server 127.127.0.0 fudge 127.127.0.0 stratum 10 ……略…… [[email protected] ~]# service ntpd restart #重启服务 [[email protected] ~]# chkconfig --level 235 ntpd on
在从服务器上安装配置ntp:
[[email protected] ~]# yum -y install ntp [[email protected] ~]# vim /etc/ntp.comf #注释掉默认的时间服务器,加上本地时间服务器 ……略…… # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). server 192.168.0.201 #server 0.centos.pool.ntp.org iburst #erver 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst ……略…… [[email protected] ~]# service ntpd restart [[email protected] ~]# chkconfig ntpd on [[email protected] ~]# ntpq -p #监控时间校准的状态信息
测试时可以试着把从服务器的时间调慢几分钟,然后观察从服务器的时间是否会慢慢的赶上来。
3、主从服务器mysql部署
3.1、主服务器安装配置
[[email protected] software]# pwd /root/software [[email protected] software]# ls mysql-5.6.24-linux-glibc2.5-x86_64.tar.gz [[email protected] software]# tar xf mysql-5.6.24-linux-glibc2.5-x86_64.tar.gz -C /usr/local/ [[email protected] software]# cd /usr/local [[email protected] local]# ln -sv mysql-5.6.24-linux-glibc2.5-x86_64 mysql [[email protected] local]# cd mysql [[email protected] mysql]# chown -R root.mysql ./* [[email protected] mysql]# mkdir /mnt/mydata/dbdata #创建数据目录 [[email protected] mysql]# chown -R mysql.mysql /mnt/mydata/dbdata [[email protected] mysql]# scripts/mysql_install_db --user=mysql --datadir=/mnt/mydata/dbdata/ #初始化数据库,如果没有mysql用户请自行创建
因mysql 5.6中的my.cnf文件太过简单,所以复制mysql 5.5中的配置文件再作一些修改:
[[email protected] mysql]# cp /opt/lamp/mysql55/support-files/my-large.cnf /etc/my.cnf 修改my.cnf配置文件 [[email protected] mysql]# vim /etc/my.cnf …… #thread_concurrency = 8 #注释此选项,在5.6中已被放弃 #指定数据目录 datadir = /mnt/mydata/dbdata #基于Innodb的表让表使用单独的表空间 innodb_file_per_table = 1 #启用慢查询日志 slow_query_log = 1 #如果查询时间长于“long_query_time”设定的值,那就把此查询查询到“slow_query_log_file”文件中 long_query_time = 1 slow_query_log_file = /var/log/mysql/master-slow.log #定义错误日志文件 log_error = /var/log/mysql/master.error …… #定义二进制日志文件 log-bin=/var/log/mysql/mysql-bin #每一次事件提交就使日志同步到磁盘,默认“sync_binlog=0”,表示让系统自己来flush使在内存的日志刷到磁盘,设置为“1”是一种安全的设置,因为当系统crash时你最多丢失一个事件,但相反会增加系统的IO,即使这样也建议设置成“1” sync_binlog = 1 …… #在5.6中已建议把二进制日志的格式修改成“row” binlog_format=row …… #设置服务器ID号 server-id = 100
[[email protected] mysql]# cp support-files/mysql.server /etc/rc.d/init.d/mysqld56 #复制启动脚本 [[email protected] mysql]# service mysqld56 start [[email protected] mysql]# ls /var/log/mysql master.error master-slow.log mysql-bin.000001 mysql-bin.index [[email protected] mysql]# vim /etc/profile.d/mysql56.sh #导出二进制文件路径 export PATH=/usr/local/mysql/bin:$PATH [[email protected] mysql]# source /etc/profile.d/mysql56.sh [[email protected] ~]# mysql #数据库连接测试 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 22 Server version: 5.6.24-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. mysql>
3.2、从服务器安装配置
从服务器的安装方法与主服务器一样,只是在my.cnf配置文件有些不同:
[[email protected] mysql]# vim /etc/my.cnf …… #thread_concurrency = 2 datadir = /mnt/mydata/dbdata innodb_file_per_table = 1 log_error = /var/log/mysql/slave.error #relay_log relay_log = /var/log/mysql/mysql-relay-bin sync_relay_log = 1 #设置让sql thread读取中继日志中的语句并在本地运用时记录到本地的二进制日志,当然从服务器要打开“log-bin”启用二进制日志,如果此从服务器还可以作为其他从服务器的主服务器,应启用“log_slave_updates = 1” log_slave_updates = 1 #在从服务器的数据中会多出两个文件,一个是master.info和relay-log.info,master.info文件记录了当前从服务器请求主服务器的二进制文件名与偏移量等信息,而relay.info文件记录了从服务器当前所使用的中继日志文件名与偏移量等信息,如果主服务器比较繁忙,文件中记录的偏移量这样的信息是时刻在变化的,可惜的是这些数据不是时时写入磁盘的,是先写进内存,再同步到磁盘,这样可能会对数据带来不一致的问题。在新版本中引入了下边两个变量来控制此行为,表示当每一次事件后就让数据更新到磁盘,也就是更新master.info和relay-log.info两个文件,这样尽可能让数据及时刷新到磁盘,让数据持久化,当然相应增加了系统的IO,但为了数据的安全就是值得的。 sync_master_info = 1 sync_relay_log_info =1 #security #设置从库为只读模式,但具有supper权限的用户不受此限制 read_only = 1 #跳过当mysqld启用时自动启用slave线程 skip_slave_start …… log-bin=/var/log/mysql/mysql-bin sync_binlog = 1 …… server-id = 200
[[email protected] mysql]# service mysqld56 start Starting MySQL.. SUCCESS! [[email protected] mysql]# ls /var/log/mysql #中继日志还没有生成,因从服务器线程没有启动 mysql-bin.000001 mysql-bin.index slave.error [[email protected] mysql]# ls /mnt/mydata/dbdata/ #master.info和relay-log.info两个文件没有生成,因为从服务线程没有启动 auto.cnf ibdata1 ib_logfile0 ib_logfile1 mysql performance_schema slave.pid test [[email protected] mysql]# mysql #测试 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.6.24-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. mysql>
4、配置、启动从服务
上边已把主从服务器各自的my.cnf配置文件已设置完毕,要想启动mysql的主从复制功能,现在还差一个从从服务器到主服务器的连接帐户,再启用从服务器上的复制线程即可。
4.1、在主服务器上创建拥有复制权限的帐户
[[email protected] ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 191 Server version: 5.6.24-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. mysql> GRANT replication slave,replication client ON *.* TO ‘repuser‘@‘192.168.0.%‘ IDENTIFIED BY ‘111111‘; Query OK, 0 rows affected (0.01 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) mysql> SHOW MASTER STATUS; #记录下当前主服务器所使用的二进制文件及position +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 430 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
4.2、从服务器连接主服务器、启动复制线程
[[email protected] mysql]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.6.24-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. mysql> CHANGE MASTER TO -> MASTER_HOST=‘192.168.0.201‘, -> MASTER_USER=‘repuser‘, -> MASTER_PASSWORD=‘111111‘, -> MASTER_LOG_FILE=‘mysql-bin.000001‘, -> MASTER_LOG_POS=0; #这里的偏移量我指定为“0”,零表示从开二进制日志的开头开始进行复制 mysql> SHOW SLAVE STATUS\G #查看slave的状态信息,IO thread和sql thread线程都还没有启动 *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.0.201 Master_User: repuser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 4 Relay_Log_File: mysql-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: No Slave_SQL_Running: No …… mysql> START SLAVE; #启动复制线程 mysql> SHOW SLAVE STATUS\G #两个线程已启动 *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.201 Master_User: repuser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 430 Relay_Log_File: mysql-relay-bin.000002 Relay_Log_Pos: 593 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes mysql> SHOW GRANTS FOR ‘repuser‘@‘192.168.0.%‘; #这个复制所用的帐户已经从主服务器复制到了从服务器 +--------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for [email protected]% | +--------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO ‘repuser‘@‘192.168.0.%‘ IDENTIFIED BY PASSWORD ‘*FD571203974BA9AFE270FE62151AE967ECA5E0AA‘ | +--------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
5、测试
在主服务器上创建、修改数据:
mysql> CREATE DATABASE mydb1; Query OK, 1 row affected (0.00 sec) mysql> USE mydb1; Database changed mysql> CREATE TABLE tb1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,name CHAR(20) NOT NULL,age TINYINT UNSIGNED); Query OK, 0 rows affected (0.05 sec) mysql> INSERT INTO tb1 (name,age) VALUES (‘tom‘,12),(‘jem‘,23); Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0
在从服务器上查看在主服务器的修改:
[[email protected] mysql]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 6 Server version: 5.6.24-log MySQL Community Server (GPL) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. mysql> SELECT * FROM mydb1.tb1; +----+------+------+ | id | name | age | +----+------+------+ | 1 | tom | 12 | | 2 | jem | 23 | +----+------+------+ 2 rows in set (0.00 sec)
测试证明:在主服务器上的修改已复制到了从服务器上。
6、总结
mysql的主从复制已搭建完毕,但这种复制并不能替代数据库的备份。由于从服务器是单进程模型(mysql 5.6的多线程也只能是库级别的),所以在一个比较繁忙的mysql系统上,从服务器可能会落后主服务器,这是mysql主从复制架构原生带来的特性,并不能真正做到主从的同步,所以在后期的维护工作中我们要用到一些监控工具来及时发现从服务器是否真正落后主服务器。在博文的最开始已提到在这种分布式的架构中时间同步的重要性,在用“show slave status\G”查看从服务器状态时有一个变量“Seconds_Behind_Master”这个值就是反应从服务器落后主服务器的时间,详细一点就是说明从服务器的SQL thread处理中继日志中的事件时,会把主服务器上日志中的timestamp与从服务器运行sql thread时的时间进行相关运算,这个差值就是“Seconds_Behind_Master”的值,所以主从服务器间的同步显得格外的重要。
“Seconds_Behind_Master”的值为0也不代表主服务器与从服务器已经同步,只能说sql thread已把relay log中的事件执行完了,因为主服务器的bin log不会实时的同步到从服务器上,从服务器上的relay log总会落后于主服务器的bin log,所以“Seconds_Behind_Master”这个值不具有真正意义上的参考价值。要监控主从是否一致,可以用percona-tools工具集中的pt-heartbeat工具。