mysql主从复制配置;
http://www.topthink.com/topic/3006.html
首先确保主从服务器上的Mysql版本相同
主数据库服务器配置:
1. 修改主数据库的配置文件my.ini, 修改之后重启Mysql服务。
[mysqld]
port=3306
server-id=10 #与从数据库不同
log-bin=c:\log-bin.log #日志文件
binlog-do-db=tpceshi #这里设置需要在主服务器记录日志的数据库,只有在这里设置了的数据库才能被复制到从服务器
binlog-ignore-db=mysql #这里设置在主服务器上不记度日志的数据库
2. 打开mysql命令行登陆mysql,,设置一个从数据库的账户,给从数据库分配复制权限
mysql>GRANT REPLICATION SLAVE ON *.* TO slave001'@'192.168.0.99' IDENTIFIED BY '123456';
slave001:用户名
192.168.0.99:IP
123456:密码
3.show masterstatus;显示主数据库状态

File:数据库日志文件
Position:日志位置
这2个选项用于在从数据库服务器中配置
////////////////
从数据库数据同步
////////////////
好了,现在可以停止主数据的的更新操作,并生成主数据库的备份,我们可以通过mysqldump导出数据到从数据库
注意在导出数据之前先对主数据库进行READ LOCK,以保证数据的一致性
mysql> flush tables with read lock;
之后是mysqldump
mysqldump -h127.0.0.1 -p3306 -uroot -p test > /home/chenyz/test.sql
最好在主数据库备份完毕,恢复写操作
mysql> unlock tables;
将刚才主数据备份的test.sql复制到从数据库,进行导入
从数据库服务器配置:
1.修改从数据库的my.ini,增加server-id参数,与主数据库不同
2.在mysql命令行,指定复制使用的用户,主数据库服务器的ip,端口以及开始执行复制日志的文件和位置
CHANGE MASTER TO
MASTER_HOST='192.168.1.238',
MASTER_USER='root',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='log-bin.000001',
MASTER_LOG_POS=120;
3.在从服务器上,启动slave进程
mysql> start slave;
4. 在从服务器进行show salvestatus验证
mysql> SHOW SLAVE STATUS\G
Slave_IO_State: Waiting for master to send event
Master_Host: localhost
Master_User: root
Master_Port: 3306
Connect_Retry: 3
Master_Log_File: mysql-bin.003
Read_Master_Log_Pos: 79
Relay_Log_File: gbichot-relay-bin.003
Relay_Log_Pos: 548
Relay_Master_Log_File: mysql-bin .003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
如果Slave_IO_Running和Slave_SQL_Running都为YES的话,则表明配置成功。
http://369369.blog.51cto.com/319630/790921
mysql主从复制
(超简单)
怎么安装mysql数据库,这里不说了,只说它的主从复制,步骤如下:
1、主从服务器分别作以下操作:
1.1、版本一致
1.2、初始化表,并在后台启动mysql
1.3、修改root的密码
2、修改主服务器master:
#vi /etc/my.cnf
[mysqld]
log-bin=mysql-bin //[必须]启用二进制日志
server-id=222 //[必须]服务器唯一ID,默认是1,一般取IP最后一段
3、修改从服务器slave:
#vi /etc/my.cnf
[mysqld]
log-bin=mysql-bin //[必须]启用二进制日志
server-id=226 //[必须]服务器唯一ID,默认是1,一般取IP最后一段
4、重启两台服务器的mysql
/etc/init.d/mysql restart
5、在主服务器上建立帐户并授权slave:
#/usr/local/mysql/bin/mysql -uroot -pmttang
mysql>GRANT REPLICATION SLAVE ON *.* to 'mysync'@'%' identified by 'q123456'; //一般不用root帐号,“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。
6、登录主服务器的mysql,查询master的状态
mysql>show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 308 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
注:执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化
7、配置从服务器Slave:
mysql>change master to aster_host='192.168.145.222',master_user='tb',master_password='q123456',
master_log_file='mysql-bin.,000004',master_log_pos=308; //注意不要断开,“308”无单引号。
Mysql>start slave; //启动从服务器复制功能
8、检查从服务器复制功能状态:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.2.222 //主服务器地址
Master_User: myrync //授权帐户名,尽量避免使用root
Master_Port: 3306 //数据库端口,部分版本没有此行
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 600 //#同步读取二进制日志的位置,大于等于>=Exec_Master_Log_Pos
Relay_Log_File: ddte-relay-bin.000003
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes //此状态必须YES
Slave_SQL_Running: Yes //此状态必须YES
......
注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。
以上操作过程,主从服务器配置完成。
9、主从服务器测试:
主服务器Mysql,建立数据库,并在这个库中建表插入一条数据:
mysql> create database hi_db;
Query OK, 1 row affected (0.00 sec)
mysql> use hi_db;
Database changed
mysql> create table hi_tb(id int(3),name char(10));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into hi_tb values(001,'bobu');
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hi_db |
| mysql |
| test |
+--------------------+
4 rows in set (0.00 sec)
从服务器Mysql查询:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hi_db | //I'M here,大家看到了吧
| mysql |
| test |
+--------------------+
4 rows in set (0.00 sec)
mysql> use hi_db
Database changed
mysql> select * from hi_tb; //可以看到在主服务器上新增的具体数据
+------+------+
| id | name |
+------+------+
| 1 | bobu |
+------+------+
1 row in set (0.00 sec)
10、完成:
编写一shell脚本,用nagios监控slave的两个“yes”,如发现只有一个或零个“yes”,就表明主从有问题了,发短信警报吧。
本文出自 “系统网络运维” 博客,请务必保留此出处http://369369.blog.51cto.com/319630/790921
==============================================================
http://freeloda.blog.51cto.com/2033581/1282329
大纲
一、前言
二、Mysql 基础知识
三、Mysql 复制(Replication)
四、Mysql 复制(Replication)类型
五、Mysql 主从复制基本步骤
六、Mysql 主从复制(异步)
七、Mysql 主从复制(半同步)
八、Mysql 复制工具
九、Mysql 复制注意事项
十、Mysql 复制过滤
一、前言
从这一篇博客开始我们就来学习mysql的高级课程,在前面的几篇博客我们讲解了mysql基础知识、mysql日志类型、mysql配置文件、mysql备份策略,这一篇博客中我们来讲解mysql的复制。
二、mysql基础知识
1.mysql日志类型
-
二进制日志
-
事务日志
-
错误日志
-
一般查询日志
-
中继日志
-
慢查询日志
注,有博友对mysql日志不怎么了解,可以参考这篇博客http://freeloda.blog.51cto.com/2033581/1253991
2.mysql二进制日志详解
说明:默认开启,精确的记录了用户对数据库中的数据进行操作的命令和操作的数据对象。
二进制日志文件的作用:
-
提供了增量备份的功能
-
提供了数据基于时间点的恢复,这个恢复的时间点可以由用户控制
-
为mysql的复制架构提供基础,将这主服务器的二进制日志复制到从服务器上并执行同样的操作,就可将数据进行同步
-
实现数据的高可用
-
分担负载
二进制日志默认存放位置:
-
数据目录下,以mysql-bin.XXXXXX命名的日志
二进制日志格式:
-
基于语句 statement
-
基于行 row
-
混合方式 mixed
二进制日志滚动方式:
-
重启服务
-
日志达到最大上限
-
执行flush logs
二进制日志事件:
-
position 基于位置,也就是offset(偏移量)
-
datetime 基于时间
-
timestamp
二进制日志的查看与删除方式:
|
1
2
3
4
5
|
mysql>show master status; 查看当前正在使用的二进制日志mysql>show binlog events in'mysql-bin.000001'; 查看二进制日志记录的事件[from position]mysql>flush logs; 二进制日志滚动mysql>show binary logs; 查看所有二进制日志mysql>purge binary logs to 'mysql-bin.000003'; 删除二进制日志 |
文件系统中查看二进制日志的命令:
|
1
2
3
4
5
6
|
mysqlbinlog相关选项,--start-position #开始位置--stop-position #结束位置--start-datetime 'yyyy-mm-dd hh:mm:ss'; #开始时间--stop-datetime ''; #结束时间 |
配置mysql的主配置文件:
|
1
2
3
4
5
6
7
8
9
|
sql_log_bin = {ON|OFF} #用于控制二进制日志信息是否记录进日志文件。默认为ON,表示启用记录功能。用户可以在会话级别修改此变量的值,但其必须具有SUPER权限binlog_cache_size = 32768 #默认值32768 Binlog Cache 用于在打开了二进制日志(binlog)记录功能的环境,是 MySQL 用来提高binlog的记录效率而设计的一个用于短时间内临时缓存binlog数据的内存区域。一般来说,如果我们的数据库中没有什么大事务,写入也不是特别频繁,2MB~4MB是一个合适的选择。但是如果我们的数据库大事务较多,写入量比较大,可与适当调高binlog_cache_size。同时,我们可以通过binlog_cache_use 以及 binlog_cache_disk_use来分析设置的binlog_cache_size是否足够,是否有大量的binlog_cache由于内存大小不够而使用临时文件(binlog_cache_disk_use)来缓存了binlog_stmt_cache_size = 32768 #当非事务语句使用二进制日志缓存,但是超出binlog_stmt_cache_size时,使用一个临时文件来存放这些语句log_bin = mysql-bin #指定binlog的位置,默认在数据目录下binlog-format= {ROW|STATEMENT|MIXED} #指定二进制日志的类型,默认为MIXED。如果设定了二进制日志的格式,却没有启用二进制日志,则MySQL启动时会产生警告日志信息并记录于错误日志中。sync_binlog = 10 #设定多久同步一次二进制日志至磁盘文件中,0表示不同步,任何正数值都表示对二进制每多少次写操作之后同步一次。当autocommit的值为1时,每条语句的执行都会引起二进制日志同步,否则,每个事务的提交会引起二进制日志同步max_binlog_cache_size = {4096 .. 18446744073709547520} #二进定日志缓存空间大小,5.5.9及以后的版本仅应用于事务缓存,其上限由max_binlog_stmt_cache_size决定。max_binlog_stmt_cache_size = {4096 .. 18446744073709547520} #二进定日志缓存空间大小,5.5.9及以后的版本仅应用于事务缓存expire_log_days = {0..99} #设定二进制日志的过期天数,超出此天数的二进制日志文件将被自动删除。默认为0,表示不启用过期自动删除功能。如果启用此功能,自动删除工作通常发生在MySQL启动时或FLUSH日志时 |
注:一般建议将binlog日志与数据文件分开存放,不但可以提高mysql性能,还可以增加安全性!
三、Mysql 复制(Replication)
1.Mysql 复制作用
-
负载平衡(load balancing)
-
备份
-
高可用性(high availability)和容错
2.Mysql 复制如何工作
主要有三步(如下图):
-
master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
-
slave将master的binary log events拷贝到它的中继日志(relay log);
-
slave重做中继日志中的事件,将改变反映它自己的数据。
具体说明:
该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。
下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。
此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。所以slave上数据一般要慢于master上数据。即master与slave之间的数据在一定时间内会不同步。
四、Mysql 复制(Replication)类型
1.mysql复制类型有以下一些基本原则
-
每个slave只能有一个master;
-
每个slave只能有一个唯一的服务器ID;
-
每个master可以有很多slave;
-
如果你设置log_slave_updates,slave可以是其它slave的master,从而扩散master的更新。
注,MySQL不支持多主服务器复制(Multimaster Replication)——即一个slave可以有多个master。但是,通过一些简单的组合,我们却可以建立灵活而强大的复制体系结构。
2.mysql复制类型
(1).一主多从模式
注,由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。
具体说明:
如果写操作较少,而读操作很时,可以采取这种结构。你可以将读操作分布到其它的slave,从而减小master的压力。但是,当slave增加到一定数量时,slave对master的负载以及网络带宽都会成为一个严重的问题。这种结构虽然简单,但是,它却非常灵活,足够满足大多数应用需求。一些建议:
-
不同的slave扮演不同的作用(例如使用不同的索引,或者不同的存储引擎)
-
用一个slave作为备用master,只进行复制
-
用一个远程的slave,用于灾难恢复
发送复制事件到其它slave,当设置log_slave_updates时,你可以让slave扮演其它slave的master。此时,slave把SQL线程执行的事件写进行自己的二进制日志(binary log),然后,它的slave可以获取这些事件并执行它。
(2).双主模式
注,Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。
具体说明:
主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都需要自己的可写的数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,如果两个服务器分别同时执行如下语句:
在第一个服务器上执行:
|
1
2
3
|
mysql> UPDATE tbl SET col=col + 1; 在第二个服务器上执行: mysql> UPDATE tbl SET col=col * 2; |
那么结果是多少呢?一台服务器是4,另一个服务器是3,但是,这并不会产生错误。
实际上,MySQL并不支持其它一些DBMS支持的多主服务器复制(Multimaster Replication),这是MySQL的复制功能很大的一个限制(多主服务器的难点在于解决更新冲突),但是,如果你实在有这种需求,你可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台。但是,可以通过其它一些方式来模拟这种多主服务器的复制。
(3).主从模式
注,这是master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中一个服务只能进行只读操作。
(4).带从服务器的Master-Master结构(Master-Master with Slaves)
注,这种结构的优点就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,而且还可以将读密集型的请求放到slave上。
总结:一般常用的两种复制类型一种是主从模式,另一种是一主多从模式。在这一篇博客中我们主要讲解主从模式复制。
五、Mysql 主从复制基本步骤
1.master 配置
-
启用二进制日志
-
配置一个唯一的server-id
-
创建具有复制权限的用户
2.slave 配置
-
启用中继日志
-
配置一个唯一的server-id
-
连接主服务器,并开始复制数据
-
启动数据复制
注,基本步骤我们就说到这里,下面我们来具体演示一下主从复制。
六、Mysql 主从复制(异步)
1.mysql异步复制
异步复制:MySQL本身支持单向的、异步的复制。异步复制意味着在把数据从一台机器拷贝到另一台机器时有一个延时,最重要的是这意味着当应用系统的事务在主服务器上提交并确认时数据并不能在同一时刻拷贝或应用到从服务器上。通常这个延时是由网络带宽、资源可用性和系统负载决定的。然而,使用正确的组件并且调优,复制能做到接近瞬时完成。
当主库有更新的时候,主库会把更新操作的SQL写入二进制日志(Bin log),并维护一个二进制日志文件的索引,以便于日志文件轮回(Rotate)。在从库启动异步复制的时候,从库会开启两个I/O线程,其中一个线程连接主库,要求主库把二进制日志的变化部分传给从库,并把传回的日志写入本地磁盘。另一个线程则负责读取本地写入的二进制日志,并在本地执行,以反映出这种变化。较老的版本在复制的时候只启用一个I/O线程,实现这两部分的功能。下面我们来具体演示一下mysql的异步复制。
2.实验拓扑
注,Active (master,node1) 192.168.1.201 , Passive (slave,node2)192.168.1.202
3.环境配置
时间同步
|
1
2
|
[root@node1 ~]# ntpdate 202.120.2.101[root@node2 ~]# ntpdate 202.120.2.101 |
4.操作系统
-
CentOS 6.4 X86_64
5.软件版本
-
Mysql 5.5.33 (注,这里用的是mysql 5.5.33二进制通用安装包,解压就能用)
6.安装并配置mysql
master:
(1).解压并链接
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@node1 src]# tar xf mysql-5.5.33-linux2.6-x86_64.tar.gz -C /usr/local/[root@node1 src]# cd /usr/local/ [root@node1 local]# ln -sv /usr/local/mysql-5.5.33-linux2.6-x86_64 mysql "mysql" -> "/usr/local/mysql-5.5.33-linux2.6-x86_64" [root@node1 local]# cd mysql [root@node1 mysql]# ll 总用量 200 drwxr-xr-x 2 root root 4096 8月 24 17:58 bin -rw-r--r-- 1 7161 wheel 17987 7月 15 20:01 COPYING drwxr-xr-x 3 root root 4096 8月 24 17:58 data drwxr-xr-x 2 root root 4096 8月 24 17:58 docs drwxr-xr-x 3 root root 4096 8月 24 17:58 include -rw-r--r-- 1 7161 wheel 134493 7月 15 20:01 INSTALL-BINARY drwxr-xr-x 3 root root 4096 8月 24 17:58 lib drwxr-xr-x 4 root root 4096 8月 24 17:58 man drwxr-xr-x 10 root root 4096 8月 24 17:58 mysql-test -rw-r--r-- 1 7161 wheel 2496 7月 15 20:01 README drwxr-xr-x 2 root root 4096 8月 24 17:58 scripts drwxr-xr-x 27 root root 4096 8月 24 17:58 share drwxr-xr-x 4 root root 4096 8月 24 17:58 sql-bench drwxr-xr-x 3 root root 4096 8月 24 17:58 support-files |
(2).新建mysql用户
|
1
2
3
4
|
[root@node1 mysql]# groupadd -g 3306 mysql[root@node1 mysql]# useradd -u 3306 -g mysql -s /sbin/nologin -M mysql [root@node1 mysql]# id mysql uid=3306(mysql) gid=3306(mysql) 组=3306(mysql) |
(3).修改mysql安装目录所有者与所属组
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[root@node1 mysql]# chown -R root.mysql /usr/local/mysql/*[root@node1 mysql]# ll 总用量 200 drwxr-xr-x 2 root mysql 4096 8月 24 17:58 bin -rw-r--r-- 1 root mysql 17987 7月 15 20:01 COPYING drwxr-xr-x 3 root mysql 4096 8月 24 17:58 data drwxr-xr-x 2 root mysql 4096 8月 24 17:58 docs drwxr-xr-x 3 root mysql 4096 8月 24 17:58 include -rw-r--r-- 1 root mysql 134493 7月 15 20:01 INSTALL-BINARY drwxr-xr-x 3 root mysql 4096 8月 24 17:58 lib drwxr-xr-x 4 root mysql 4096 8月 24 17:58 man drwxr-xr-x 10 root mysql 4096 8月 24 17:58 mysql-test -rw-r--r-- 1 root mysql 2496 7月 15 20:01 README drwxr-xr-x 2 root mysql 4096 8月 24 17:58 scripts drwxr-xr-x 27 root mysql 4096 8月 24 17:58 share drwxr-xr-x 4 root mysql 4096 8月 24 17:58 sql-bench drwxr-xr-x 3 root mysql 4096 8月 24 17:58 support-files |
(4).为mysql提供配置文件并修改
|
1
2
3
4
5
|
[root@node1 mysql]# cp support-files/my-large.cnf /etc/my.cnf[root@node1 mysql]# vim /etc/my.cnf[mysqld]#增加一行datadir = /mydata/data |
(5).为mysql提供启动脚本
|
1
2
|
[root@node1 mysql]# cp support-files/mysql.server /etc/init.d/mysqld[root@node1 mysql]# chmod +x /etc/init.d/mysqld |
(6).初始化mysql数据库
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[root@node1 ~]# mkdir -pv /mydata/datamkdir: 已创建目录 "/mydata" mkdir: 已创建目录 "/mydata/data" [root@node1 ~]# chown -R mysql.mysql /mydata/data/ [root@node1 ~]# /usr/local/mysql/scripts/mysql_install_db --datadir=/mydata/data/ --basedir=/usr/local/mysql --user=mysql Installing MySQL system tables... /usr/local/mysql/bin/mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directoryInstallation of system tables failed! Examine the logs in/mydata/data/ for more information.You can try to start the mysqld daemon with: shell> /usr/local/mysql/bin/mysqld --skip-grant &and use the command line tool /usr/local/mysql/bin/mysqlto connect to the mysql database and look at the grant tables: shell> /usr/local/mysql/bin/mysql -u root mysql mysql> show tablesTry 'mysqld --help' if you have problems with paths. Using --loggives you a log in /mydata/data/ that may be helpful.Please consult the MySQL manual section'Problems running mysql_install_db', and the manual section that describes problems on your OS. Another information source are the MySQL email archives available at http://lists.mysql.com/.Please check all of the above before mailing us! And remember, ifyou do mail us, you MUST use the /usr/local/mysql/scripts/mysqlbug script![root@node1 ~]# cd /mydata/data/[root@node1 data]# ll 总用量 8 drwx------ 2 mysql root 4096 8月 24 18:21 mysql drwx------ 2 mysql root 4096 8月 24 18:21 test |
(7).启动并测试
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
启动报错[root@node1 data]# service mysqld startStarting MySQL. ERROR! The server quit without updating PID file (/mydata/data/node1.test.com.pid).查看一下错误日志[root@node1 data]# vim node1.test.com.err130824 18:21:44 mysqld_safe Starting mysqld daemon with databases from /mydata/data/usr/local/mysql/bin/mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory 130824 18:21:44 mysqld_safe mysqld from pid file /mydata/data/node1.test.com.pid ended注,从错误日志中我们看到差一个库文件libaio,我们用yum安装一下即可。[root@node1 data]# yum install -y libaio重新初始化mysql[root@node1 data]# /usr/local/mysql/scripts/mysql_install_db --datadir=/mydata/data/ --basedir=/usr/local/mysql --user=mysql启动mysql[root@node1 data]# service mysqld startStarting MySQL... SUCCESS!环境变量配置[root@node1 data]# vim /etc/profile.d/mysql.shexport PATH=$PATH:/usr/local/mysql/bin[root@node1 data]# source /etc/profile测试一下[root@node1 data]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.5.33-log MySQL Community Server (GPL)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respective owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.03 sec)mysql> |
好了,到这里master的mysql配置完成,下面我们进行slave的mysql配置。
slave:
(1).解压并链接
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@node2 ~]# tar xf mysql-5.5.33-linux2.6-x86_64.tar.gz -C /usr/local/[root@node2 ~]# cd /usr/local/ [root@node2 local]# ln -sv /usr/local/mysql-5.5.33-linux2.6-x86_64 mysql "mysql" -> "/usr/local/mysql-5.5.33-linux2.6-x86_64" [root@node2 local]# cd mysql [root@node2 mysql]# ll 总用量 200 drwxr-xr-x 2 root root 4096 8月 24 18:41 bin -rw-r--r-- 1 7161 wheel 17987 7月 15 20:01 COPYING drwxr-xr-x 3 root root 4096 8月 24 18:41 data drwxr-xr-x 2 root root 4096 8月 24 18:41 docs drwxr-xr-x 3 root root 4096 8月 24 18:41 include -rw-r--r-- 1 7161 wheel 134493 7月 15 20:01 INSTALL-BINARY drwxr-xr-x 3 root root 4096 8月 24 18:41 lib drwxr-xr-x 4 root root 4096 8月 24 18:41 man drwxr-xr-x 10 root root 4096 8月 24 18:41 mysql-test -rw-r--r-- 1 7161 wheel 2496 7月 15 20:01 README drwxr-xr-x 2 root root 4096 8月 24 18:41 scripts drwxr-xr-x 27 root root 4096 8月 24 18:41 share drwxr-xr-x 4 root root 4096 8月 24 18:41 sql-bench drwxr-xr-x 3 root root 4096 8月 24 18:41 support-files |
(2).新建mysql用户
|
1
2
3
4
|
[root@node2 mysql]# groupadd -g 3306 mysql[root@node2 mysql]# useradd -u 3306 -g mysql -s /sbin/nologin -M mysql [root@node2 mysql]# id mysql uid=3306(mysql) gid=3306(mysql) 组=3306(mysql) |
(3).修改mysql安装目录所有者与所属组
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[root@node2 mysql]# chown -R root.mysql /usr/local/mysql/*[root@node2 mysql]# ll 总用量 200 drwxr-xr-x 2 root mysql 4096 8月 24 18:41 bin -rw-r--r-- 1 root mysql 17987 7月 15 20:01 COPYING drwxr-xr-x 3 root mysql 4096 8月 24 18:41 data drwxr-xr-x 2 root mysql 4096 8月 24 18:41 docs drwxr-xr-x 3 root mysql 4096 8月 24 18:41 include -rw-r--r-- 1 root mysql 134493 7月 15 20:01 INSTALL-BINARY drwxr-xr-x 3 root mysql 4096 8月 24 18:41 lib drwxr-xr-x 4 root mysql 4096 8月 24 18:41 man drwxr-xr-x 10 root mysql 4096 8月 24 18:41 mysql-test -rw-r--r-- 1 root mysql 2496 7月 15 20:01 README drwxr-xr-x 2 root mysql 4096 8月 24 18:41 scripts drwxr-xr-x 27 root mysql 4096 8月 24 18:41 share drwxr-xr-x 4 root mysql 4096 8月 24 18:41 sql-bench drwxr-xr-x 3 root mysql 4096 8月 24 18:41 support-files |
(4).为mysql提供配置文件并修改
|
1
2
3
4
|
[root@node2 mysql]# cp support-files/my-large.cnf /etc/my.cnf [root@node2 mysql]# vim /etc/my.cnf[mysqld]datadir = /mydata/data |
(5).为mysql提供启动脚本
|
1
2
|
[root@node2 mysql]# cp support-files/mysql.server /etc/init.d/mysqld [root@node2 mysql]# chmod +x /etc/init.d/mysqld |
(6).初始化mysql数据库
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
先安装libaio库文件[root@node2 mysql]# yum install -y libaio[root@node2 mysql]# mkdir -pv /mydata/datamkdir: 已创建目录 "/mydata" mkdir: 已创建目录 "/mydata/data" [root@node2 mysql]# cd /mydata/data [root@node2 data]# chown -R mysql.mysql /mydata/data/[root@node2 data]# /usr/local/mysql/scripts/mysql_install_db --datadir=/mydata/data/ --basedir=/usr/local/mysql --user=mysql[root@node2 data]# ll总用量 1084 drwx------ 2 mysql root 4096 8月 24 18:49 mysql -rw-rw---- 1 mysql mysql 27698 8月 24 18:49 mysql-bin.000001 -rw-rw---- 1 mysql mysql 1061358 8月 24 18:49 mysql-bin.000002 -rw-rw---- 1 mysql mysql 38 8月 24 18:49 mysql-bin.index drwx------ 2 mysql mysql 4096 8月 24 18:49 performance_schema drwx------ 2 mysql root 4096 8月 24 18:49 test |
(7).启动并测试
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
启动mysql[root@node2 data]# service mysqld startStarting MySQL... SUCCESS!环境变量配置[root@node2 data]# vim /etc/profile.d/mysql.shexport PATH=$PATH:/usr/local/mysql/bin[root@node1 data]# source /etc/profile测试一下[root@node2 data]# mysqlWelcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.5.33-log MySQL Community Server (GPL)Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respective owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.06 sec)mysql> |
好了,slave的mysql也配置完成了,下面我们来配置主从复制。
7.配置master
(1).修改配置文件
|
1
2
3
4
5
6
7
|
[root@node1 ~]# vim /etc/my.cnf#增加下面几行[mysqld]log-bin=master-binlog-bin-index=master-bin.indexserver-id = 1innodb_file_per_table = 1 |
(2).授权复制用户
|
1
2
3
4
|
mysql> grant replication slave on *.* to 'repluser'@'192.168.1.%' identified by 'replpass';Query OK, 0 rows affected (0.61 sec)mysql> flush privileges;Query OK, 0 rows affected (0.41 sec) |
(3).重启一下mysql服务
|
1
2
3
|
[root@node1 ~]# service mysqld restartShutting down MySQL....... SUCCESS! Starting MySQL............. SUCCESS! |
8.配置slave
(1).修改配置文件
|
1
2
3
4
5
6
|
[root@node2 ~]# vim /etc/my.cnf#增加下面几行[mysqld]relay-log = relay-logrelay-log-index = relay-log.indexserver-id = 10 |
(2).重启mysql服务
|
1
2
3
|
[root@node2 ~]# service mysqld restartShutting down MySQL..... SUCCESS! Starting MySQL........... SUCCESS! |
(3).连接主服务器并复制
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
查看master上二进制日志mysql> show master status;+-------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-------------------+----------+--------------+------------------+ | master-bin.000001 | 107 | | | +-------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)连接master服务器mysql> change master to master_host='192.168.1.201',master_user='repluser',master_password='replpass',master_log_file='master-bin.000001',master_log_pos=107;Query OK, 0 rows affected (0.07 sec)查看一下slave状态mysql> show slave status\G*************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.1.201 Master_User: repluser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000001 Read_Master_Log_Pos: 107 Relay_Log_File: relay-log.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: master-bin.000001 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: 107 Relay_Log_Space: 107 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: 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 1 row in set (0.00 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: 192.168.1.201 Master_User: repluser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000001 Read_Master_Log_Pos: 107 Relay_Log_File: relay-log.000002 Relay_Log_Pos: 254 Relay_Master_Log_File: master-bin.000001 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: 107 Relay_Log_Space: 404 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) |
9.主从复制测试
master:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
mysql> create database mydb;Query OK, 1 row affected (0.00 sec)mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) |
slave:
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.03 sec) |
好了,到这里异步的主从复制到这里配置完成。下面我们来说一下什么是半同步复制(或说是同步也行)。
七、Mysql 主从复制(半同步)
1.半同步复制
在说明半同步复制之前我们先来了解一下,什么是同步复制?同步复制:同步复制可以定义为数据在同一时刻被提交到一台或多台机器,通常这是通过众所周知的“两阶段提交”做到的。虽然这确实给你在多系统中保持一致性,但也由于增加了额外的消息交换而造成性能下降。使用MyISAM或者InnoDB存储引擎的MySQL本身并不支持同步复制,然而有些技术,例如分布式复制块设备(简称DRBD),可以在下层的文件系统提供同步复制,允许第二个MySQL服务器在主服务器丢失的情况下接管(使用第二服务器的复本)。了解了同步复制我们正下面来说一下,什么是半同步复制?
MYSQL 5.5开始,支持半自动复制。之前版本的MySQL Replication都是异步(asynchronous)的,主库在执行完一些事务后,是不会管备库的进度的。如果备库不幸落后,而更不幸的是主库此时又出现Crash(例如宕机),这时备库中的数据就是不完整的。简而言之,在主库发生故障的时候,我们无法使用备库来继续提供数据一致的服务了。Semisynchronous Replication(半同步复制)则一定程度上保证提交的事务已经传给了至少一个备库。Semi synchronous中,仅仅保证事务的已经传递到备库上,但是并不确保已经在备库上执行完成了。
此外,还有一种情况会导致主备数据不一致。在某个session中,主库上提交一个事务后,会等待事务传递给至少一个备库,如果在这个等待过程中主库Crash,那么也可能备库和主库不一致,这是很致命的。如果主备网络故障或者备库挂了,主库在事务提交后等待10秒(rpl_semi_sync_master_timeout的默认值)后,就会继续。这时,主库就会变回原来的异步状态。
MySQL在加载并开启Semi-sync插件后,每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务,两台主机的延迟又较小,则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。
2.异步与半同步异同
默认情况下MySQL的复制是异步的,Master上所有的更新操作写入Binlog之后并不确保所有的更新都被复制到Slave之上。异步操作虽然效率高,但是在Master/Slave出现问题的时候,存在很高数据不同步的风险,甚至可能丢失数据。
MySQL5.5引入半同步复制功能的目的是为了保证在master出问题的时候,至少有一台Slave的数据是完整的。在超时的情况下也可以临时转入异步复制,保障业务的正常使用,直到一台salve追赶上之后,继续切换到半同步模式。
3.具体配置
注,mysql5.5半同步插件是由谷歌提供,具体位置/usr/local/mysql/lib/plugin/下,一个是master用的semisync_master.so,一个是slave用的semisync_slave.so,下面我们就来具体配置一下。
master:
(1).安装插件
|
1
2
3
4
5
6
|
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; Query OK, 0 rows affected (0.39 sec)mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;Query OK, 0 rows affected (0.00 sec)mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;Query OK, 0 rows affected (0.00 sec) |
(2).修改配置文件
|
1
2
3
4
|
[root@node1 ~]# vim /etc/my.cnf[mysqld]rpl_semi_sync_master_enabled=1 #启用半同步rpl_semi_sync_master_timeout=1000 #超时时间为1s |
(3).重新启动服务
|
1
2
3
|
[root@node1 ~]# service mysqld restartShutting down MySQL... SUCCESS! Starting MySQL.. SUCCESS! |
slave:
(1).安装插件
|
1
2
3
4
5
6
7
8
|
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.38 sec)mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1; Query OK, 0 rows affected (0.00 sec)mysql> STOP SLAVE IO_THREAD;Query OK, 0 rows affected (0.00 sec)mysql> START SLAVE IO_THREAD;Query OK, 0 rows affected (0.01 sec) |
(2).修改配置文件
|
1
2
3
|
[root@node2 ~]# vim /etc/my.cnf[mysqld]rpl_semi_sync_slave_enabled=1 #启用半同步复制 |
(3).重新启动服务
|
1
2
3
|
[root@node2 ~]# service mysqld restartShutting down MySQL. SUCCESS! Starting MySQL.. SUCCESS! |
4.查看一下状态
master:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
mysql> SHOW GLOBAL STATUS LIKE 'rpl_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) |
slave:
|
1
2
3
4
5
6
7
|
mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';+----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.01 sec) |
5.测试一下
master:
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> create table user (id int(10));Query OK, 0 rows affected (0.42 sec)mysql> show tables;+----------------+ | Tables_in_mydb | +----------------+ | user | +----------------+ 1 row in set (0.00 sec)mysql> insert user value (1);Query OK, 1 row affected (0.34 sec) |
注,大家可以看到创建一个表的插入一个数据的时间都很长,说明半同步配置完成。
6.模拟一下故障
slave:
|
1
2
3
4
5
|
mysql> STOP SLAVE IO_THREAD;Query OK, 0 rows affected (0.01 sec)master:mysql> create table user1 (id int(10));Query OK, 0 rows affected (1.03 sec) |
注,大家可以看到主服务器会卡1s,我们超时时间设置的为1s。
7.查看一下状态
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';+--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | | Rpl_semi_sync_master_net_avg_wait_time | 1560 | | Rpl_semi_sync_master_net_wait_time | 10920 | | Rpl_semi_sync_master_net_waits | 7 | | Rpl_semi_sync_master_no_times | 1 | | Rpl_semi_sync_master_no_tx | 1 | | Rpl_semi_sync_master_status | OFF | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 985 | | Rpl_semi_sync_master_tx_wait_time | 985 | | 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 | 6 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec)mysql> STOP SLAVE IO_THREAD;Query OK, 0 rows affected (0.01 sec)mysql> SHOW GLOBAL STATUS LIKE 'rpl_semi%';+----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | OFF | +----------------------------+-------+ 1 row in set (0.00 sec) |
好了,到这里我们就配置完成了半同步复制。希望大家有所收获。下面我们来简单说一下mysql复制的工具。
八、Mysql 复制工具
1.percona-toolkit简介
percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括:
-
检查master和slave数据的一致性
-
有效地对记录进行归档
-
查找重复的索引
-
对服务器信息进行汇总
-
分析来自日志和tcpdump的查询
-
当系统出问题的时候收集重要的系统信息
percona-toolkit源自Maatkit 和Aspersa工具,这两个工具是管理mysql的最有名的工具,现在Maatkit工具已经不维护了,请大家还是使用percona-toolkit吧!这些工具主要包括开发、性能、配置、监控、复制、系统、实用六大类,作为一个优秀的DBA,里面有的工具非常有用,如果能掌握并加以灵活应用,将能极大的提高工作效率。
2.安装percona-toolkit
|
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@node1 ~]# wget http://www.percona.com/downloads/percona-toolkit/2.2.4/RPM/percona-toolkit-2.2.4-1.noarch.rpm[root@node1 ~]# yum install -y percona-toolkit-2.2.4-1.noarch.rpm[root@node1 ~]# pt #以pt开头命令 pt-agent pt-fingerprint pt-pmp pt-table-checksum pt-align pt-fk-error-logger pt-query-digest pt-table-sync pt-archiver pt-heartbeat pt-show-grants pt-table-usage pt-config-diff pt-index-usage pt-sift pt-upgrade pt-deadlock-logger pt-ioprofile pt-slave-delay pt-variable-advisor pt-diskstats pt-kill pt-slave-find pt-visual-explain pt-duplicate-key-checker pt-mext pt-slave-restart ptx pt-fifo-split pt-mysql-summary pt-stalk pt-find pt-online-schema-change pt-summary |
3.简单使用
常用工具:
(1).服务器摘要
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
[root@node1 ~]# pt-summary # Percona Toolkit System Summary Report ###################### Date | 2013-08-24 15:15:14 UTC (local TZ: CST +0800) Hostname | node1.test.com Uptime | 10:37, 3 users, load average: 0.00, 0.08, 0.07 Platform | Linux Release | CentOS release 6.4 (Final) Kernel | 2.6.32-358.el6.x86_64 Architecture | CPU = 64-bit, OS = 64-bit Threading | NPTL 2.12 SELinux | Disabled Virtualized | VMWare # Processor ################################################## Processors | physical = 2, cores = 0, virtual = 2, hyperthreading = no Speeds | 2x2261.309 Models | 2xIntel(R) Core(TM) i5 CPU M 430 @ 2.27GHz Caches | 2x3072 KB # Memory ##################################################### Total | 230.8M Free | 45.5M Used | physical = 185.3M, swap allocated = 1000.0M, swap used = 40.5M, virtual = 225.9M Buffers | 4.3M Caches | 75.0M Dirty | 104 kB UsedRSS | 69.0M Swappiness | 60 DirtyPolicy | 20, 10 DirtyStatus | 0, 0 # Mounted Filesystems ######################################## Filesystem Size Used Type Opts Mountpoint /dev/sda1 194M 14% ext4 rw /boot /dev/sda2 9.7G 27% ext4 rw / /dev/sda3 4.9G 3% ext4 rw /data tmpfs 116M 0% tmpfs rw /dev/shm # Disk Schedulers And Queue Size ############################# sda | [cfq] 128 sdb | [cfq] 128 sr0 | [cfq] 128 # Disk Partioning ############################################ Device Type Start End Size ============ ==== ========== ========== ================== /dev/sda Disk 21474836480 /dev/sda1 Part 1 26 205632000 /dev/sda2 Part 26 1301 10487232000 /dev/sda3 Part 1301 1938 5239503360 /dev/sda4 Part 1938 2611 5535613440 /dev/sda5 Part 1939 2066 1044610560 /dev/sdb Disk 21474836480 /dev/sr0 Disk 4353378304 # Kernel Inode State ######################################### dentry-state | 8709 3069 45 0 0 0 file-nr | 736 0 21159 inode-nr | 9018 568 # LVM Volumes ################################################ Unable to collect information # LVM Volume Groups ########################################## Unable to collect information # RAID Controller ############################################ Controller | No RAID controller detected # Network Config ############################################# FIN Timeout | 60 Port Range | 61000 # Interface Statistics ####################################### interface rx_bytes rx_packets rx_errors tx_bytes tx_packets tx_errors ========= ========= ========== ========== ========== ========== ========== lo 0 0 0 0 0 0 eth0 225000000 225000 0 200000000 225000 0 # Network Devices ############################################ Device Speed Duplex ========= ========= ========= eth0 1000Mb/s Full # Network Connections ######################################## Connections from remote IP addresses 192.168.1.102 2 Connections to local IP addresses 192.168.1.201 2 Connections to top 10 local ports 22 2 States of connections ESTABLISHED 2 LISTEN 10 # Top Processes ############################################## PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 19228 648 444 S 0.0 0.3 0:01.71 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.04 kthreadd 3 root RT 0 0 0 0 S 0.0 0.0 0:00.51 migration/0 4 root 20 0 0 0 0 S 0.0 0.0 0:00.14 ksoftirqd/0 5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 6 root RT 0 0 0 0 S 0.0 0.0 0:00.13 watchdog/0 7 root RT 0 0 0 0 S 0.0 0.0 0:00.17 migration/1 8 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/1 9 root 20 0 0 0 0 S 0.0 0.0 0:00.09 ksoftirqd/1 # Notable Processes ########################################## PID OOM COMMAND 1037 -17 sshd # Simplified and fuzzy rounded vmstat (wait please) ########## procs ---swap-- -----io---- ---system---- --------cpu-------- r b si so bi bo ir cs us sy il wa st 1 0 0 1 15 15 9 15 0 0 100 0 0 0 0 0 0 0 0 1000 1000 5 18 77 0 0 0 0 0 0 0 0 10 40 0 0 100 0 0 0 0 0 0 0 0 15 40 0 0 100 0 0 0 0 0 0 0 0 15 40 0 0 100 0 0 # The End #################################################### |
(2).服务器磁盘监测
|
1
2
3
4
5
6
7
8
9
10
11
|
[root@node1 ~]# pt-diskstats #ts device rd_s rd_avkb rd_mb_s rd_mrg rd_cnc rd_rt wr_s wr_avkb wr_mb_s wr_mrg wr_cnc wr_rt busy in_prg io_s qtime stime 1.0 sda 0.0 0.0 0.0 0% 0.0 0.0 2.0 6.0 0.0 33% 0.0 0.3 0% 0 2.0 0.0 0.3 1.0 sda2 0.0 0.0 0.0 0% 0.0 0.0 2.0 6.0 0.0 33% 0.0 0.3 0% 0 2.0 0.0 0.3 1.0 sda 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda2 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda2 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda2 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 1.0 sda 0.0 0.0 0.0 0% 0.0 0.0 0.0 0.0 0.0 0% 0.0 0.0 0% 0 0.0 0.0 0.0 |
(3).mysql服务状态摘要
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
[root@node1 ~]# pt-mysql-summary -- --user=root # Percona Toolkit MySQL Summary Report ####################### System time | 2013-08-24 15:16:55 UTC (local TZ: CST +0800) # Instances ################################################## Port Data Directory Nice OOM Socket ===== ========================== ==== === ====== 3306 /mydata/data 0 0 /tmp/mysql.sock # MySQL Executable ########################################### Path to executable | /usr/local/mysql/bin/mysqld Has symbols | Yes # Report On Port 3306 ######################################## User | root@localhost Time | 2013-08-24 23:16:55 (CST) Hostname | node1.test.com Version | 5.5.33-log MySQL Community Server (GPL) Built On | linux2.6 x86_64 Started | 2013-08-24 22:37 (up 0+00:39:17) Databases | 5 Datadir | /mydata/data/ Processes | 2 connected, 2 running Replication | Is not a slave, has 1 slaves connected Pidfile | /mydata/data/node1.test.com.pid (exists) # Processlist ################################################ Command COUNT(*) Working SUM(Time) MAX(Time) ------------------------------ -------- ------- --------- --------- Binlog Dump 1 1 2250 2250 Query 1 1 0 0 User COUNT(*) Working SUM(Time) MAX(Time) ------------------------------ -------- ------- --------- --------- repluser 1 1 2250 2250 root 1 1 0 0 Host COUNT(*) Working SUM(Time) MAX(Time) ------------------------------ -------- ------- --------- --------- 192.168.1.202 1 1 2250 2250 localhost 1 1 0 0 db COUNT(*) Working SUM(Time) MAX(Time) ------------------------------ -------- ------- --------- --------- NULL 2 2 2250 2250 State COUNT(*) Working SUM(Time) MAX(Time) ------------------------------ -------- ------- --------- --------- Master has sent all binlog to 1 1 2250 2250 NULL 1 1 0 0# Status Counters (Wait 10 Seconds) ##########################Variable Per day Per second 10 secs Aborted_clients 70 Binlog_cache_use 175 Bytes_received 90000 1 200 Bytes_sent 700000 7 2000 Com_admin_commands 100 Com_change_db 70 Com_create_table 100 Com_insert 175 Com_select 400 1 Com_set_option 250 Com_show_databases 70 Com_show_status 100 Com_show_tables 70 Com_show_variables 250 Connections 350 1 Created_tmp_files 225 Created_tmp_tables 500 4 Flush_commands 35 Handler_commit 350 Handler_prepare 350 Handler_read_first 100 Handler_read_rnd_next 15000 35 Handler_write 12500 35 Innodb_buffer_pool_bytes_data 90000000 1000 Innodb_buffer_pool_pages_flushed 1500 Innodb_buffer_pool_read_requests 22500 Innodb_buffer_pool_reads 5000 Innodb_buffer_pool_write_requests 5000 Innodb_data_fsyncs 1250 Innodb_data_read 175000000 2000 Innodb_data_reads 6000 Innodb_data_writes 2500 Innodb_data_written 50000000 600 Innodb_dblwr_pages_written 1500 Innodb_dblwr_writes 150 Innodb_log_write_requests 1250 Innodb_log_writes 500 Innodb_os_log_fsyncs 700 Innodb_os_log_written 700000 7 Innodb_pages_created 500 Innodb_pages_read 5000 Innodb_pages_written 1500 Innodb_rows_inserted 175 Open_table_definitions 1250 Opened_files 3500 4 Opened_table_definitions 1250 Opened_tables 1250 Qcache_not_cached 400 1 Queries 2250 4 Questions 2250 4 Rpl_semi_sync_master_clients 35 Rpl_semi_sync_master_net_avg_wait_time 60000 Rpl_semi_sync_master_net_wait_time 400000 4 Rpl_semi_sync_master_net_waits 250 Rpl_semi_sync_master_no_times 35 Rpl_semi_sync_master_no_tx 35 Rpl_semi_sync_master_tx_avg_wait_time 35000 Rpl_semi_sync_master_tx_wait_time 35000 Rpl_semi_sync_master_tx_waits 35 Rpl_semi_sync_master_yes_tx 225 Select_scan 500 Table_locks_immediate 1500 Threads_created 70 Uptime 90000 1 1 # Table cache ################################################ Size | 256 Usage | 10% # Key Percona Server features ################################ Table & Index Stats | Not Supported Multiple I/O Threads | Enabled Corruption Resilient | Not Supported Durable Replication | Not Supported Import InnoDB Tables | Not Supported Fast Server Restarts | Not Supported Enhanced Logging | Not Supported Replica Perf Logging | Not Supported Response Time Hist. | Not Supported Smooth Flushing | Not Supported HandlerSocket NoSQL | Not Supported Fast Hash UDFs | Unknown # Percona XtraDB Cluster ##################################### # Plugins #################################################### InnoDB compression | ACTIVE # Query cache ################################################ query_cache_type | ON Size | 16.0M Usage | 0% HitToInsertRatio | 0% # Semisynchronous Replication ################################ master semisync status | master trace level | 32, net wait (more information about network waits) master timeout in milliseconds | 1000 master waits for slaves | ON master clients | master net_avg_wait_time | master net_wait_time | master net_waits | master no_times | master no_tx | master timefunc_failures | master tx_avg_wait_time | master tx_wait_time | master tx_waits | master wait_pos_backtraverse | master wait_sessions | master yes_tx | Slave | Disabled # Schema ##################################################### |
(4).慢查询日志分析统计
|
1
|
[root@node1 ~]# pt-query-digest /mydata/data/mysql-slow.log |
(5).主从状态监测,提供给它一台mysql服务器的IP用户名密码,就可以分析出整个主从架构中每台服务器的信息,包括但不限于mysql版本,IP地址,server ID,mysql服务的启动时间,角色(主/从),Slave Status(落后于主服务器多少秒,有没有错误,slave有没有在运行)。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@node1 ~]# pt-slave-find --host=localhost --user=rootCannot connect to h=192.168.1.202,u=root localhost Version 5.5.33-log Server ID 1 Uptime 42:09 (started 2013-08-24T22:37:38) Replication Is not a slave, has 1 slaves connected, is not read_only Filters Binary logging MIXED Slave status Slave mode STRICT Auto-increment increment 1, offset 1 InnoDB version 5.5.33 |
(6).mysql死锁监测
|
1
|
[root@node1 ~]# pt-duplicate-key-checker --database=world h='127.0.0.1' --user=root --password=123456 |
(7).监测从库的复制延迟
|
1
|
[root@node1 ~]# pt-slave-delay --host 192.168.1.202 --user=root --password=123456 |
注,简单说明就到这里,想学习更详细的内容,命令的使用可以通过--help获知
九、Mysql 复制注意事项
注,在主-从架构上建议使用的配置
master:
|
1
2
3
4
5
|
sync_binlog=1 # 立刻同步binloginnodb_flush_logs_at_trx_commit=1 #立刻刷新innodb日志slave:skip_slave_start=1 #设置开机不同步read_only=1 #设置为只读 |
十、Mysql 复制过滤
master:
|
1
2
3
4
5
6
7
8
9
|
binlog-do-db=mydbbinlog-ignore-db=mysqlslave:replicate_do_dbrpplicate_ignore_dbreplicate_do_tablereplicate_ignore_tablereplicate_wild_do_tablereplicate_wild_ignore_table |
测试一下:
在从服务器上只复制testdb一个数据库
slave:
|
1
2
3
4
5
6
7
|
[root@node2 ~]# vim /etc/my.cnf[mysqld]replicate_do_db=testdbreplicate_do_db=mysql[root@node2 ~]# service mysqld restartShutting down MySQL. SUCCESS! Starting MySQL.. SUCCESS! |
master:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
mysql> create database mydb1;Query OK, 1 row affected (0.34 sec)mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mydb1 | | mysql | | performance_schema | | test | +--------------------+ 6 rows in set (0.00 sec) |
slave:
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec) |
注,大家可以看到没有同步mydb1,再测试一下。
master:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
mysql> create database testdb;Query OK, 1 row affected (0.01 sec)mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mydb1 | | mysql | | performance_schema | | test | | testdb | +--------------------+ 7 rows in set (0.00 sec)slave:mysql> show databases;+--------------------+ | Database | +--------------------+ | information_schema | | mydb | | mysql | | performance_schema | | test | | testdb | +--------------------+ 6 rows in set (0.00 sec) |
注,大家可以看到同步了testdb,好了到这里所有演示全部完成,希望大家有所收获。^_^……
本文出自 “Share your knowledge …” 博客,请务必保留此出处http://freeloda.blog.51cto.com/2033581/1282329
http://yangyaru.blog.51cto.com/6616699/1205001
Mysql-5.5主从实现同步、半同步、过滤、基于ssl安全复制、以及mysql-proxy实现mysql-5.6读写分离
案例拓扑图

