MySQL复制的原理
复制过程分三步:
1、master将改变的数据记录到二进制日志(中(这些记录叫做二进制日志事件,binary log events);
2、slave将master的二进制日志事件拷贝到它的中继日志中
3、SQL线程读取中继日志,并且重放其中的事件,将改变反映到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 thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。
实现过程分四步:
一,安装mysql服务器
二,主从复制架构的实现
三,主从半同步的实现
四,主主复制架构的实现
一、安装mysql服务器(主从服务器都安装)
下载绿色版mysql-5.5.28-linux2.6-i686.tar.gz至本地;此版本不用编译安装
- 1、创建Mysql用户
- # groupadd -r mysql
- # useradd -g mysql -r -s /sbin/nologin -M mysql
- # mkdir -pv /data/mydata
- # chown -R mysql:mysql /data/mydata
- 2、安装Mysql
- # tar xf mysql-5.5.28-linux2.6-i686.tar.gz -C /usr/local
- # cd /usr/local
- # ln -sv mysql-5.5.28-linux2.6-i686 mysql
- # cd /mysql
- # chown root.mysql . -R
- 3、初始化Mysql
- # scripts/mysql_install_db --user=mysql --datadir=/data/mydata
- cp support-files/my-large.cnf /etc/my.cnf
- vim /etc/my.cnf ##做如下修改
- thread_concurrency = 2
- datadir = /data/mydata ##指定mysql数据文件的存放位置
- # cp support-files/mysql.server /etc/rc.d/init.d/mysqld
- 添加至服务列表:
- # chkconfig --add mysqld
- # chkconfig mysqld on
- 4、导出PATH环境变量
- # vim /etc/profile.d/mysql.sh
- 添加如下:
- PATH=$PATH:/usr/local/mysql/bin
- export PATH
- 5、输出mysql的man手册至man命令的查找路径:
- #vim /etc/man.config,添加如下行即可:
- MANPATH /usr/local/mysql/man
- 6、输出mysql的头文件至系统头文件路径/usr/include:
- 这可以通过简单的创建链接实现:
- # ln -sv /usr/local/mysql/include /usr/include/mysql
- 7、输出mysql的库文件给系统库查找路径:
- # echo '/usr/local/mysql/lib' > /etc/ld.so.conf.d/mysql.conf
- 8、而后让系统重新载入系统库:
- # ldconfig
- 启动mysql服务:
- #service mysqld start
二,mysql主从复制的实现
主服务器:172.16.14.9
从服务器:172.16.14.10
mysql主从复制分大致三个步骤:
1)在每个服务器上创建一个复制帐号
2)配置master和slave;
3)Slave连接master开始复制
1、在主服务器上创建仅限slave主机使用的专门用于进行复制数据的用户,
- mysql> grant replication client,replication slave on *.* to
- rpuser@'172.16.14.%' identified by 'rpuser';
- mysql> flush privileges;
2、配置主服务器
2.1、查看二进制日志的状态是否开启:
- mysql> show variables like 'log_bin';
- +---------------+-------+
- | Variable_name | Value |
- +---------------+-------+
- | log_bin | ON |
- +---------------+-------+
若value为OFF,在/etc/my.cnf添加如下行
log-bin=mysql-bin
2.2、指定唯一的server id:
#vim /etc/my.cnf
在[mysqld]的配置中修改:
server-id = 1
重启mysql服务器使生效:
#service mysqld restart
然后查看master的状态:
- ysql> show master status;
- +------------------+----------+--------------+---------------
- ---+
- | File | Position | Binlog_Do_DB |
- Binlog_Ignore_DB |
- +------------------+----------+--------------+---------------
- ---+
- | mysql-bin.000001 | 107 |
- | |
- +------------------+----------+--------------+---------------
- ---+
- mysql> show binlog events in 'mysql-bin.000001'\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-log, Binlog ver: 4
- 1 row in set (0.00 sec)
3、配置从服务器
3.1、从服务器不需要二进制日志,只需要启动中继日志
- # vim /etc/my.cnf
- 注释掉下面两行
- log-bin=mysql-bin
- binlog_format=mixed
- 添加如下两行:
- relay-log=relay-mysql
- relay-log-index=relay-mysql.index
3.2、指定从服务的server-id
- # vim /etc/my.cnf
- server-id = 10 ##主从服务器的server id不能相同
3.3、为slave指定master;用户必须是在主服务器上建立的用户rpuser
- mysql> change master to master_host='172.16.14.9',
- -> master_user='rpuser',
- -> master_password='rpuser',
- -> master_log_file='mysql-bin.000001',
- -> master_log_pos=107;
4、启动从服务器进程并查看运行状态;
- mysql> start slave;
- mysql> show slave status\G
如果出现如下行,则表明正常启动
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
5、测试复制过程的实现;
在主服务器上创建一个库和表,如果在从服务器上能看到相应库表话
说明主从服务器可以正常运行了
- mysql> create database testdb;
- Query OK, 1 row affected (0.00 sec)
- mysql> use testdb;
- Database changed
- mysql> create table table1 (id int primary key
- auto_increment,name char(20));
在从服务器上查看:
- mysql> show databases;
- +--------------------+
- | Database |
- +--------------------+
- | information_schema |
- | drbd |
- | jiaowu |
- | mysql |
- | performance_schema |
- | testdb |
- +--------------------+
三:半同步的实现:
默认主从复制是异步进行的,一段时间后会使得从服务器的数据时间落后于主服务器的;如果主服务器故障的话,将会有一部分数据来不及从主服务器上复制到从服务器上,后来goole为mysql贡献了一个插件,实现半同步复制,大大缩减了同步花费的时间,那就是 Semi-sync。
之所以叫半同步,是因为主服务器只等待多个从服务器中的某一台从服务器复制完成;这在一定程度上加强了数据安全性,但当从服务器挂掉时,主服务器不能一直等待,此时就需要定义一个超时时间,在这个超时时间内如果无法完成半同步,那么,就自动把半同步降低到异步模式。
- cd /usr/local/mysql/lib/plugin
- semisync_master.so semisync_slave.so ##该目录下有两个插件,分别为主从准备的
1、在主服务器上配置:
- # install plugin rpl_semi_sync_master soname
- 'semisync_master.so'; ##安装插件
- mysql> set global rpl_semi_sync_master_enabled = 1;
- mysql> set global rpl_semi_sync_master_timeout = 1000;
- # vim /etc/my.cnf ##在配置文件中永久生效
- 在[mysqld]中添加:
- rpl_semi_sync_master_enabled=1 开启半同步功能
- rpl_semi_sync_master_timeout=1000 设定超时时间为1000ms
- # service mysqld restar
2、在从服务器上配置:
- mysql> install plugin rpl_semi_sync_slave soname
- 'semisync_slave.so';
- mysql> set global rpl_semi_sync_slave_enabled=1;
- mysql> stop slave io_theard;
- mysql> start slave io_thread;
- # vim /etc/my.cnf
- 在[mysqld]中添加:
- rpl_semi_sync_slave_enabled=1 ##开启半同步功能
3、重启服务:
#service mysqld restart
查看主服务器上的semi_sync是否开启,注意clients 变为1,证明主从半同步复制连接成功:
- mysql> show global status like 'rpl_semi%';
- +----------------------------+-------+
- | Variable_name | Value |
- +----------------------------+-------+
- | Rpl_semi_sync_slave_status | ON |
- +----------------------------+-------+
四:主主复制架构:
在主主模式中,两台服务器都可以读,可以写,彼此又是对方的从服
务器,互为主从。两个服务器可以对读操作进行分摊,写操作不可以。
1、双方都要创建具有复制权限的用户
上面在172.16.14.9上创建了一个复制权限的用户,下面在172.16.14.
10上创建一个具有复制权限的用户:
- mysql> grant replication client,replication slave on *.* to
- rpuser@'172.16.14.9' identified by 'rpuser';
2.两个主服务器server-id不能一样
- 在172.16.14.9主机上:
- server-id = 1
- 在172.16.14.10主机上:
- server-id = 10
3、双方都要开启二进制日志和中继日志,互为主从
- 在172.16.14.9主机上:
- # vim /etc/my.cnf
- 在[mysqld]中添加:
- replicate-do-db = jiaowu
- auto-increment-increment = 2
- auto-increment-offset = 1
- log-bin = mysql-bin
- 在172.16.14.10主机上:
- log-bin = mysql-bin
- replicate-do-db = jiaowu
- auto-increment-increment = 2
- auto-increment-offset = 2
重启服务
查看两个服务器状态:
- 172.16.14.9服务器状态:
- mysql> show master status\G;
- *************************** 1. row ***************************
- File: mysql-bin.000002
- Position: 107
- Binlog_Do_DB:
- Binlog_Ignore_DB:
- 1 row in set (0.00 sec)
- 172.16.14.10服务器状态:
- mysql> show master status\G;
- *************************** 1. row ***************************
- File: mysql-bin.000003
- Position: 107
- Binlog_Do_DB:
- Binlog_Ignore_DB:
- 1 row in set (0.01 sec)
4、两个主服务器互相指定对方为自己的主服务器;
在172.16.14.9主服务器上:
- mysql> change master to
- master_host='172.16.14.10',master_user='rpuser',master_passwo
- rd='rpuser',master_log_file='mysql-bin.000003',master_log_pos
- =107;
- mysql> start slave;
- mysql> show slave status\G;
- *************************** 1. row ***************************
- Slave_IO_State: Waiting for master to send
- event
- Master_Host: 172.16.14.10
- Master_User: rpuser
- Master_Port: 3306
- Connect_Retry: 60
- Master_Log_File: mysql-bin.000003
- Read_Master_Log_Pos: 107
- Relay_Log_File: master-relay-bin.000002
- Relay_Log_Pos: 253
- Relay_Master_Log_File: mysql-bin.000003
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
在172.16.14.10主服务器上:
- 在172.16.14.10主服务器上:
- mysql> change master to
- master_host='172.16.14.910',master_user='rpuser',master_passw
- ord='rpuser',master_log_file='mysql-bin.000002',master_log_po
- s=107;
如果出现如下两行,则说明工作正常:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
至此,主主复制也完成了