创建mysql数据目录及进程用户并安装mysql
创建mysql服务进程的用户,提供mysql数据存放目录,并修改数据的目录。
|
1
2
3
4
5
|
[root@master ~]# mkdir -pv /mydata/datamkdir: created directory `/mydata'mkdir: created directory `/mydata/data'[root@master ~]# useradd -r mysql[root@master ~]# chown -R mysql.mysql /mydata/data |
将从网上下载的mysql二进制包复制到从服务端。
|
1
2
3
4
5
6
7
|
[root@master ~]# scp mysql-5.5.28-linux2.6-i686.tar.gz 172.16.20.7:/root/The authenticity of host '172.16.20.7 (172.16.20.7)' can't be established.RSA key fingerprint is 0a:0b:2f:67:c7:29:af:79:fe:2f:64:51:ca:01:1d:b0.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '172.16.20.7' (RSA) to the list of known hosts.root@172.16.20.7's password:mysql-5.5.28-linux2.6-i686.tar.gz 100% 172MB 6.9MB/s 00:25 |
这里以主服务端安装二进制源码包mysql。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
[root@master ~]# tar xf mysql-5.5.28-linux2.6-i686.tar.gz -C /usr/local/[root@master ~]# cd /usr/local/[root@master local]#ln -sv mysql-5.5.28-linux2.6-86.i386 mysql[root@master local]# cd mysql[root@master mysql]# scripts/mysql_install_db --user=mysql --datadir=/mydata/dataWARNING: The host 'master.yangyaru.com' could not be looked up with resolveip.This probably means that your libc libraries are not 100 % compatiblewith this binary MySQL version. The MySQL daemon, mysqld, should worknormally with the exception that host name resolving will not work.This means that you should use IP addresses instead of hostnameswhen specifying MySQL privileges !Installing MySQL system tables...OKFilling help tables...OKTo start mysqld at boot time you have to copysupport-files/mysql.server to the right place for your systemPLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !To do so, start the server, then issue the following commands:./bin/mysqladmin -u root password 'new-password'./bin/mysqladmin -u root -h master.yangyaru.com password 'new-password'Alternatively you can run:./bin/mysql_secure_installationwhich will also give you the option of removing the testdatabases and anonymous user created by default. This isstrongly recommended for production servers.See the manual for more instructions.You can start the MySQL daemon with:cd . ; ./bin/mysqld_safe &You can test the MySQL daemon with mysql-test-run.plcd ./mysql-test ; perl mysql-test-run.plPlease report any problems with the ./bin/mysqlbug script! |
给mysql服务提供一个启动服务脚本并开机自动启动。
|
1
2
|
[root@master mysql]# cp support-files/mysql.server /etc/init.d/mysqld[root@master mysql]# chkconfig --add mysqld |
将mysql的命令添加到PATH变量中并重读下脚本。
|
1
2
3
|
[root@master mysql]# vim /etc/profile.d/mysql.shexport PATH=$PATH:/usr/local/mysql/bin[root@master mysql]# . /etc/profile.d/mysql.sh |
给mysql提供一个配置文件并配置mysql配置文件
|
1
2
3
4
5
6
7
8
9
|
[root@master mysql]# cp support-files/my-large.cnf /etc/my.cnf[root@master ~]# cat /etc/my.cnf添加如下几行,其余与的不动datadir = /mydata/datainnodb_file_per_table = 1log-bin=master-binlog_bin_index = master_bin.indexbinlog_format=mixedserver-id = 6 |
启动mysql服务器进程。
[root@master ~]# service mysqld start
Starting MySQL................ [ OK ]
查看进程是否已启动。
直接在命令行提示符下连接上mysql测下是否可以连接上mysql,如果不可以再打开一个终端测试。
连接上mysql授权172.16.20.7允许复制数据。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@master ~]# mysqlWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 2Server version: 5.5.28-log MySQL Community Server (GPL)Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> grant replication slave on *.* to 'yangyaru'@'172.16.20.7' identified by 'yangyaru';Query OK, 0 rows affected (0.09 sec)mysql>flush privileges;mysql>exit |
从服务端的相关配置大多和主服务端的配置相同这里,我只列出不一样的配置。
从服务端的配置文件
|
1
2
3
4
5
6
7
8
|
[root@master ~]# cat /etc/my.cnf添加如下几行,其余与的不动datadir = /mydata/datainnodb_file_per_table = 1relay_log=relay_logrelay_bin_index = relay_log.indexbinlog_format=mixedserver-id = 7 |
查看下主服务端现在二进制日志的文件和位置。 
开启主服务端授权的帐号连接到主服务器端并开启复制。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@slave1 ~]# mysqlWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 1Server version: 5.5.28 MySQL Community Server (GPL)Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.Oracle is a registered trademark of Oracle Corporation and/or itsaffiliates. Other names may be trademarks of their respectiveowners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> CHANGE MASTER TO MASTER_HOST = '172.16.20.6', MASTER_PORT = 3306, MASTER_USER='yangyaru',MASTER_PASSWORD='yangyaru', MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=340;Query OK, 0 rows affected (0.17 sec)mysql> start slave;Query OK, 0 rows affected (0.03 sec)mysql> \qBye |
查看下当前我们的从服务器端记录二进制数据文件和position位置。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
mysql> show slave status\G*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 172.16.20.6Master_User: yangyaruMaster_Port: 3306Connect_Retry: 60Master_Log_File: master-bin.000001Read_Master_Log_Pos: 340Relay_Log_File: relay_log.000002Relay_Log_Pos: 254Relay_Master_Log_File: master-bin.000001Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB:Replicate_Ignore_DB:Replicate_Do_Table:Replicate_Ignore_Table:Replicate_Wild_Do_Table:Replicate_Wild_Ignore_Table:Last_Errno: 0Last_Error:Skip_Counter: 0Exec_Master_Log_Pos: 340Relay_Log_Space: 404Until_Condition: NoneUntil_Log_File:Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File:Master_SSL_CA_Path:Master_SSL_Cert:Master_SSL_Cipher:Master_SSL_Key:Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error:Last_SQL_Errno: 0Last_SQL_Error:Replicate_Ignore_Server_Ids:Master_Server_Id: 61 row in set (0.03 sec) |
可以看到当前是Read_Master_Log_Pos: 340。
到此简单的主从mysql服务配置就已经完成^_^。
下面对此配置测试下,在主服务器端创建一个yangyarudb的数据库。看下从服务器上是否复制。
现在对我们的配置做下延伸。
一、主从服务器读写分离实现负载均衡。
一般我们从服务器端是只负责客户的读请求的,主服务端负责写请求的。那么配置下吧!
首先查看下从服务器端的只读方式是否打开。
|
1
2
3
4
5
6
7
8
9
|
mysql> show global variables like 'read%';+----------------------+---------+| Variable_name | Value |+----------------------+---------+| read_buffer_size | 1048576 || read_only | OFF || read_rnd_buffer_size | 4194304 |+----------------------+---------+3 rows in set (0.00 sec) |
打开我们的只读方式有两种
一种是在mysql服务器端的全局模式下配置,但是在全局模式下配置mysql重启之后就会失效;
一种是在/etc/my.cnf配置文件中配置,这个配置是永久生效;这里我们选择第二种。
给/etc/my.cnf配置文件添加一行如下:
[root@slave1 ~]# vim /etc/my.cnf
read_only = ON
然后重启启动下我们的mysql服务器。
[root@slave1 ~]# service mysqld restart
Shutting down MySQL...... [ OK ]
Starting MySQL.................. [ OK ]
主服务器端执行了写操作,日志文件立即同步到从服务器,为了保证事务的完整性。可以在
从服务器端配置文件的[mysqld]段中添加skip_slave_start = 1来实现从服务器的mysql服务在启动时候不要自动启动从服务线程。
二、实现主从服务器半同步。
半同步的定义:主服务器端执行了写操作,必须往从服务器端复制一份,才能给客户端返回提交状态。
这里我们需要在主服务器端安装semisync_master.so从服务器端安装semisync_slave.so
具体步骤如下:
主服务器端:
mysql> install plugin rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.36 sec)
主服务器端开启semi_sync功能,并设置等待时候为3秒。
mysql> set global rpl_semi_sync_master_enabled =1;
Query OK, 0 rows affected (0.02 sec)
mysql> set global rpl_semi_sync_master_timeout = 3000 ;
Query OK, 0 rows affected (0.00 sec)
从服务器端:
mysql> install plugin rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.28 sec)
从服务器端开启semi_sync功能。
mysql> set global rpl_semi_sync_slave_enabled =1;
Query OK, 0 rows affected (0.03 sec)
半同步复制是如果从服务端没有开启的话,主服务端第一次会延迟3秒中之后提交,之后主服务端会降低延迟不再等待从服务端。从服务端开启之后在追赶上主服务端让后在实现半同步。
实现演示下:
1、先关闭从服务端。
mysql> stop slave;
Query OK, 0 rows affected (0.02 sec)
2、主服务端创建一个semidb数据库
3、从服务端启动服务。
mysql> start slave;
Query OK, 0 rows affected (0.03 sec)
mysql> show slave status\G 
三、percona-toolkit是一个专门对msyql主从服务的管理的一个工具。这里我们可以安装下使用下。
主从服务都安装percona-toolkit
主服务端下载安装下
[root@master ~]# yum -y --nogpgcheck localinstall percona-toolkit-2.2.2-1.noarch.rpm
从服务端从主服务端复制过来安装:
[root@master ~]# scp percona-toolkit-2.2.2-1.noarch.rpm 172.16.20.7:/root/
root@172.16.20.7's password:
percona-toolkit-2.2.2-1.noarch.rpm 100% 1632KB 816.0KB/s 00:02
安装之后会给我们生成很多以pt开头的命令行工具这些命令,如pt-slave-delay:这个命令行工具,他是专门让我们的从服务端比主服务端慢一点的的设置。
这些命令我们不一一做介绍了哈:
四、基于ssl加密的方式实现主从复制。
Mysql的主从复制是明文传送的,但在生产环境中我们的主从服务器不可以在同一个机房或在同一个局域网中,这时候我们的数据传输肯定需要用到ssl啦。Ssl的实现其实很简单的,如下操作步骤。
主服务器端自创创建CA,并为主服务器端和从服务器端颁发CA。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@master ~]#vim /etc/pki/tls/openssl.conf #如果你的系统平台是5.8的就需要该这些将dir = ../../CA 更改为:dir = /etc/pki/CA[root@master ~]# (umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 1024)[root@master ~]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650 #CA 的相关信息这里我们根据自己的实际情况填写。You are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [XX]:CNState or Province Name (full name) []:HENANLocality Name (eg, city) [Default City]:ZHENGZHOUOrganization Name (eg, company) [Default Company Ltd]:mageduOrganizational Unit Name (eg, section) []:techCommon Name (eg, your name or your server's hostname) []:ca.magedu.comEmail Address []:caadmin.magedu.com[root@master ~]# mkdir /etc/pki/CA/{certs,newcerts,crl} #如果你的系统平台是5.8需要创建这些文件。[root@master ~]# touch /etc/pki/CA/index.txt[root@master ~]# echo 01 > /etc/pki/CA/serial |
主从服务器端都创建密钥和申请文件,步骤一样这里以主服务端为例。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[root@master ~]#mkdir /usr/local/mysql/ssl[root@master ~]#(umask 077;openssl genrsa -out /usr/local/mysql/ssl/mysql.key 1024)[root@master ~]#openssl req -new -key /usr/local/mysql/ssl/mysql.key -out /usr/local/mysql/ssl/mysql.csr -days 365 #申请书的内容根据自己的实际情况填写。You are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.-----Country Name (2 letter code) [XX]:CNState or Province Name (full name) []:HENANLocality Name (eg, city) [Default City]:ZHENGZHOUOrganization Name (eg, company) [Default Company Ltd]:mageduOrganizational Unit Name (eg, section) []:techCommon Name (eg, your name or your server's hostname) []:master.yangyaru.comEmail Address []:master.yangyaru.comPlease enter the following 'extra' attributesto be sent with your certificate requestA challenge password []:An optional company name []: |
主服务器端的CA证书颁发:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
[root@master ~]#openssl ca -in /usr/local/mysql/ssl/mysql.csr -out /mydata/data/ssl/mysql.crt -days 365Using configuration from /etc/pki/tls/openssl.cnfCheck that the request matches the signatureSignature okCertificate Details:Serial Number: 1 (0x1)ValidityNot Before: May 19 23:47:49 2013 GMTNot After : May 19 23:47:49 2014 GMTSubject:countryName = CNstateOrProvinceName = HENANorganizationName = mageduorganizationalUnitName = techcommonName = master.yangyaru.comemailAddress = master.yangyaru.comX509v3 extensions:X509v3 Basic Constraints:CA:FALSENetscape Comment:OpenSSL Generated CertificateX509v3 Subject Key Identifier:9B:42:46:CF:1D:83:56:7D:04:37:CB:40:89:A2:07:EC:C7:9D:C2:0DX509v3 Authority Key Identifier:keyid:07:7C:CF:69:74:1D:4D:D8:09:7A:3C:D9:F3:07:B6:46:40:E0:47:0CCertificate is to be certified until May 19 23:47:49 2014 GMT (365 days)Sign the certificate? [y/n]:y1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated |
从服务器端创建申请书之后将申请书发送到CA让CA签署。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
[root@slave ~]#scp /usr/local/mysql/ssl/mysql.csr 172.16.20.6:/tmpThe authenticity of host '172.16.20.6 (172.16.20.6)' can't be established.RSA key fingerprint is 0a:0b:2f:67:c7:29:af:79:fe:2f:64:51:ca:01:1d:b0.Are you sure you want to continue connecting (yes/no)? yPlease type 'yes' or 'no': yesWarning: Permanently added '172.16.20.6' (RSA) to the list of known hosts.root@172.16.20.6's password:mysql.csr 100% 708 0.7KB/s 00:00[root@master ~]#openssl ca -in /tmp/mysql.csr -out /tmp/mysql.crt -days 365Using configuration from /etc/pki/tls/openssl.cnfCheck that the request matches the signatureSignature okCertificate Details:Serial Number: 2 (0x2)ValidityNot Before: May 19 23:51:08 2013 GMTNot After : May 19 23:51:08 2014 GMTSubject:countryName = CNstateOrProvinceName = HENANorganizationName = mageduorganizationalUnitName = techcommonName = slave.yangyaru.comemailAddress = slave.yangyaru.comX509v3 extensions:X509v3 Basic Constraints:CA:FALSENetscape Comment:OpenSSL Generated CertificateX509v3 Subject Key Identifier:A8:DB:F3:88:F1:25:A0:02:B6:F5:49:EE:67:2B:C1:BE:66:B9:E8:A7X509v3 Authority Key Identifier:keyid:07:7C:CF:69:74:1D:4D:D8:09:7A:3C:D9:F3:07:B6:46:40:E0:47:0CCertificate is to be certified until May 19 23:51:08 2014 GMT (365 days)Sign the certificate? [y/n]:yes1 out of 1 certificate requests certified, commit? [y/n]yWrite out database with 1 new entriesData Base Updated[root@master ~]# scp /tmp/mysql.crt 172.16.20.7:/tmproot@172.16.20.7's password:mysql.crt 100% 3239 3.2KB/s 00:00[root@slave ~]# mv /tmp/mysql.crt /mydata/data/ssl |
将CA文件按拷贝到从服务端证书所在目录
[root@master ~]# scp /etc/pki/CA/cacert.pem 172.16.20.7:/mydata/data/ssl/
root@172.16.20.7's password:
cacert.pem 100% 1070 1.0KB/s 00:00
注意:生成的证书和密钥的属组和属主都要改成mysql用户。
至此,证书颁发成功!!
下面配置主从服务器让他们支持ssl功能。
首先看下ssl功能的开启状态,如果没有开启就开启。
Master:
主服务器端配置开启ssl功能
[root@master ~]#vim /etc/my.cnf
添加如下几行,其余不动
ssl #开启服务
ssl_ca = /mydata/data/ssl/cacert.pem #指定下CA文件所在的位置在那
ssl_cert = /mydada/data/ssl/mysql.crt #证书文件的位置
ssl_key = /usr/local/mysql/ssl/mysql.key #密钥所在的位置
重启服务,查看其变量的状态。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@master ~]#service mysqld restartmysql>show variables like ‘%ssl%’;+---------------+--------------------------------+| Variable_name | Value |+---------------+--------------------------------+| have_openssl | YES || have_ssl | YES || ssl_ca | /mydata/data/ssl/cacert.pem || ssl_capath | || ssl_cert | /mydata/data/ssl/mysql.crt || ssl_cipher | || ssl_key | /usr/local/mysql/ssl/mysql.key |+---------------+--------------------------------+7 rows in set (0.00 sec) |
创建一个帐号让从服务器端可以连接到主服务器端复制数据,但是要添加上基于密钥认证才可以。
mysql>grant replication slave on *.* to 'yangyaru'@'172.16.20.7' identified by 'yangyaru' require ssl;
mysql>flush privileges;
查看主服务器端现在二进制的文件和所在的位置记下它,等会从服务端连接直接从这里开始复制。 
slave:
配置mysql配置文件:
[root@slave ~]# vim /etc/my.cnf
添加如下几行,其余不动
ssl #开启服务
ssl_ca = /mydata/data/ssl/cacert.pem #指定下CA文件所在的位置在那
ssl_cert = /mydada/data/ssl/mysql.crt #证书文件的位置
ssl_key = /usr/local/mysql/ssl/mysql.key #密钥所在的位置
因为我们之前连接过主服务器端所以这里我们做下修改设置。
|
1
2
3
4
5
6
7
8
9
10
11
|
mysql> change master to-> master_host='172.16.20.6',-> master_user='yangyaru',-> master_password='yangyaru',-> master_log_file='master-bin.***',-> master_log_pos=***,-> master_ssl=1,-> master_ssl_ca='/etc/pki/CA/cacert.pem',-> master_ssl_cert='/mydata/data/ssl/mysql.crt',-> master_ssl_key='/mydata/data/ssl/mysql.key';mysql>start slave; |
如果出现下面红色的显示就说明,我们的配置已经生效。
mysql>show slave status\G
mysql数据复制的过滤。
(一般我们不建议主服务器端过滤数据,它会使我们二进制日志不完整,所以我们做实验演示也是不再主服务器端操作只在从服务端进行过滤。)
m’syql从服务器只复制主服务器的magedudb这个库。
mysql>show global variables like ‘binlog-%’;
[root@slave ~]#vim /etc/my.cnf
replicate-do-db = discuzdb
[root@slave ~]#service mysqld restart
在从服务器检查下是否
mysql>show slave status\G;
在主服务端创建数据库。
mysql>create database magedudb;
mysql>create database discuzdb;
在从服务器端看下结果。
mysql>show databases;
#############################################################################
MySQL 5.6引入的GTID(Global Transaction IDs)使得其复制功能的配置、监控及管理变得更加易于实现,且更加健壮。
要在MySQL 5.6中使用复制功能,其服务配置段[mysqld]中于少应该定义如下选项:
1、log-slave-updates、gtid-mode、enforce-gtid-consistency、report-port和report-host:用于启动GTID及满足附属的其它需求;
2、master-info-repository、relay-log-info-repository:启用此两项,可用于实现在崩溃时保证二进制及从服务器安全的功能;
3、sync-master-info:启用之可确保无信息丢失;
4、slave-paralles-workers:设定从服务器的SQL线程数;0表示关闭多线程复制功能;
5、binlog-checksum、master-verify-checksum、slave-sql-verify-checksum:启用复制有关的所有校验功能;
6、binlog-rows-query-log-events:启用之可用于在二进制日志记录事件相关的信息,可降低故障排除的复杂度;
7、log-bin:启用二进制日志,这是保证复制功能的基本前提;
server-id:同一个复制拓扑中的所有服务器的id号必须惟一;
8、binlog-format:二进制日志的格式,有row、statement和mixed几种类型;
注意:当设置隔离级别为READ-COMMITED必须设置二进制日志格式为ROW,现在MySQL官方认为STATEMENT这个已经不再适合继续使用;但mixed类型在默认的事务隔离级别下,可能会导致主从数据不一致;
mysql-5.6的配置演示:
1、配置主从节点的服务配置文件
1.1、配置master节点:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
[mysqld]binlog-format=ROWlog-bin=master-bin.loglog-slave-updates=truegtid-mode=onenforce-gtid-consistency=truemaster-info-repository=TABLErelay-log-info-repository=TABLEsync-master-info=1slave-parallel-workers=2binlog-checksum=CRC32master-verify-checksum=1slave-sql-verify-checksum=1binlog-rows-query-log_events=1server-id=1report-port=3306port=3306datadir=/mydata/datasocket=/tmp/mysql.sockreport-host=master.magedu.com |
1.2、配置slave节点:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
[mysqld]binlog-format=ROWlog-slave-updates=truegtid-mode=onenforce-gtid-consistency=truemaster-info-repository=TABLErelay-log-info-repository=TABLEsync-master-info=1slave-parallel-workers=2binlog-checksum=CRC32master-verify-checksum=1slave-sql-verify-checksum=1binlog-rows-query-log_events=1server-id=11report-port=3306port=3306log-bin=mysql-bin.logdatadir=/mydata/datasocket=/tmp/mysql.sockreport-host=slave.magedu.com |
2、创建复制用户
mysql> GRANT REPLICATION SLAVE ON *.* TO yangyaru@172.16.20.7 IDENTIFIED BY 'yangyaru';
说明:172.16.20.7是从节点服务器;如果想一次性授权更多的节点,可以自行根据需要修改;
3、为备节点提供初始数据集
锁定主表,备份主节点上的数据,将其还原至从节点;如果没有启用GTID,在备份时需要在master上使用show master status命令查看二进制日志文件名称及事件位置,以便后面启动slave节点时使用。
4、启动从节点的复制线程
如果启用了GTID功能,则使用如下命令:
mysql> CHANGE MASTER TO MASTER_HOST='master.yangyaru.com', MASTER_USER='yangyaru', MASTER_PASSWORD='yangyaru', MASTER_AUTO_POSITION=1;
没启用GTID,需要使用如下命令:
slave> CHANGE MASTER TO MASTER_HOST='172.16.100.6',
-> MASTER_USER='yangyaru',
-> MASTER_PASSWORD='yangyaru',
-> MASTER_LOG_FILE='master-bin.000003',
-> MASTER_LOG_POS=1174;
实现半同步复制
1、分别在主从节点上安装相关的插件
master> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
slave> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
2、启用半同步复制
在master上的配置文件中,添加
rpl_semi_sync_master_enabled=ON
在至少一个slave节点的配置文件中添加
rpl_semi_sync_slave_enabled=ON
而后重新启动mysql服务即可生效。
或者,也可以mysql服务上动态启动其相关功能:
master> SET GLOBAL rpl_semi_sync_master_enabled = ON;
slave> SET GLOBAL rpl_semi_sync_slave_enabled = ON;
slave> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
3、确认半同步功能已经启用
master> CREATE DATABASE magedudb;
master> SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
slave> SHOW DATABASES;
拓展:
使用mysql proxy实现mysql主从服务读写分离功能。
这里的系统平台为rhel6.4 32位系统,因此就以mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit.tar.gz为例。
安装配置mysql-proxy:
[root@proxy ~]# tar xf mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit.tar.gz -C /usr/local
[root@proxy ~]# cd /usr/local
[root@proxy ~]# ln -sv mysql-proxy-0.8.3-linux-glibc2.3-x86-32bit mysql-proxy
为mysql-proxy提供SysV服务脚本
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
[root@proxy ~]vim /etc/rc.d/init.d/mysql-proxy#!/bin/bash## mysql-proxy This script starts and stops the mysql-proxy daemon## chkconfig: - 78 30# processname: mysql-proxy# description: mysql-proxy is a proxy daemon for mysql# Source function library.. /etc/rc.d/init.d/functionsprog="/usr/local/mysql-proxy/bin/mysql-proxy"# Source networking configuration.if [ -f /etc/sysconfig/network ]; then. /etc/sysconfig/networkfiif [ -f /etc/sysconfig/mysql-proxy ]; then. /etc/sysconfig/mysql-proxyfi# Check that networking is up.[ ${NETWORKING} = "no" ] && exit 0# Set default mysql-proxy configuration.ADMIN_USER=${ADMIN_USER:-admin}ADMIN_PASSWD=${ADMIN_PASSWD:-""}PROXY_OPTIONS=${PROXY_OPTIONS:="--daemon"}PROXY_USER=${PROXY_USER:-"mysql-proxy"}ADMIN_ADDRESS="${ADMIN_ADDRESS:-0.0.0.0:4040}"PROXY_ADDRESS="${PROXY_ADDRESS:-0.0.0.0:4041}"PROXY_PID=/var/run/mysql-proxy.pid# Source mysql-proxy configuration.if [ -f /etc/sysconfig/mysql-proxy ]; then. /etc/sysconfig/mysql-proxyfiRETVAL=0start() {echo -n $"Starting $prog: "daemon $prog $PROXY_OPTIONS --pid-file=$PROXY_PID --user=$PROXY_USER --admin-username="$ADMIN_USER" --admin-lua-script="$ADMIN_LUA_SCRIPT" --admin-password="$ADMIN_PASSWORD" --admin-address="$ADMIN_ADDRESS" --proxy-address="$PROXY_ADDRESS"RETVAL=$?echoif [ $RETVAL -eq 0 ]; thentouch /var/lock/subsys/mysql-proxyfi}stop() {echo -n $"Stopping $prog: "killproc -p $PROXY_PID -d 3 $progRETVAL=$?echoif [ $RETVAL -eq 0 ]; thenrm -f /var/lock/subsys/mysql-proxyrm -f $PROXY_PIDfi}# See how we were called.case "$1" instart)start;;stop)stop;;restart)stopstart;;condrestart|try-restart)if status -p $PROXY_PIDFILE $prog >&/dev/null; thenstopstartfi;;status)status -p $PROXY_PID $prog;;*)echo "Usage: $0 {start|stop|restart|reload|status|condrestart|try-restart}"RETVAL=1;;esacexit $RETVAL[root@proxy ~]# chmod +x /etc/rc.d/init.d/mysql-proxy[root@proxy ~]# chkconfig --add mysql-proxy |
为服务脚本提供配置文件:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
[root@proxy ~]# vim /etc/sysconfig/mysql-proxy# Options for mysql-proxyADMIN_USER="admin"ADMIN_PASSWORD=""ADMIN_ADDRESS=""PROXY_ADDRESS=""PROXY_USER="mysql-proxy"PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog"其中最后一行,需要按实际场景进行修改,例如:PROXY_OPTIONS="--daemon --log-level=info --log-use-syslog --plugins=proxy --plugins=admin --proxy-backend-addresses=172.16.20.6:3306 --proxy-read-only-backend-addresses=172.16.20.7:3306 --proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua"说明:--proxy-address=host:port ———— 代理服务监听的地址和端口;--admin-address=host:port ———— 管理模块监听的地址和端口;--proxy-lua-script=file_name ———— 完成mysql代理功能的Lua脚本;提供续写分离脚本,这个脚本mysql-proxy-0.8.3提供,所以这里我们只需要复制到对应的读取脚本的位置即可。[root@proxy ~]# vim /usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua--[[ $%BEGINLICENSE%$Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public License aspublished by the Free Software Foundation; version 2 of theLicense.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA02110-1301 USA$%ENDLICENSE%$ --]]----- a flexible statement based load balancer with connection pooling---- * build a connection pool of min_idle_connections for each backend and maintain-- its size-- *----local commands = require("proxy.commands")local tokenizer = require("proxy.tokenizer")local lb = require("proxy.balance")local auto_config = require("proxy.auto-config")--- config---- connection poolif not proxy.global.config.rwsplit thenproxy.global.config.rwsplit = {min_idle_connections = 4,max_idle_connections = 8,is_debug = false}end----- read/write splitting sends all non-transactional SELECTs to the slaves---- is_in_transaction tracks the state of the transactionslocal is_in_transaction = false-- if this was a SELECT SQL_CALC_FOUND_ROWS ... stay on the same connectionslocal is_in_select_calc_found_rows = false----- get a connection to a backend---- as long as we don't have enough connections in the pool, create new connections--function connect_server()local is_debug = proxy.global.config.rwsplit.is_debug-- make sure that we connect to each backend at least ones to-- keep the connections to the servers alive---- on read_query we can switch the backends again to another backendif is_debug thenprint()print("[connect_server] " .. proxy.connection.client.src.name)endlocal rw_ndx = 0-- init all backendsfor i = 1, #proxy.global.backends dolocal s = proxy.global.backends[i]local pool = s.pool -- we don't have a username yet, try to find a connections which is idlinglocal cur_idle = pool.users[""].cur_idle_connectionspool.min_idle_connections = proxy.global.config.rwsplit.min_idle_connectionspool.max_idle_connections = proxy.global.config.rwsplit.max_idle_connectionsif is_debug thenprint(" [".. i .."].connected_clients = " .. s.connected_clients)print(" [".. i .."].pool.cur_idle = " .. cur_idle)print(" [".. i .."].pool.max_idle = " .. pool.max_idle_connections)print(" [".. i .."].pool.min_idle = " .. pool.min_idle_connections)print(" [".. i .."].type = " .. s.type)print(" [".. i .."].state = " .. s.state)end-- prefer connections to the masterif s.type == proxy.BACKEND_TYPE_RW ands.state ~= proxy.BACKEND_STATE_DOWN andcur_idle < pool.min_idle_connections thenproxy.connection.backend_ndx = ibreakelseif s.type == proxy.BACKEND_TYPE_RO ands.state ~= proxy.BACKEND_STATE_DOWN andcur_idle < pool.min_idle_connections thenproxy.connection.backend_ndx = ibreakelseif s.type == proxy.BACKEND_TYPE_RW ands.state ~= proxy.BACKEND_STATE_DOWN andrw_ndx == 0 thenrw_ndx = iendendif proxy.connection.backend_ndx == 0 thenif is_debug thenprint(" [" .. rw_ndx .. "] taking master as default")endproxy.connection.backend_ndx = rw_ndxend-- pick a random backend---- we someone have to skip DOWN backends-- ok, did we got a backend ?if proxy.connection.server thenif is_debug thenprint(" using pooled connection from: " .. proxy.connection.backend_ndx)end-- stay with itreturn proxy.PROXY_IGNORE_RESULTendif is_debug thenprint(" [" .. proxy.connection.backend_ndx .. "] idle-conns below min-idle")end-- open a new connectionend----- put the successfully authed connection into the connection pool---- @param auth the context information for the auth---- auth.packet is the packetfunction read_auth_result( auth )if is_debug thenprint("[read_auth_result] " .. proxy.connection.client.src.name)endif auth.packet:byte() == proxy.MYSQLD_PACKET_OK then-- auth was fine, disconnect from the serverproxy.connection.backend_ndx = 0elseif auth.packet:byte() == proxy.MYSQLD_PACKET_EOF then-- we received either a---- * MYSQLD_PACKET_ERR and the auth failed or-- * MYSQLD_PACKET_EOF which means a OLD PASSWORD (4.0) was sentprint("(read_auth_result) ... not ok yet");elseif auth.packet:byte() == proxy.MYSQLD_PACKET_ERR then-- auth failedendend----- read/write splittingfunction read_query( packet )local is_debug = proxy.global.config.rwsplit.is_debuglocal cmd = commands.parse(packet)local c = proxy.connection.clientlocal r = auto_config.handle(cmd)if r then return r endlocal tokenslocal norm_query-- looks like we have to forward this statement to a backendif is_debug thenprint("[read_query] " .. proxy.connection.client.src.name)print(" current backend = " .. proxy.connection.backend_ndx)print(" client default db = " .. c.default_db)print(" client username = " .. c.username)if cmd.type == proxy.COM_QUERY thenprint(" query = " .. cmd.query)endendif cmd.type == proxy.COM_QUIT then-- don't send COM_QUIT to the backend. We manage the connection-- in all aspects.proxy.response = {type = proxy.MYSQLD_PACKET_OK,}if is_debug thenprint(" (QUIT) current backend = " .. proxy.connection.backend_ndx)endreturn proxy.PROXY_SEND_RESULTend-- COM_BINLOG_DUMP packet can't be balanced---- so we must send it always to the masterif cmd.type == proxy.COM_BINLOG_DUMP then-- if we don't have a backend selected, let's pick the master--if proxy.connection.backend_ndx == 0 thenproxy.connection.backend_ndx = lb.idle_failsafe_rw()endreturnendproxy.queries:append(1, packet, { resultset_is_needed = true })-- read/write splitting---- send all non-transactional SELECTs to a slaveif not is_in_transaction andcmd.type == proxy.COM_QUERY thentokens = tokens or assert(tokenizer.tokenize(cmd.query))local stmt = tokenizer.first_stmt_token(tokens)if stmt.token_name == "TK_SQL_SELECT" thenis_in_select_calc_found_rows = falselocal is_insert_id = falsefor i = 1, #tokens dolocal token = tokens[i]-- SQL_CALC_FOUND_ROWS + FOUND_ROWS() have to be executed-- on the same connection-- print("token: " .. token.token_name)-- print(" val: " .. token.text)if not is_in_select_calc_found_rows and token.token_name == "TK_SQL_SQL_CALC_FOUND_ROWS" thenis_in_select_calc_found_rows = trueelseif not is_insert_id and token.token_name == "TK_LITERAL" thenlocal utext = token.text:upper()if utext == "LAST_INSERT_ID" orutext == "@@INSERT_ID" thenis_insert_id = trueendend-- we found the two special token, we can't find moreif is_insert_id and is_in_select_calc_found_rows thenbreakendend-- if we ask for the last-insert-id we have to ask it on the original-- connectionif not is_insert_id thenlocal backend_ndx = lb.idle_ro()if backend_ndx > 0 thenproxy.connection.backend_ndx = backend_ndxendelseprint(" found a SELECT LAST_INSERT_ID(), staying on the same backend")endendend-- no backend selected yet, pick a masterif proxy.connection.backend_ndx == 0 then-- we don't have a backend right now---- let's pick a master as a good default--proxy.connection.backend_ndx = lb.idle_failsafe_rw()end-- by now we should have a backend---- in case the master is down, we have to close the client connections-- otherwise we can go onif proxy.connection.backend_ndx == 0 thenreturn proxy.PROXY_SEND_QUERYendlocal s = proxy.connection.server-- if client and server db don't match, adjust the server-side---- skip it if we send a INIT_DB anywayif cmd.type ~= proxy.COM_INIT_DB andc.default_db and c.default_db ~= s.default_db thenprint(" server default db: " .. s.default_db)print(" client default db: " .. c.default_db)print(" syncronizing")proxy.queries:prepend(2, string.char(proxy.COM_INIT_DB) .. c.default_db, { resultset_is_needed = true })end-- send to masterif is_debug thenif proxy.connection.backend_ndx > 0 thenlocal b = proxy.global.backends[proxy.connection.backend_ndx]print(" sending to backend : " .. b.dst.name);print(" is_slave : " .. tostring(b.type == proxy.BACKEND_TYPE_RO));print(" server default db: " .. s.default_db)print(" server username : " .. s.username)endprint(" in_trans : " .. tostring(is_in_transaction))print(" in_calc_found : " .. tostring(is_in_select_calc_found_rows))print(" COM_QUERY : " .. tostring(cmd.type == proxy.COM_QUERY))endreturn proxy.PROXY_SEND_QUERYend----- as long as we are in a transaction keep the connection-- otherwise release it so another client can use itfunction read_query_result( inj )local is_debug = proxy.global.config.rwsplit.is_debuglocal res = assert(inj.resultset)local flags = res.flagsif inj.id ~= 1 then-- ignore the result of the USE <default_db>-- the DB might not exist on the backend, what do do ?--if inj.id == 2 then-- the injected INIT_DB failed as the slave doesn't have this DB-- or doesn't have permissions to read from itif res.query_status == proxy.MYSQLD_PACKET_ERR thenproxy.queries:reset()proxy.response = {type = proxy.MYSQLD_PACKET_ERR,errmsg = "can't change DB ".. proxy.connection.client.default_db .." to on slave " .. proxy.global.backends[proxy.connection.backend_ndx].dst.name}return proxy.PROXY_SEND_RESULTendendreturn proxy.PROXY_IGNORE_RESULTendis_in_transaction = flags.in_translocal have_last_insert_id = (res.insert_id and (res.insert_id > 0))if not is_in_transaction andnot is_in_select_calc_found_rows andnot have_last_insert_id then-- release the backendproxy.connection.backend_ndx = 0elseif is_debug thenprint("(read_query_result) staying on the same backend")print(" in_trans : " .. tostring(is_in_transaction))print(" in_calc_found : " .. tostring(is_in_select_calc_found_rows))print(" have_insert_id : " .. tostring(have_last_insert_id))endend----- close the connections if we have enough connections in the pool---- @return nil - close connection-- IGNORE_RESULT - store connection in the poolfunction disconnect_client()local is_debug = proxy.global.config.rwsplit.is_debugif is_debug thenprint("[disconnect_client] " .. proxy.connection.client.src.name)end-- make sure we are disconnection from the connection-- to move the connection into the poolproxy.connection.backend_ndx = 0end |
重启下服务即可。下面的测试我就不写了哈。^_^
本文出自 “杨亚茹yyr” 博客,请务必保留此出处http://yangyaru.blog.51cto.com/6616699/1205001
http://my.oschina.net/wangboa/blog/338231
MySQL5.6 主从复制配置
转自本人独立博客:http://www.wangboak.com/2014/10/mysql5-6-replication-manual/
环境说明:
两台安装在CentOS6.5的MySQL5.6.21服务器:master 和 slave
Master服务器:
IP:192.168.80.51
Port:3316
Slave 服务器:
IP:192.168.80.52
Port:3316
配置步骤:
1、 修改master的my.cnf配置文件,开启记录日志并设置server-id。
2、 修改slave的my.cnf配置文件,开启读取二进制日志并设置server-id。
3、 在slave上启动slave与master的连接。
4、 检查是否配置成功与排错。
1、 修改 master 的my.cnf配置文件,在[mysqld]下添加如下配置:
[mysqld]
log-bin=/usr/local/mysql56/binlog/master-bin
log-bin-index=/usr/local/mysql56/binlog/master-bin.index
server-id=1
说明:
log-bin 配置的是开启二进制日志,并将日志写在配置的路径上。记录的日志将以master-bin.000001 的方式进行记录。
log-bin-index 配置的是二进制日志记录文件的目录。该文件中每一行都是二进制日志文件的路径。
server-id是该MySQL服务器的服务ID,用于区分在主从配置中的其他服务器。
配置成功后,重启mysqld服务。
注意:如果不定义log-bin的文件名,则会以hostname主机名命名,一旦主机名修改,则会因为找不见二进制文件报错。所以最好还是显示指定文件名。
2、 修改 slave 的my.cnf配置文件,在[mysqld]下添加如下配置:
server-id=11
relay-log=/usr/local/mysql56/binlog/slave-relay-bin
relay-log-index=/usr/local/mysql56/binlog/slave-relay-bin.index
server-id和master意义一样,用于区分不同的mysql服务器。
relay-log用以记录收到的中继二进制日志。relay-log-index用以保存收到的日志路径索引。如果不显示指定文件名,则以hostname值命名。
保存后可以重启mysqld服务。
3、 在slave上启动slave与master的连接。
在slave上登录到mysql,在mysql>:下进行操作。
-
1、mysql>stop slave; //停止slave。
-
2、mysql>change master to
->master_host=’192.168.80.51’, //注意有个逗号
->master_port=3316,
->master_user=’root’,
->master_password=’root’;
-
3、mysql>start slave;
4、检查是否配置成功与排错
mysql>show slave status \G;
在打印出来的状态下,查看以下两个参数的值:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
如果这两个参数的值都是yes,则运行正常,可以在master数据库上添加一个数据库或者添加一张表,检查slave数据库上是否存在。
如果 这两个参数有任何一个不是 Yes,则说明存在问题。可以查看slave上的数据库错误日志文件查看错误原因。
常见的错误原因:
1、 server-id 一致。
2、 用户权限不够。需要的权限包括:REPLICATION SLAVE,RELOAD,CREATE USER,SUPER。
GRANT REPLICATION SLAVE,RELOAD,CREATE USER,SUPER ON *.* TO {USER}@{IP_ADDR} WITH GRANT OPTION;
3、 数据库UUID一致,如果mysql安装时是通过批量复制安装的,则有可能数据库的UUID一致,进入数据库的datadir目录,修改auto.cnf。随意修改下uuid中的值,重启mysqld服务即可。
4、 Master数据库端口被防火墙阻挡。
http://www.xuchanggang.cn/archives/536.html
rhel6系统中,mysql 5.6复制新特性下主从复制配置[基于GTID]
1.mysql5.6在复制方面的新特性:
(1).支持多线程复制:事实上是针对每个database开启相应的独立线程,即每个库有一个单独的(sql thread).针对这样的改进,如果我们想实现多线程复制,无疑要对现存的数据库结构进行重新设计,分库分表.对于压力都集中在个别database的,多线程并发复制特性就没有意义.
(2).支持启用GTID,在配置主从复制,传统的方式里,你需要找到binlog和POS点,然后change master to指向.在mysql5.6里,无须再知道binlog和POS点,只需要知道master的IP/端口/账号密码即可,因为同步复制是自动的,mysql通过内部机制GTID自动找点同步.
(3).基于Row复制只保存改变的列,大大节省Disk Space/Newwork resources和Memory usage.
(4).支持把Master 和Slave的相关信息记录在Table中,原来是记录在文件里,记录在表里,增强可用性
(5).支持延迟复制
注:
关于 server_uuid 的解释:服务器身份ID。在第一次启动Mysql时,会自动生成一个server_uuid并写入到数据目录下auto.cnf文件里,官方不建议修改。
- [root@client102 ~]# cat /home/mysql/data/auto.cnf
- [auto]
- server-uuid=14be3ddd-4e92-11e3-8335-000c299c1b31
关于GTID的解释: 全局事务标识符。当开启这个功能时,每次事务提交都会在binlog里生成一个唯一的标示符,它由server_uuid和事务ID组成。首次提交的事务ID为1,第二次为2,第三次为3,依次类推。
2.mysql主从复制的原理图:[此原理没有变化]
3. MySQL5.6开始主从复制有两种方式:基于日志(binlog)[基于日志的搭建,上篇文章已搭建过];基于GTID(全局事务标识符)
本次配置是基于GTID(全局事务标识符),但其也有劣势,实际生产环境中,暂时不推荐使用
基于GTID(全局事务标识符)的局限性:
(1).GTID同步复制是基于事务。所以Myisam表不支持,这可能导致多个GTID分配给同一个事务。(5.6.9版本已经修改,支持修改Myisam表)
(2).gtid_mode和enforce-gtid-consistency=true 必须同时使用,不同时使用,启动Mysql报错。
(3).无法修改myisam表的数据,会提示"Updates to non-transactional tables are forbidden when disable-gtid-unsafe-statements" --> 这个我测试5.6.14,是可以正常修改数据,所以这点劣势待定,大家可以分享测试结果
(4).不支持对临时表操作:CREATE TEMPORARY TABLE、DROP TEMPORARY TABLE --> 这个劣势,5.6.14也可以做,大家可以测试,留言反馈,最近,在5.6.19上测试,是不可以操作,以前5.6.14可能测试有误,这里补充一下。
(5).不支持CREATE TABLE ... SELECT语句。因为该语句会被拆分成create table 和insert两个事务,并且这个两个事务被分配了同一个GTID,这会导致insert被备库忽略掉[这条语句在游戏数据库用的比较多,通常用来将大表分成小表]
4.基于GTID(全局事务标识符)mysql主从复制配置演示:
(1).默认主DB server和从DB server数据库都已经安装好,我的两台DB server都已经安装好(5.6.14版本),都会是双实例[这里我使用3307端口的实例]
注:两台机器的的selinux都是disable(永久关闭selinux,请修改/etc/selinux/config,将SELINUX改为disabled),防火墙可以选择关闭,开启的话也行[不行的话,添加防火墙策略]
主DB server:192.168.1.102:3307
从DB server:192.168.1.100:3307
(2).修改主DB server的配置文件(/etc/my.cnf) [client102为主DB server] --> 主DB sever的配置文件和从DB server文件基本一样,方便搭建HA
- [root@client102 ~]# vim /etc/my.cnf
- # 在[mysqld]里加入如下代码[里面原代码保留,有重复的部分,以这部分为准]
- # 设置server_id,一般建议设置为IP,或者再加一些数字[在以前版本为server-id]
- server_id =1021
- # 二进制日志的格式:有row、statement和mixed三种
- # 注:当设置隔离级别为READ-COMMITED必须设置二进制日志格式为ROW,MySQL官方认为STATEMENT这个已经不再适合继续使用;但mixed类型在默认的事务隔离级别下,可能会导致主从数据不一致; 推荐使用 row
- binlog-format=ROW
- # 这个选项允许应用程序只能对行的镜像数据进行复制,而不在关心行是否已经进行了DML操作.这提高了主从机器的复制吞吐量,减少了二进制日志所占用的磁盘空间、网络资源和内存占用.
- binlog-row-image = minimal
- # 开启二进制日志功能,可以随便取,最好有含义
- log-bin=mysql3307-bin
- # log-slave-updates/gtid-mode/enforce-gtid-consistency/report-port/report-host:用于启动GTID及满足附属的其它需求[其中启动GTID必须同时设置gtid-mode/enforce-gtid-consistency/]
- report-host=192.168.1.102
- report-port=3307
- gtid-mode=on
- enforce-gtid-consistency=true
- log-slave-updates=true
- # master-info-repository/relay-log-info-repository都设置为TABLE,mysql.slave_master_info与 mysql.slave_relay_log_info 中,table都是innodb类型的,支持事务,比文件安全
- # 默认值是FILE, 比如master info就保存在master.info文件中,relay log info保存在relay-log.info文件中,如果服务器意外关闭,正确的relay info 没有来得及更新到 relay-log.info文件,这样会造成数据丢失
- master-info-repository=TABLE
- relay-log-info-repository=TABLE
- # 启用之后,使binlog在每N次binlog写入后与硬盘 同步
- sync-master-info=1
- # 以下是对二进制日志一些设置
- binlog_cache_size = 4M
- max_binlog_size = 1G
- max_binlog_cache_size = 2G
- # 以下这几个参数是启用binlog/relaylog的校验,防止日志出错
- binlog-checksum=CRC32
- slave_allow_batching = 1
- master-verify-checksum=1
- slave-sql-verify-checksum=1
- # 启用这个参数,可用于在二进制日志记录事件相关的信息,可降低故障排除的复杂度
- # 只对row binlog格式有效.启用后,会向binlog中写入更多的调试信息,比如sql语句自身都会被写进去. mysqlbinlog -vv 可以看到.
- binlog-rows-query-log_events=1
- # 开启基于库的多线程复制.默认是0,不开启,最大并发数为1024个线程
- slave-parallel-workers=4
- # 这两个是启用relaylog的自动修复功能,避免由于网络之类的外因造成日志损坏,主从停止.
- relay_log_purge = 1
- relay_log_recovery = 1
(3).启动数据库服务器,并登陆数据库,授予相应的用户用于同步
- # 查看GTID是否开启[enforce_gtid_consistency/gtid_mode 为ON,表示已经开启]
- mysql> show global variables like '%gtid%';
- +--------------------------+-------+
- | Variable_name | Value |
- +--------------------------+-------+
- | enforce_gtid_consistency | ON |
- | gtid_executed | |
- | gtid_mode | ON |
- | gtid_owned | |
- | gtid_purged | |
- +--------------------------+-------+
- # 我这里是多实例mysql,所以启动是这样的,如果大家是单实例的,就直接启动就可以[/etc/init.d/mysqld start]
- [root@client102 ~]# mysqld_multi start 3307
- # 登陆mysql 服务器
- [root@client102 ~]# mysql -uroot -S /usr/local/mysql/mysqld3307.sock -p
- # 授予用户权限用于主从同步
- mysql> grant replication slave on *.* to 'kongzhong'@'192.168.1.100' identified by 'kongzhong';
- # 刷新授权表信息
- mysql> flush privileges;
(4).从DB server配置文件添加代码如下,和主基本一样
- [root@client100 ~]# vim /etc/my.cnf
- # 在[mysqld]下添加如下代码[里面原代码保留,有重复的部分,以这部分为准]
- server_id =1002 # 此处和主DB server不一样,唯一值
- binlog-format=ROW
- binlog-row-image = minimal
- log-bin=mysql33071-bin # 此处和主DB server不一样
- report-host=192.168.1.100 # 此处和主DB server不一样
- report-port=3307
- gtid-mode=on
- enforce-gtid-consistency=true
- master-info-repository=TABLE
- relay-log-info-repository=TABLE
- sync-master-info=1
- slave-parallel-workers=4
- binlog_cache_size = 4M
- max_binlog_size = 1G
- max_binlog_cache_size = 2G
- binlog-checksum=CRC32
- master-verify-checksum=1
- slave-sql-verify-checksum=1
- binlog-rows-query-log_events=1
- log-slave-updates=true
- relay_log_purge = 1
- relay_log_recovery = 1
(5).启动从数据库,添加主DB server指向[关键位置]
- # 启动数据库
- [root@client100 ~]# mysqld_multi start 3307
- # 登陆数据库,添加相关参数(主DBserver的ip/端口/同步用户/密码/****) 这里也需要看是否启动GTID,我这里省略
- [root@client100 ~]# mysql -uroot -S /usr/local/mysql/mysqld3307.sock -p
- mysql> change master to
- -> master_host='192.168.1.102',
- -> master_user='kongzhong',
- -> master_password='kongzhong',
- -> master_port=3307,
- -> master_auto_position = 1,
- -> master_delay=30;
- #/* 下面是一部分注解:
- #/* 指定主DB server的IP地址
- master_host='192.168.1.102'
- #/* 指定用于同步的用户[这个就是我们在主DB server授权的用户]
- master_user='kongzhong'
- #/* 指定用于同步的用户的密码
- master_password='kongzhong'
- #/* 指定主DB server的端口[下面一个例子,可以重点看这个]
- master_port=3306
- #/* 自动寻找position号
- master_auto_position = 1
- #/* 延时30秒执行复制,relay日志会及时同步到slave机,只是日志的中的事件会根据事件的时间戳延时30秒执行.此参数具有实用性
- master_delay=30
(6).开启同步,验证同步状态
- # 开启主从同步[以前的版本slave start,新版本已不支持此写法]
- mysql> start slave;
- # 查看主从同步状态
- mysql> show slave status\G;
- # 主要看以下两个参数:[这两个参数如果是yes就表示主从同步正常]
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
- # 在新特性下,我们还可以看到如下几个参数
- Retrieved_Gtid_Set: 1f14026d-53e7-11e3-a5f9-000c299c1b31:4
- Executed_Gtid_Set: 1f14026d-53e7-11e3-a5f9-000c299c1b31:1-4
- #/* Retrieved_Gtid_Set项:记录了relay日志从Master获取了binlog日志的位置
- #/* Executed_Gtid_Set项:记录本机执行的binlog日志位置(如果是从机,包括Master的binlog日志位置和slave本身的binlog日志位置)
- # 此时,我们可以在主DB sever 查看一下,现在gtid标识是否和从DB server 一致:
- # 登陆到主DB server执行如下命令[查看gtid_executed和从DB server上的Executed_Gtid_Set是否一致,一致表示同步完成]
- mysql> show global variables like '%GTID%';
- +--------------------------+------------------------------------------+
- | Variable_name | Value |
- +--------------------------+------------------------------------------+
- | enforce_gtid_consistency | ON |
- | gtid_executed | 1f14026d-53e7-11e3-a5f9-000c299c1b31:1-4 |
- | gtid_mode | ON |
- | gtid_owned | |
- | gtid_purged | |
- +--------------------------+------------------------------------------+
- # 此时可以大家可以在主上执行操作,看是否能同步到从上,并时刻对比上面几个参数
- 上面的搭建,省了数据一致部分[我这里是新装的实例,所以数据是一致的],各位如果不是新环境,可以备份,还原数据
- 备份使用如下语句, --triggers --routines --events 这几个参数没有认真揣摩其含义,如有对其了解的,可留言告知
- [root@client102 ~]# mysqldump -uroot -p -S /usr/local/mysql/mysqld3307.sock --all-databases --triggers --routines --events >/tmp/mysql3307.sql
- # 还原语句还和原理一样
- [root@client100 ~]# mysql -uroot -p -S /usr/local/mysql/mysqld3307.sock < /tmp/mysql3307.sql
mysql 5.6新特性下的主从,这里研究的还不够深入,有时间还需进一步研究。
各位如果发现文章中的错误,请及时指正,交流,谢谢!
==============================================================
http://7056824.blog.51cto.com/69854/400642/
我们一般使用 MySQL 的时候,如果数据量不大,只使用一台 MySQL 服务器,备份的时候使用 mysqldump 工具就可以了,但是随着业务不断发展,问题出现了:数据量直线上升,单独一台数据库服务器开始出现性能的瓶颈,数据访问越来越慢。备份也变得困难了,因为 mysqldump 是导出一份文本文件,而数据量特别大的时候,这样的备份往往需要很长时间。
如果你遇到了类似上面的问题,你就可以使用建立 MySQL 主从服务器的复制方式来解决,MySQL 的复制有以下几个优势:主服务器/从服务器设置增加了健壮性,主服务器出现问题时,你可以切换到从服务器继续提供服务。通过在从服务器上执行查询操作来降低客户查询的负荷,可以得到更好的客户响应时间,但是不要同时在主从服务器上进行更新,这样可能引起冲突。使用复制的另一个好处是可以使用一个从服务器执行备份,而不会干扰主服务器。在备份过程中主服务器可以继续处理更新。
MySQL 复制的原理:
MySQL使用3个线程来执行复制功能,其中1个在主服务器上,另两个在从服务器上。当发出START SLAVE时,从服务器创建一个I/O线程,以连接主服务器并让主服务器发送二进制日志。主服务器创建一个线程将二进制日志中的内容发送到从服务器。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷贝到从服务器数据目录中的本地文件中,即中继日志。第3个线程是SQL线程,从服务器使用此线程读取中继日志并执行日志中包含的更新。SHOW PROCESSLIST语句可以查询在主服务器上和从服务器上发生的关于复制的信息。
默认中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序列号。用连续序列号来创建连续中继日志文件,从000001开始。从服务器跟踪中继日志索引文件来识别目前正使用的中继日志。默认中继日志索引文件名为host_name-relay-bin.index。在默认情况,这些文件在从服务器的数据目录中被创建。中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。当SQL线程执行完中继日志中的所有事件后,中继日志将会被自动删除。
设置 MySQL 主从复制:
注意:MySQL 主从服务器最好使用相同的软件版本,以避免不不可预期的故障。
软件环境:系统 rhel4u8,MySQL-5.1.44,
主服务器ip:192.168.0.1 hostname:node1
从服务器ip:192.168.0.2 hostname:node2
设置主服务器
1、编辑 /etc/hosts (此步非必须)
增加以下内容:
| 192.168.0.2 node2 |
2、在主服务器上建立一个为从服务器进行复制使用的用户。该账户必须授予 REPLICATION SLAVE 权限,由于仅仅是进行复制使用所以不需要再授予任何其它权限。
| mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%'192.168.0.2' IDENTIFIED BY 'slavepasswd'; mysql> FLUSH PRIVILEGES; |
3、编辑主服务器的配置文件:/etc/my.cnf的[ mysqld ] 部分:
server-id = 本机数据库 ID 标示,该部分还应有一个server-id=Master_id选项,其中master_id必须为1到232之间的一个正整数值
log-bin = 二进制日志的位置和名称
binlog-do-db = 需要备份的数据库名,如果备份多个数据库,重复设置这个选项即可
binlog-ignore-db = 不需要备份的数据库苦命,如果备份多个数据库,重复设置这个选项即可
我的主服务器设置为:
| server-id = 1 log-bin=/usr/local/mysql/data/mysql-bin.000001 binlog-do-db = wapnews binlog-ignore-db = mysql binlog-ignore-db = test binlog-ignore-db = information_schema |
4、主服务器执行FLUSH TABLES WITH READ LOCK语句清空所有表和块写入语句:
| mysql> FLUSH TABLES WITH READ LOCK; |
5、保持mysql客户端程序不要退出。开启另一个终端对主服务器数据目录做备份。
| [root@node1 ~]# cd /usr/local/mysql/data [root@node1 ~]# tar -zcvf /tmp/mysql-wapnews.tar.gz ./wapnews |
把备份完毕的数据库备份复制到从服务器上。
6、当FLUSH TABLES WITH READ LOCK所置读锁定有效时(即mysql客户端程序不退出),读取主服务器上当前的二进制日志名和偏移量值:
|
mysql > SHOW MASTER STATUS; +-----------------------------+---------------+-------------------------+--------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------------------+---------------+-------------------------+--------------------------------------------+ | mysql-bin.000001 | 73 | wapnews | test,mysql,information_schema | +------------------------------+---------------+-------------------------+--------------------------------------------+ |
File列显示日志名,而Position显示偏移量。在该例子中,二进制日志值为mysql-bin.000001,偏移量为73。记录该值。以后设置从服务器时需要使用这些值。它们表示复制坐标,从服务器应从该点开始从主服务器上进行新的更新。
取得快照并记录日志名和偏移量后,回到前一中端重新启用写活动:
| mysql> UNLOCK TABLES; |
设置从服务器:
1、编辑/etc/hosts (此步非必要)
增加以下内容:
| 192.168.0.1 node1 |
2、停止从服务器上的mysqld服务并编辑从服务器的配置文件:/etc/my.cnf 的[ mysqld ] 部分:
server-id = 本机数据库 ID 标示,该部分还应有一个server-id=Master_id选项,其中master_id必须为1到232之间的一个正整数值
| [root@node2 ~]# service mysqld stop |
我的从服务器配置
| server-id=2 |
3、将主服务器数据库备份恢复到从服务器的数据目录中。确保对这些文件和目录的权限正确。服务器 MySQL运行的用户必须能够读写文件,如同在主服务器上一样。
| [root@node2 ~]# cd /usr/local/mysql/data [root@node2 ~]# tar -zxvf mysql-wapnews.tar.gz [root@node2 ~]# chown -R mysql:mysql /usr/local/mysql/data/wapnews |
4、启动从服务器。在从服务器上执行下面的语句,用你的系统的实际值替换选项值:
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name',
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
我的从服务器设置:
| mysql> change master to -> master_host='192.168.0.1', -> master_user='replication', -> master_password='slavepass', -> master_port=3306 -> master_log_file='mysql-bin.000001', -> master_log_pos=73, -> master_connect_retry=30; |
5、启动从服务器线程:
| mysql> START SLAVE; |
执行这些程序后,从服务器应连接主服务器,并补充自从快照以来发生的任何更新。
检查主从复制是否正常运行
在从服务器上运行 show processlist 命令,检查是否启动两个复制进程。
| mysql> show processlist \G; *************************** 1. row *************************** Id: 44 User: system user Host: db: NULL Command: Connect Time: 490 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 45 User: system user Host: db: NULL Command: Connect Time: 390 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL 3 rows in set (0.00 sec) |
在从服务器上运行 show slave status 命令,检查复制进程是否正确。
| mysql> show slave status \G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.0.1 Master_User: replication Master_Port: 3306 Connect_Retry: 30 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 73 Relay_Log_File: localhost-relay-bin.000002 Relay_Log_Pos: 251 Relay_Master_Log_File: mysql-bin.000001 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: 106 Relay_Log_Space: 410 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: 1 row in set (0.00 sec) |
上面出现: Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 表示复制正常,如果有一个显示是NO,请检查以上的主从设置步骤是否正确。如果出现复制错误,从服务器的错误日志(HOSTNAME.err)中也会出现错误消息。
注意:从服务器复制时,会在其数据目录中发现文件master.info和HOSTNAME-relay-log.info。状态文件保存在硬盘上,从服务器关闭时不会丢失。下次从服务器启动时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。不要移除或编辑这些文件,除非你确切知你正在做什么并完全理解其意义。即使这样,最好是使用CHANGE MASTER TO语句。
本文出自 “小苗” 博客,请务必保留此出处http://7056824.blog.51cto.com/69854/400642
http://blog.csdn.net/hguisu/article/details/7325124
温习《高性能MySQL》的复制篇.
1 复制概述
Mysql内建的复制功能是构建大型,高性能应用程序的基础。将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的。复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
请注意当你进行复制时,所有对复制中的表的更新必须在主服务器上进行。否则,你必须要小心,以避免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。
1.1 mysql支持的复制类型:
(1):基于语句的复制: 在主服务器上执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。
一旦发现没法精确复制时, 会自动选着基于行的复制。
(2):基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.0开始支持
(3):混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制。
1.2 . 复制解决的问题
MySQL复制技术有以下一些特点:
(1) 数据分布 (Data distribution )
(2) 负载平衡(load balancing)
(3) 备份(Backups)
(4) 高可用性和容错行 High availability and failover
1.3 复制如何工作
整体上来说,复制有3个步骤:
(1) master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);
(3) slave重做中继日志中的事件,将改变反映它自己的数据。
下图描述了复制的过程:

该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。
下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。
此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。
2 .复制配置
有两台MySQL数据库服务器Master和slave,Master为主服务器,slave为从服务器,初始状态时,Master和slave中的数据信息相同,当Master中的数据发生变化时,slave也跟着发生相应的变化,使得master和slave的数据信息同步,达到备份的目的。
要点:
负责在主、从服务器传输各种修改动作的媒介是主服务器的二进制变更日志,这个日志记载着需要传输给从服务器的各种修改动作。因此,主服务器必须激活二进制日志功能。从服务器必须具备足以让它连接主服务器并请求主服务器把二进制变更日志传输给它的权限。
环境:
Master和slave的MySQL数据库版本同为5.0.18
操作系统:unbuntu 11.10
IP地址:10.100.0.100
2.1、创建复制帐号
1、在Master的数据库中建立一个备份帐户:每个slave使用标准的MySQL用户名和密码连接master。进行复制操作的用户会授予REPLICATION SLAVE权限。用户名的密码都会存储在文本文件master.info中
命令如下:
mysql > GRANT REPLICATION SLAVE,RELOAD,SUPER ON *.*
TO backup@’10.100.0.200’
IDENTIFIED BY ‘1234’;
建立一个帐户backup,并且只能允许从10.100.0.200这个地址上来登陆,密码是1234。
(如果因为mysql版本新旧密码算法不同,可以设置:set password for 'backup'@'10.100.0.200'=old_password('1234'))
2.2、拷贝数据
(假如是你完全新安装mysql主从服务器,这个一步就不需要。因为新安装的master和slave有相同的数据)
关停Master服务器,将Master中的数据拷贝到B服务器中,使得Master和slave中的数据同步,并且确保在全部设置操作结束前,禁止在Master和slave服务器中进行写操作,使得两数据库中的数据一定要相同!
2.3、配置master
接下来对master进行配置,包括打开二进制日志,指定唯一的servr ID。例如,在配置文件加入如下值:
server-id=1
log-bin=mysql-bin
server-id:为主服务器A的ID值
log-bin:二进制变更日值
重启master,运行SHOW MASTER STATUS,输出如下:
2.4、配置slave
log_bin = mysql-bin
server_id = 2
relay_log = mysql-relay-bin
log_slave_updates = 1
read_only = 1
server_id是必须的,而且唯一。slave没有必要开启二进制日志,但是在一些情况下,必须设置,例如,如果slave为其它slave的master,必须设置bin_log。在这里,我们开启了二进制日志,而且显示的命名(默认名称为hostname,但是,如果hostname改变则会出现问题)。
relay_log配置中继日志,log_slave_updates表示slave将复制事件写进自己的二进制日志(后面会看到它的用处)。
有些人开启了slave的二进制日志,却没有设置log_slave_updates,然后查看slave的数据是否改变,这是一种错误的配置。所以,尽量使用read_only,它防止改变数据(除了特殊的线程)。但是,read_only并是很实用,特别是那些需要在slave上创建表的应用。
2.5、启动slave
接下来就是让slave连接master,并开始重做master二进制日志中的事件。你不应该用配置文件进行该操作,而应该使用CHANGE MASTER TO语句,该语句可以完全取代对配置文件的修改,而且它可以为slave指定不同的master,而不需要停止服务器。如下:mysql> CHANGE MASTER TO MASTER_HOST='server1',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='p4ssword',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;
MASTER_LOG_POS的值为0,因为它是日志的开始位置。
你可以用SHOW SLAVE STATUS语句查看slave的设置是否正确:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
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
...omitted...
Seconds_Behind_Master: NULL
Slave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No
表明slave还没有开始复制过程。日志的位置为4而不是0,这是因为0只是日志文件的开始位置,并不是日志位置。实际上,MySQL知道的第一个事件的位置是4。
为了开始复制,你可以运行:
mysql> START SLAVE;
运行SHOW SLAVE STATUS查看输出结果:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
Slave_IO_Running=Yes
Slave_SQL_Running=Yes
slave的I/O和SQL线程都已经开始运行,而且Seconds_Behind_Master不再是NULL。日志的位置增加了,意味着一些事件被获取并执行了。如果你在master上进行修改,你可以在slave上看到各种日志文件的位置的变化,同样,你也可以看到数据库中数据的变化。
你可查看master和slave上线程的状态。在master上,你可以看到slave的I/O线程创建的连接:
|
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: root Host: localhost:2096 db: test Command: Query Time: 0 State: NULL Info: show processlist *************************** 2. row *************************** Id: 2 User: repl Host: localhost:2144 db: NULL Command: Binlog Dump Time: 1838 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL 2 rows in set (0.00 sec) |
行2为处理slave的I/O线程的连接。
在slave服务器上运行该语句:
|
mysql> show processlist \G *************************** 1. row *************************** Id: 1 User: system user Host: db: NULL Command: Connect Time: 2291 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 2 User: system user Host: db: NULL Command: Connect Time: 1852 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL *************************** 3. row *************************** Id: 5 User: root Host: localhost:2152 db: test Command: Query Time: 0 State: NULL Info: show processlist 3 rows in set (0.00 sec) |
行1为I/O线程状态,行2为SQL线程状态。
2.5、添加新slave服务器
假如master已经运行很久了,想对新安装的slave进行数据同步,甚至它没有master的数据。
此时,有几种方法可以使slave从另一个服务开始,例如,从master拷贝数据,从另一个slave克隆,从最近的备份开始一个slave。Slave与master同步时,需要三样东西:
(1)master的某个时刻的数据快照;
(2)master当前的日志文件、以及生成快照时的字节偏移。这两个值可以叫做日志文件坐标(log file coordinate),因为它们确定了一个二进制日志的位置,你可以用SHOW MASTER STATUS命令找到日志文件的坐标;
(3)master的二进制日志文件。
可以通过以下几中方法来克隆一个slave:
(1) 冷拷贝(cold copy)
停止master,将master的文件拷贝到slave;然后重启master。缺点很明显。
(2) 热拷贝(warm copy)
如果你仅使用MyISAM表,你可以使用mysqlhotcopy拷贝,即使服务器正在运行。
(3) 使用mysqldump
使用mysqldump来得到一个数据快照可分为以下几步:
<1>锁表:如果你还没有锁表,你应该对表加锁,防止其它连接修改数据库,否则,你得到的数据可以是不一致的。如下:
mysql> FLUSH TABLES WITH READ LOCK;
<2>在另一个连接用mysqldump创建一个你想进行复制的数据库的转储:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
<3>对表释放锁。
mysql> UNLOCK TABLES;
3、深入了解复制
3.1、基于语句的复制(Statement-Based Replication)
这种方式的优点就是实现简单。此外,基于语句的复制的二进制日志可以很好的进行压缩,而且日志的数据量也较小,占用带宽少——例如,一个更新GB的数据的查询仅需要几十个字节的二进制日志。而mysqlbinlog对于基于语句的日志处理十分方便。
但是,基于语句的复制并不是像它看起来那么简单,因为一些查询语句依赖于master的特定条件,例如,master与slave可能有不同的时间。所以,MySQL的二进制日志的格式不仅仅是查询语句,还包括一些元数据信息,例如,当前的时间戳。即使如此,还是有一些语句,比如,CURRENT USER函数,不能正确的进行复制。此外,存储过程和触发器也是一个问题。
另外一个问题就是基于语句的复制必须是串行化的。这要求大量特殊的代码,配置,例如InnoDB的next-key锁等。并不是所有的存储引擎都支持基于语句的复制。
3.2、基于记录的复制(Row-Based Replication)
对于一些语句,基于记录的复制能够更有效的工作,如:
mysql> INSERT INTO summary_table(col1, col2, sum_col3)
-> SELECT col1, col2, sum(col3)
-> FROM enormous_table
-> GROUP BY col1, col2;
假设,只有三种唯一的col1和col2的组合,但是,该查询会扫描原表的许多行,却仅返回三条记录。此时,基于记录的复制效率更高。
另一方面,下面的语句,基于语句的复制更有效:
mysql> UPDATE enormous_table SET col1 = 0;
此时使用基于记录的复制代价会非常高。由于两种方式不能对所有情况都能很好的处理,所以,MySQL 5.1支持在基于语句的复制和基于记录的复制之前动态交换。你可以通过设置session变量binlog_format来进行控制。
3.3、复制相关的文件
(1)mysql-bin.index
(2)mysql-relay-bin.index
.\mysql-02-relay-bin.000017
.\mysql-02-relay-bin.000018
(3)master.info
I/O线程更新master.info文件,内容如下(我的机器上):
|
.\mysql-02-relay-bin.000019 254 mysql-01-bin.000010 286 0 52813 |
(4)relay-log.info
3.4、发送复制事件到其它slave
3.5、复制过滤(Replication Filters)
4、复制的常用拓扑结构
(1) 每个slave只能有一个master;
(2) 每个slave只能有一个唯一的服务器ID;
(3) 每个master可以有很多slave;
(4) 如果你设置log_slave_updates,slave可以是其它slave的master,从而扩散master的更新。
MySQL不支持多主服务器复制(Multimaster Replication)——即一个slave可以有多个master。但是,通过一些简单的组合,我们却可以建立灵活而强大的复制体系结构。
4.1、单一master和多slave
在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只要Master和Slave的压力不是太大(尤其是Slave端压力)的话,异步复制的延时一般都很少很少。尤其是自从Slave端的复制方式改成两个线程处理之后,更是减小了Slave端的延时问题。而带来的效益是,对于数据实时性要求不是特别Critical的应用,只需要通过廉价的pcserver来扩展Slave的数量,将读压力分散到多台Slave的机器上面,即可通过分散单台数据库服务器的读压力来解决数据库端的读性能瓶颈,毕竟在大多数数据库应用系统中的读压力还是要比写压力大很多。这在很大程度上解决了目前很多中小型网站的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。
如果写操作较少,而读操作很时,可以采取这种结构。你可以将读操作分布到其它的slave,从而减小master的压力。但是,当slave增加到一定数量时,slave对master的负载以及网络带宽都会成为一个严重的问题。
这种结构虽然简单,但是,它却非常灵活,足够满足大多数应用需求。一些建议:
(1) 不同的slave扮演不同的作用(例如使用不同的索引,或者不同的存储引擎);
(2) 用一个slave作为备用master,只进行复制;
(3) 用一个远程的slave,用于灾难恢复;
大家应该都比较清楚,从一个Master节点可以复制出多个Slave节点,可能有人会想,那一个Slave节点是否可以从多个Master节点上面进行复制呢?至少在目前来看,MySQL是做不到的,以后是否会支持就不清楚了。
MySQL不支持一个Slave节点从多个Master节点来进行复制的架构,主要是为了避免冲突的问题,防止多个数据源之间的数据出现冲突,而造成最后数据的不一致性。不过听说已经有人开发了相关的patch,让MySQL支持一个Slave节点从多个Master结点作为数据源来进行复制,这也正是MySQL开源的性质所带来的好处。
4.2、主动模式的Master-Master(Master-Master in Active-Active Mode)
可能有些读者朋友会有一个担心,这样搭建复制环境之后,难道不会造成两台MySQL之间的循环复制么?实际上MySQL自己早就想到了这一点,所以在MySQL的BinaryLog中记录了当前MySQL的server-id,而且这个参数也是我们搭建MySQLReplication的时候必须明确指定,而且Master和Slave的server-id参数值比需要不一致才能使MySQLReplication搭建成功。一旦有了server-id的值之后,MySQL就很容易判断某个变更是从哪一个MySQLServer最初产生的,所以就很容易避免出现循环复制的情况。而且,如果我们不打开记录Slave的BinaryLog的选项(--log-slave-update)的时候,MySQL根本就不会记录复制过程中的变更到BinaryLog中,就更不用担心可能会出现循环复制的情形了。
主动的Master-Master复制有一些特殊的用处。例如,地理上分布的两个部分都需要自己的可写的数据副本。这种结构最大的问题就是更新冲突。假设一个表只有一行(一列)的数据,其值为1,如果两个服务器分别同时执行如下语句:
在第一个服务器上执行:
mysql> UPDATE tbl SET col=col + 1;
在第二个服务器上执行:
mysql> UPDATE tbl SET col=col * 2;
那么结果是多少呢?一台服务器是4,另一个服务器是3,但是,这并不会产生错误。
实际上,MySQL并不支持其它一些DBMS支持的多主服务器复制(Multimaster Replication),这是MySQL的复制功能很大的一个限制(多主服务器的难点在于解决更新冲突),但是,如果你实在有这种需求,你可以采用MySQL Cluster,以及将Cluster和Replication结合起来,可以建立强大的高性能的数据库平台。但是,可以通过其它一些方式来模拟这种多主服务器的复制。
4.3、主动-被动模式的Master-Master(Master-Master in Active-Passive Mode)
在有些应用场景中,可能读写压力差别比较大,读压力特别的大,一个Master可能需要上10台甚至更多的Slave才能够支撑注读的压力。这时候,Master就会比较吃力了,因为仅仅连上来的SlaveIO线程就比较多了,这样写的压力稍微大一点的时候,Master端因为复制就会消耗较多的资源,很容易造成复制的延时。
遇到这种情况如何解决呢?这时候我们就可以利用MySQL可以在Slave端记录复制所产生变更的BinaryLog信息的功能,也就是打开—log-slave-update选项。然后,通过二级(或者是更多级别)复制来减少Master端因为复制所带来的压力。也就是说,我们首先通过少数几台MySQL从Master来进行复制,这几台机器我们姑且称之为第一级Slave集群,然后其他的Slave再从第一级Slave集群来进行复制。从第一级Slave进行复制的Slave,我称之为第二级Slave集群。如果有需要,我们可以继续往下增加更多层次的复制。这样,我们很容易就控制了每一台MySQL上面所附属Slave的数量。这种架构我称之为Master-Slaves-Slaves架构
这种多层级联复制的架构,很容易就解决了Master端因为附属Slave太多而成为瓶颈的风险。下图展示了多层级联复制的Replication架构。

当然,如果条件允许,我更倾向于建议大家通过拆分成多个Replication集群来解决
上述瓶颈问题。毕竟Slave并没有减少写的量,所有Slave实际上仍然还是应用了所有的数据变更操作,没有减少任何写IO。相反,Slave越多,整个集群的写IO总量也就会越多,我们没有非常明显的感觉,仅仅只是因为分散到了多台机器上面,所以不是很容易表现出来。
此外,增加复制的级联层次,同一个变更传到最底层的Slave所需要经过的MySQL也会更多,同样可能造成延时较长的风险。
而如果我们通过分拆集群的方式来解决的话,可能就会要好很多了,当然,分拆集群也需要更复杂的技术和更复杂的应用系统架构。
4.5、带从服务器的Master-Master结构(Master-Master with Slaves)
级联复制在一定程度上面确实解决了Master因为所附属的Slave过多而成为瓶颈的问题,但是他并不能解决人工维护和出现异常需要切换后可能存在重新搭建Replication的问题。这样就很自然的引申出了DualMaster与级联复制结合的Replication架构,我称之为Master-Master-Slaves架构
和Master-Slaves-Slaves架构相比,区别仅仅只是将第一级Slave集群换成了一台单独的Master,作为备用Master,然后再从这个备用的Master进行复制到一个Slave集群。
这种DualMaster与级联复制结合的架构,最大的好处就是既可以避免主Master的写入操作不会受到Slave集群的复制所带来的影响,同时主Master需要切换的时候也基本上不会出现重搭Replication的情况。但是,这个架构也有一个弊端,那就是备用的Master有可能成为瓶颈,因为如果后面的Slave集群比较大的话,备用Master可能会因为过多的SlaveIO线程请求而成为瓶颈。当然,该备用Master不提供任何的读服务的时候,瓶颈出现的可能性并不是特别高,如果出现瓶颈,也可以在备用Master后面再次进行级联复制,架设多层Slave集群。当然,级联复制的级别越多,Slave集群可能出现的数据延时也会更为明显,所以考虑使用多层级联复制之前,也需要评估数据延时对应用系统的影响。
参考:《高性能 MySQL》
http://blog.csdn.net/mycwq/article/details/17136001
MYSQL主从同步是目前使用比较广泛的数据库架构,技术比较成熟,配置也不复杂,特别是对于负载比较大的网站,主从同步能够有效缓解数据库读写的压力。
MySQL主从同步的机制
MYSQL主从同步是在MySQL主从复制(Master-Slave Replication)基础上实现的,通过设置在Master MySQL上的binlog(使其处于打开状态),Slave MySQL上通过一个I/O线程从Master MySQL上读取binlog,然后传输到Slave MySQL的中继日志中,然后Slave MySQL的SQL线程从中继日志中读取中继日志,然后应用到Slave MySQL的数据库中。这样实现了主从数据同步功能。
MySQL主从同步的作用
1、可以作为一种备份机制,相当于热备份
2、可以用来做读写分离,均衡数据库负载
MySQL主从同步的步骤
一、准备操作
1、主从数据库版本一致,建议版本5.5以上
2、主从数据库数据一致
二、主数据库master修改
1、修改MySQL配置:
- # 日志文件名
- log-bin = mysql-bin
- # 主数据库端ID号
- server-id = 1
2、重启mysql,创建用于同步的账户:
- # 创建slave帐号slave_account,密码123456
- mysql>grant replication slave on *.* to 'slave_account'@'%' identified by '123456';
- # 更新数据库权限
- mysql>flush privileges;
3、查询master的状态
- mysql> show master status;
- +------------------+----------+--------------+------------------+
- | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
- +------------------+----------+--------------+------------------+
- | mysql-bin.000009 | 196 | | |
- +------------------+----------+--------------+------------------+
- 1 row in set
注:执行完这个步骤后不要再操作主数据库了,防止主数据库状态值变化
三、从数据库slave修改
1、修改MySQL配置:
- # 从数据库端ID号
- server-id =2
2、执行同步命令
- # 执行同步命令,设置主数据库ip,同步帐号密码,同步位置
- mysql>change master to master_host='192.168.1.2',master_user='slave_account',master_password='123456',master_log_file='mysql-bin.000009',master_log_pos=196;
- # 开启同步功能
- mysql>start slave;
3、检查从数据库状态:
- mysql> show slave status\G;
- *************************** 1. row ***************************
- Slave_IO_State: Waiting for master to send event
- Master_Host: 192.168.1.2
- Master_User: slave_account
- Master_Port: 3306
- Connect_Retry: 60
- Master_Log_File: mysql-bin.000009
- Read_Master_Log_Pos: 196
- Relay_Log_File: vicky-relay-bin.000002
- Relay_Log_Pos: 253
- Relay_Master_Log_File: mysql-bin.000009
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
- Replicate_Do_DB:
- Replicate_Ignore_DB:
- ...
注:Slave_IO_Running及Slave_SQL_Running进程必须正常运行,即YES状态,否则说明同步失败。
到这里,主从数据库设置工作已经完成,自己可以新建数据库和表,插入和修改数据,测试一下是否成功
四、其他可能用到的相关参数
1、master端:
- # 不同步哪些数据库
- binlog-ignore-db = mysql
- binlog-ignore-db = test
- binlog-ignore-db = information_schema
- # 只同步哪些数据库,除此之外,其他不同步
- binlog-do-db = game
- # 日志保留时间
- expire_logs_days = 10
- # 控制binlog的写入频率。每执行多少次事务写入一次
- # 这个参数性能消耗很大,但可减小MySQL崩溃造成的损失
- sync_binlog = 5
- # 日志格式,建议mixed
- # statement 保存SQL语句
- # row 保存影响记录数据
- # mixed 前面两种的结合
- binlog_format = mixed
2、slave端:
- # 停止主从同步
- mysql> stop slave;
- # 连接断开时,重新连接超时时间
- mysql> change master to master_connect_retry=50;
- # 开启主从同步
- mysql> start slave;
以上连接超时设置,类似方式可用于设置主数据库ip,同步帐号密码,同步位置
http://blog.sina.com.cn/s/blog_821512b50101hxod.html
一 什么叫MySQL主从复制
MySQL主从复制是其最重要的功能之一。主从复制是指一台服务器充当主数据库服务器,另一台或多台服务器充当从数据库服务器,主服务器中的数据自动复制到从服务器之中。对于多级复制,数据库服务器即可充当主机,也可充当从机。MySQL主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新。
二 MySQL主从复制类型
1、基于语句的复制:主服务器上面执行的语句在从服务器上面再执行一遍,在MySQL-3.23版本以后支持。
存在的问题:时间上可能不完全同步造成偏差,执行语句的用户也可能是不同一个用户。
2、基于行的复制:把主服务器上面改编后的内容直接复制过去,而不关心到底改变该内容是由哪条语句引发的,在MySQL-5.0版本以后引入。
存在的问题:比如一个工资表中有一万个用户,我们把每个用户的工资+1000,那么基于行的复制则要复制一万行的内容,由此造成的开销比较大,而基于语句的复制仅仅一条语句就可以了。
3、混合类型的复制:MySQL默认使用基于语句的复制,当基于语句的复制会引发问题的时候就会使用基于行的复制,MySQL会自动进行选择。
在MySQL主从复制架构中,读操作可以在所有的服务器上面进行,而写操作只能在主服务器上面进行。主从复制架构虽然给读操作提供了扩展,可如果写操作也比较多的话(多台从服务器还要从主服务器上面同步数据),单主模型的复制中主服务器势必会成为性能瓶颈。
三 MySQL主从复制工作原理
如下图所示:
主服务器上面的任何修改都会保存在二进制日志Binary log里面,从服务器上面启动一个I/O thread(实际上就是一个主服务器的客户端进程),连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log里面。从服务器上面开启一个SQL thread定时检查Realy log,如果发现有更改立即把更改的内容在本机上面执行一遍。
如果一主多从的话,这时主库既要负责写又要负责为几个从库提供二进制日志。此时可以稍做调整,将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从。或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。工作原理图如下:
实际上在老版本的MySQL主从复制中Slave端并不是两个进程完成的,而是由一个进程完成。但是后来发现这样做存在较大的风险和性能问题,主要如下:
首先,一个进程会使复制bin-log日志和解析日志并在自身执行的过程成为一个串行的过程,性能受到了一定的限制,异步复制的延迟也会比较长。
另外,Slave端从Master端获取bin-log过来之后,需要接着解析日志内容,然后在自身执行。在这个过程中,Master端可能又产生了大量变化并新增了大量的日志。如果在这个阶段Master端的存储出现了无法修复的错误,那么在这个阶段所产生的所有变更都将永远无法找回。如果在Slave端的压力比较大的时候,这个过程的时间可能会比较长。
为了提高复制的性能并解决存在的风险,后面版本的MySQL将Slave端的复制动作交由两个进程来完成。提出这个改进方案的人是Yahoo!的一位工程师“Jeremy Zawodny”。这样既解决了性能问题,又缩短了异步的延时时间,同时也减少了可能存在的数据丢失量。
当然,即使是换成了现在这样两个线程处理以后,同样也还是存在slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。如果要完全避免这些问题,就只能用MySQL的cluster来解决了。不过MySQL的cluster是内存数据库的解决方案,需要将所有数据都load到内存中,这样就对内存的要求就非常大了,对于一般的应用来说可实施性不是太大。
还有一点要提的是MySQL的复制过滤(Replication Filters),复制过滤可以让你只复制服务器中的一部分数据。有两种复制过滤:在Master上过滤二进制日志中的事件;在Slave上过滤中继日志中的事件。如下:
配置Master的my.cnf文件(关键性的配置)/etc/my.cnf
log-bin=mysql-bin
server-id = 1
binlog-do-db=icinga
binlog-do-db=DB2 //如果备份多个数据库,重复设置这个选项即可
binlog-do-db=DB3 //需要同步的数据库,如果没有本行,即表示同步所有的数据库
binlog-ignore-db=mysql //被忽略的数据库
配置Slave的my.cnf文件(关键性的配置)/etc/my.cnf
log-bin=mysql-bin
server-id=2
master-host=10.1.68.110
master-user=backup
master-password=1234qwer
master-port=3306
replicate-do-db=icinga
replicate-do-db=DB2
replicate-do-db=DB3 //需要同步的数据库,如果没有本行,即表示同步所有的数据库
replicate-ignore-db=mysql //被忽略的数据库
网友说replicate-do-db的使用中可能会出些问题(http://blog.knowsky.com/196961.htm),自己没有亲自去测试。猜想binlog-do-db参数用于主服务器中,通过过滤Binary Log来过滤掉配置文件中不允许复制的数据库,也就是不向Binary Log中写入不允许复制数据的操作日志;而replicate-do-db用于从服务器中,通过过滤Relay Log来过滤掉不允许复制的数据库或表,也就是执行Relay Log中的动作时不执行那些不被允许的修改动作。这样的话,多个从数据库服务器的情况:有的从服务器既从主服务器中复制数据,又做为主服务器向另外的从服务器复制数据,那它的配置文件中应该可以同时存在binlog-do-db、replicate-do-db这两个参数才对。一切都是自己的预测,关于binlog-do-db、replicate-do-db的具体使用方法还得在实际开发中一点点摸索才可以。
网上有说,复制时忽略某些数据库或者表的操作最好不要在主服务器上面进行,因为主服务器忽略之后就不会再往二进制文件中写了,但是在从服务器上面虽然忽略了某些数据库但是主服务器上面的这些操作信息依然会被复制到从服务器上面的relay log里面,只是不会在从服务器上面执行而已。我想这个意思应该是建议在从服务器中设置replicate-do-db,而不要在主服务器上设置binlog-do-db。
另外,不管是黑名单(binlog-ignore-db、replicate-ignore-db)还是白名单(binlog-do-db、replicate-do-db)只写一个就行了,如果同时使用那么只有白名单生效。
四 MySQL主从复制过程
MySQL主从复制的两种情况:同步复制和异步复制,实际复制架构中大部分为异步复制。复制的基本过程如下:
1、Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容。
2、Master接收到来自Slave的IO进程的请求后,负责复制的IO进程会根据请求信息读取日志指定位置之后的日志信息,返回给Slave的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置。
3、Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”。
4、Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。
五 MySQL主从复制的具体配置
复制通常用来创建主节点的副本,通过添加冗余节点来保证高可用性,当然复制也可以用于其他用途,例如在从节点上进行数据读、分析等等。在横向扩展的业务中,复制很容易实施,主要表现在在利用主节点进行写操作,多个从节点进行读操作,MySQL复制的异步性是指:事物首先在主节点上提交,然后复制给从节点并在从节点上应用,这样意味着在同一个时间点主从上的数据可能不一致。异步复制的好处在于它比同步复制要快,如果对数据的一致性要求很高,还是采用同步复制较好。
最简单的复制模式就是一主一从的复制模式了,这样一个简单的架构只需要三个步骤即可完成:
(1)建立一个主节点,开启binlog,设置服务器id;
(2)建立一个从节点,设置服务器id;
(3)将从节点连接到主节点上。
下面我们开始操作,以MySQL 5.5为例,操作系统Ubuntu12.10,Master 10.1.6.159 Slave 10.1.6.191。
1 |
apt-get install mysql-server |
Master机器
Master上面开启binlog日志,并且设置一个唯一的服务器id,在局域网内这个id必须唯一。二进制的binlog日志记录master上的所有数据库改变,这个日志会被复制到从节点上,并且在从节点上回放。修改my.cnf文件,在mysqld模块下修改如下内容:
1 |
[mysqld] |
2 |
server-id = 1 |
3 |
log_bin = /var/log/mysql/mysql-bin.log |
log_bin设置二进制日志所产生文件的基本名称,二进制日志由一系列文件组成,log_bin的值是可选项,如果没有为log_bin设置值,则默认值是:主机名-bin。如果随便修改主机名,则binlog日志的名称也会被改变的。server-id是用来唯一标识一个服务器的,每个服务器的server-id都不一样。这样slave连接到master后,会请求master将所有的binlog传递给它,然后将这些binlog在slave上回放。为了防止权限混乱,一般都是建立一个单独用于复制的账户。
binlog是复制过程的关键,它记录了数据库的所有改变,通常即将执行完毕的语句会在binlog日志的末尾写入一条记录,binlog只记录改变数据库的语句,对于不改变数据库的语句则不进行记录。这种情况叫做基于语句的复制,前面提到过还有一种情况是基于行的复制,两种模式各有各的优缺点。
Slave机器
slave机器和master一样,需要一个唯一的server-id。
1 |
[mysqld] |
2 |
server-id = 2 |
连接Slave到Master
在master和slave都已经配置好后,只需要把slave指向master即可。
1 |
change master to master_host='10.1.6.159',master_port=3306,master_user='rep','123456'; |
2 |
start slave; |
接下来在master上做一些针对改变数据库的操作,来观察slave的变化情况。在修改完my.cnf配置重启数据库后,就开始记录binlog了。可以在/var/log/mysql目录下看到一个mysql-bin.000001文件,而且还有一个mysql-bin.index文件,这个mysql-bin.index文件是什么?这个文件保存了所有的binlog文件列表,但是我们在配置文件中并没有设置改值,这个可以通过log_bin_index进行设置,如果没有设置改值,则默认值和log_bin一样。在master上执行show binlog events命令,可以看到第一个binlog文件的内容。
注意:上面的sql语句是从头开始复制第一个binlog,如果想从某个位置开始复制binlog,就需要在change master to时指定要开始的binlog文件名和语句在文件中的起点位置,参数如下:master_log_file和master_log_pos。
mysql> show binlog events\G
*************************** 1. row ***************************
Log_name: mysql-bin.000001
Pos: 4
Event_type: Format_desc
Server_id: 1
End_log_pos: 107
Info: Server ver: 5.5.28-0ubuntu0.12.10.2-log, Binlog ver: 4
*************************** 2. row ***************************
Log_name: mysql-bin.000001
Pos: 107
Event_type: Query
Server_id: 1
End_log_pos: 181
Info: create user rep
*************************** 3. row ***************************
Log_name: mysql-bin.000001
Pos: 181
Event_type: Query
Server_id: 1
End_log_pos: 316
Info: grant replication slave on *.* to rep identified by '123456'
3 rows in set (0.00 sec)
Log_name 是二进制日志文件的名称,一个事件不能横跨两个文件
Pos 这是该事件在文件中的开始位置
Event_type 事件的类型,事件类型是给slave传递信息的基本方法,每个新的binlog都已Format_desc类型开始,以Rotate类型结束
Server_id 创建该事件的服务器id
End_log_pos 该事件的结束位置,也是下一个事件的开始位置,因此事件范围为Pos~End_log_pos-1
Info 事件信息的可读文本,不同的事件有不同的信息
在master的test库中创建一个rep表,并插入一条记录。
1 |
create table rep(name var); |
2 |
insert into rep values ("guol"); |
3 |
flush logs; |
flush logs命令强制轮转日志,生成一个新的二进制日志,可以通过show binlog events in 'xxx'来查看该二进制日志。可以通过show master status查看当前正在写入的binlog文件。这样就会在slave上执行相应的改变操作。
上面就是最简单的主从复制模式,不过有时候随着时间的推进,binlog会变得非常庞大,如果新增加一台slave,从头开始复制master的binlog文件是非常耗时的,所以我们可以从一个指定的位置开始复制binlog日志,可以通过其他方法把以前的binlog文件进行快速复制,例如copy物理文件。在change master to中有两个参数可以实现该功能,master_log_file和master_log_pos,通过这两个参数指定binlog文件及其位置。我们可以从master上复制也可以从slave上复制,假如我们是从master上复制,具体操作过程如下:
(1)为了防止在操作过程中数据更新,导致数据不一致,所以需要先刷新数据并锁定数据库:flush tables with read lock。
(2)检查当前的binlog文件及其位置:show master status。
1 |
mysql> show master status\G |
2 |
*************************** 1. row *************************** |
3 |
File: mysql-bin.000003 |
4 |
Position: 107 |
5 |
Binlog_Do_DB: |
6 |
Binlog_Ignore_DB: |
7 |
1 row in set (0.00 sec) |
(3)通过mysqldump命令创建数据库的逻辑备分:mysqldump --all-databases -hlocalhost -p >back.sql。
(4)有了master的逻辑备份后,对数据库进行解锁:unlock tables。
(5)把back.sql复制到新的slave上,执行:mysql -hlocalhost -p 把master的逻辑备份插入slave的数据库中。
(6)现在可以把新的slave连接到master上了,只需要在change master to中多设置两个参数master_log_file='mysql-bin.000003'和master_log_pos='107'即可,然后启动slave:start slave,这样slave就可以接着107的位置进行复制了。
1 |
change master to master_host='10.1.6.159' |
2 |
start slave; |
有时候master并不能让你锁住表进行复制,因为可能跑一些不间断的服务,如果这时master已经有了一个slave,我们则可以通过这个slave进行再次扩展一个新的slave。原理同在master上进行复制差不多,关键在于找到binlog的位置,你在复制的同时可能该slave也在和master进行同步,操作如下:
(1)为了防止数据变动,还是需要停止slave的同步:stop slave。
(2)然后刷新表,并用mysqldump逻辑备份数据库。
(3)使用show slave status查看slave的相关信息,记录下两个字段的值Relay_Master_Log_File和Exec_Master_Log_Pos,这个用来确定从后面哪里开始复制。
(4)对slave解锁,把备份的逻辑数据库导入新的slave的数据库中,然后设置change master to,这一步和复制master一样。
六 深入了解MySQL的主从配置
1、一主多从
由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。
在上图中,是我们开始时提到的一主多从的情况,这时主库既要负责写又要负责为几个从库提供二进制日志。这种情况将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从,或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。PS:这些前面都写过了,又复制了一遍。
2、主主复制
上图中,Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。在这种复制架构中,各自上运行的不是同一db,比如左边的是db1,右边的是db2,db1的从在右边反之db2的从在左边,两者互为主从,再辅助一些监控的服务还可以实现一定程度上的高可以用。
3、主动—被动模式的Master-Master(Master-Master in Active-Passive Mode)
上图中,这是由master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中只有一个节点在提供读写服务,另外一个节点时刻准备着,当主节点一旦故障马上接替服务。比如通过corosync+pacemaker+drbd+MySQL就可以提供这样一组高可用服务,主备模式下再跟着slave服务器,也可以实现读写分离。
4、带从服务器的Master-Master结构(Master-Master with Slaves)
这种结构的优点就是提供了冗余。在地理上分布的复制结构,它不存在单一节点故障问题,而且还可以将读密集型的请求放到slave上。
5、MySQL-5.5支持半同步复制
早前的MySQL复制只能是基于异步来实现,从MySQL-5.5开始,支持半自动复制。在以前的异步(asynchronous)复制中,主库在执行完一些事务后,是不会管备库的进度的。如果备库处于落后,而更不幸的是主库此时又出现Crash(例如宕机),这时备库中的数据就是不完整的。简而言之,在主库发生故障的时候,我们无法使用备库来继续提供数据一致的服务了。Semisynchronous Replication(半同步复制)则一定程度上保证提交的事务已经传给了至少一个备库。Semi synchronous中,仅仅保证事务的已经传递到备库上,但是并不确保已经在备库上执行完成了。
此外,还有一种情况会导致主备数据不一致。在某个session中,主库上提交一个事务后,会等待事务传递给至少一个备库,如果在这个等待过程中主库Crash,那么也可能备库和主库不一致,这是很致命的。如果主备网络故障或者备库挂了,主库在事务提交后等待10秒(rpl_semi_sync_master_timeout的默认值)后,就会继续。这时,主库就会变回原来的异步状态。
MySQL在加载并开启Semi-sync插件后,每一个事务需等待备库接收日志后才返回给客户端。如果做的是小事务,两台主机的延迟又较小,则Semi-sync可以实现在性能很小损失的情况下的零数据丢失。
http://www.centoscn.com/mysql/2014/0610/3115.html
数据库服务器随着数据的不断增加,由单台MYSQL作为独立的数据承载很多时候并不能满足需求,无论是在安全性,高可用性以及并发等各个方面….
因此,一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力这样的方案来进行部署与实施的。
Mysql 主从复制的好处有:
1、采用主从服务器这种架构,稳定性得以提升。如果主服务器发生故障,我们可以使用从服务器来提供服务。
2、在主从服务器上分开处理用户的请求,可以提升数据处理效率。
3、将主服务器上的数据复制到从服务器上,保护数据免受意外的损失。
如下图:
![]()
mysql-master-slave
1、Mysql 的安装和配置
我好想暂时没有写example出来,晚点我更新下…..
2、Mysql 的主从配置
环境如下:
主数据库服务器:10.204.24.10,MySQL已经安装,无应用数据。
从数据库服务器:10.204.24.11,MySQL已经安装,无应用数据。
2.1 主服务器上进行配置
####下面列出的配置是你(除开常规正常的配置后)配置Mysql 主从必须的配置
[root@i-it-master /]# cat /etc/my.cnf
[mysqld]
log-bin=mysql-bin ###########启用二进制日志#############
server-id=10 ###########服务器唯一ID,取IP最后一段###########
###启动Mysql 服务###
[root@i-it-master /]# service mysqld start
Starting mysqld: [ OK ]
###默认Mysql 没有密码....renew###
[root@i-it-master /]# mysqladmin -uroot password "mysql-password"
###登陆mysql###
[root@i-it-master /]# mysql -uroot -p
Enter password:
###授权给Slave服务器###
mysql> GRANT REPLICATION SLAVE ON *.* to 'root'@'10.204.24.11' identified by 'mysql-password';
###查询主数据库状态###
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000008 | 544 | | |
+------------------+----------+--------------+------------------+
###这里需要记录 File 以及 Position 的值,在操作从服务器时会用到###
2.2 配置Slave 服务器
####下面列出的配置是你(除开常规正常的配置后)配置Mysql 主从必须的配置
[root@i-it-slave /]# cat /etc/my.cnf
[mysqld] #####艾玛 我也是复制的前面的#####
log-bin=mysql-bin ###########启用二进制日志#############
server-id=11 ###########服务器唯一ID,取IP最后一段###########
###启动Mysql 服务###
[root@i-it-slave /]# service mysqld start
Starting mysqld: [ OK ]
###默认Mysql 没有密码....renew###
[root@i-it-slave /]# mysqladmin -uroot password "mysql-password"
###登陆mysql###
[root@i-it-slave /]# mysql -uroot -p
Enter password:
###执行同步SQL语句###
mysql> CHANGE master to
-> master_host='10.204.24.10',
-> master_user='root',
-> master_password='mysql-password',
-> master_log_file='mysql-bin.000008',
-> master_log_pos=544;
Query OK, 0 rows affected (0.03 sec)
###启动Slave 同步进程####
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: 10.204.24.10
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 262
Relay_Log_File: mysqld-relay-bin.000002
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:













