主节点 172.16.26.1
[root@localhost mysql]# mkdir /mydata/{bindata,data} �Cpv
/etc/mysql/my.cnf =>修改主配置文件
datadir = /mydata/data log-bin=/mydata/bindata/mysql1-bin => 二进制文件另找位置存放
备节点 172.16.26.5
[root@localhost mysql]# mkdir /mydata/{bindata,data,relaylogs} �Cpv
/etc/mysql/my.cnf =>修改主配置文件
bindata 二进制目录
data, 数据目录
relaylogs 中继日志
log-bin=/mydata/bindata/mysql2-bin =>二进制文件记录位置
datadir=/mydata/data =>数据目录记录位置
relay-log=/mydata/relaylogs/relay-log =>中继日志记录位置 (指定即为开启中继日志)
server-id = 2 =>服务器id
配置过程:
master:
1、启用二进制日志
2、定义server-id 1
3、创建有复制权限的账号
REPLICATION SLAVE, =>从服务器权限 REPLICATION CLIENT =>同步客户端权限
为了安全性一般都需要replication slave 。如果单独设置replication slave,replication client 复制其实都可以运行的。mysql有一些特殊的权限允许复制进程运行,运行在从服务器上的I/O线程创建了到master的连接,这就意味着必须在主服务器上创建一个用户并且需要授予特殊的权限。这样I/O线程就会一特定的身份连接到主服务器上并且读取二进制日志。但是需要说明的一点是,复制用户在主服务器上实际只需要replication client 权限就可以运行的,这里授予replication slave的原因是用于监视和管理复制账号需要这个权限,并且这两个功能(复制需要的权限,监视和管理复制账号权限)通常是一个账号在管理,而不是为了达到这两个目标而分别设置2个账号
MariaDB [(none)]> grant replication slave,replication client on *.* to [email protected] identified by 'password';
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
slave:
1、启动中继日志 ==> /etc/mysql/my.cnf 添加 relay-log = /mydata/relaylogs/relay-log
2、定义server-id 2
3、使用有复制权限的账号连接master
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.16.26.1', MASTER_USER='repluser', MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql1-bin.000001',MASTER_LOG_POS=418;
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='172.16.26.1', MASTER_USER='repluser', MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql1-bin.000005',MASTER_LOG_POS=245;
4、启动io thread以及sql thread
START SLAVE IO_THREAD; =>启动io线程
START SLAVE SQL_THREAD; =>启动SQL线程
start SLAVE; =>启动从节点
SHOW SLAVE STATUS\G; =>查看从节点状态
stop SLAVE; =>停止从节点
主从复制架构中, 从服务器是只读的,如果在从服务器上写入数据,那么主服务器得不到同步, 后果是很严重的,所以要禁止从服务器写, 所以要将一个全局变量 read_only 改为1开启
set GLOBAL read_only=1; =>临时设置mysql的全局变量只读属性
想永久生效在配置文件中的 [mysqld] 下修改,
[mysqld]
read_only=1
但是这种限制,对于mysql的 root用户是无效的,所以开发中,要保护好root权限,尽量不要在程序中使用root用户直接对服务器写入数据
MariaDB [(none)]> show global variables like 'read_only';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| read_only | OFF |
+---------------+-------+
这样可以阻止所有的用户执行写操作
flush tables with read lock;
如何保证主从复制时的事务安全?
主服务器上,一但有事务提交,就必须把内存中的二进制信息同步到磁盘上.
前提:mysql对二进制日志事件数据会有缓冲;
在master上设置如下参数:
sync_binlog = 1
临时设置
set global sync_binlog=1;
想永久有效,还是得写入配置文件中
[mysqld]
sync_binlog=1
对于事务操作很频繁的服务器,应该关闭autocommit 事务自动提交功能
由开发在前端的语句中控制
autocommit = OFF
实现半同步复制
半同步复制的概念是:主节点master要等待一个从节点把数据完整复制过去;
master:
MariaDB [testdb]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; ==>安装主节点使用的半同步插件
MariaDB [testdb]> SHOW GLOBAL VARIABLES LIKE '%semi%';
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF | =>半同步插件是否开启
| rpl_semi_sync_master_timeout | 10000 | =>主节点等待从节点同步超时时长, 一般1,2秒即可, 主节点连接从节点超时后,会自动降级为异步模式
| rpl_semi_sync_master_trace_level | 32 | =>
| rpl_semi_sync_master_wait_no_slave | ON | =>是否等待至少一个从节点上来
+----------------------------------------+------+
MariaDB [testdba]> set global rpl_semi_sync_master_enabled=1; =>开启主节点的半同步工作机制
MariaDB [testdba]> set global rpl_semi_sync_master_timeout=1000; =>调整等待从节点的超时时长 注,这是临时修改,永久有效还是得改配置文件
slave:
MariaDB [mysql]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; ==>安装从节点使用的半同步插件
Query OK, 0 rows affected (0.06 sec)
MariaDB [mysql]> SHOW GLOBAL VARIABLES LIKE 'rpl_semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
MariaDB [mysql]> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
注意:只需要关闭并启动IO_THREAD即可;
主节点在联系从节点超时后,会自动降纸为异步模式;
在主节点验正是否已经工作于半同步模式:
SHOW GLOBAL STATUS LIKE '%semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 | =>从节点个数
| Rpl_semi_sync_master_net_avg_wait_time | 0 | 主节点为了等待从节点所消耗的平均时间
| Rpl_semi_sync_master_net_wait_time | 0 | 网络等待时间
| Rpl_semi_sync_master_net_waits | 0 | 网络等待次数
| Rpl_semi_sync_master_no_times | 0 | 无时间
| Rpl_semi_sync_master_no_tx | 0 | 无事务
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
+--------------------------------------------+-------+
MariaDB [testdba]> delete from tb1 where id<3; =>在主节点上,删除部分表中数据
Query OK, 2 rows affected (0.03 sec)
slave 中查看
MariaDB [testdba]> select * from tb1;
+------+
| id |
+------+
| 3 |
| 4 |
| 5 |
| 6 |
+------+
4 rows in set (0.00 sec) OK, id<3 的数据确实被删除了.
如果一台mysql主机,已经运行了一段时间,有许多数据了, 这时才想加入一台mysql服务器作为从节点,那么又应该怎么操作呢?
没有更好的办法, 只能是先将主服务器的数据备份一分出来,让从服务器先导入,而后,再从主服务器的备份节点开始同步.
mysqldump用来温备,所以我们得为所有库加读锁,并且滚动一下二进制日志,并记录当前二进制文件位置
mysqldump --all-databases --lock-all-tables --routines --triggers --master-data=2 --flush-logs > /mydata/`date +%F-%T`.sql
--all-databases 备份所有库
--lock-all-tables 为所有表加读锁
--routines 存储过程与函数
--triggers 触发器
--master-data=2 在备份文件中记录当前二进制日志的位置,并且为注释的,1是不注释掉在主从复制中才有意义
--flush-logs 日志滚动一次
将 /mydata/2014-09-19-00:37:04.sql 备份发送到从服务器,
节点导入数据时,最好把二进制日志先关闭,导入完成再把它开启
[root@www ~]# mysql -u root -p < /tmp/2014-09-19-00\:37\:04.sql =>在从服务器上,将备份导入数据库中, 中间输入正确的口令即可
复制过滤器
让slave仅复制有限的几个数据库,甚至于仅复制某数据库内有限的几张表的机制;
有两种方案:
1、在主节点上过滤
在向二进制日志记录事件时,仅记录指定数据库的相关操作;
binlog_do_db = # 数据库白名单
binlog_ignore_db = # 数据库黑名单
2、在从节点上过滤
仅从中继日志中读取指定的数据库或表的相关事件并应用于本地;
replicate_do_db =
replicate_ignore_db =
replicate_db_table = DB_NAME.TB_NAME
replicate_ignore_table =
replicate_wild_do_table =
replicate_wild_ignore_table =
mysql双主模型的配置
原master 172.16.26.1 配置为172.16.26.5的从节点 以实现两个节点间互为主从
/etc/mysql/my.cnf =>修改主配置文件
relay-log = /mydata/relaylogs/relay-log =>开启中继日志
auto-increment-offset=1 =>自增长id起始位
auto-increment-increment=2 =>自增长的步进
原slave 172.16.26.5 配置为172.16.26.1的主节点 以实现两个节点间互为主从
/etc/mysql/my.cnf =>修改主配置文件
log-bin=/mydata/bindata/mysql2-bin =>开始二进制日志
auto-increment-offset=2 =>自增长id起始位
auto-increment-increment=2 =>自增长的步进
MariaDB [(none)]> show master status\G;
*************************** 1. row ***************************
File: mysql2-bin.000005
Position: 424
Binlog_Do_DB:
Binlog_Ignore_DB: ==>查询得知 172.16.26.5的二进制日志位置
MariaDB [(none)]> grant replication slave,replication client on *.* to repluser@'172.16.%.%' identified by 'password'; =>为主服务器开启帐号权限
172.16.26.1 指定为 172.16.26.5的从服务器
CHANGE MASTER TO MASTER_HOST='172.16.26.5', MASTER_USER='repluser', MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql2-bin.000005',MASTER_LOG_POS=424;
CHANGE MASTER TO MASTER_HOST='172.16.26.5', MASTER_USER='repluser', MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql2-bin.000005',MASTER_LOG_POS=419;
MariaDB [(none)]> start slave; =>开启从节点
172.16.26.5
MariaDB [(none)]> create database dtest;
CREATE TABLE `ran` (
`id` int(3) NOT NULL AUTO_INCREMENT,
`username` char(3) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
172.16.26.1
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| dtest | =>172.16.26.1作为172.16.26.5的从节点, 已能将数据同步过来
| mysql |
| performance_schema |
| tbabc |
| test |
| testdba |
+--------------------+
7 rows in set (0.01 sec)
些时再插入数据
MariaDB [dtest]> INSERT INTO `ran` (`username`) VALUES ('abc'), ('def'), ('ghi'), ('jkl');
Query OK, 4 rows affected (0.02 sec)
Records: 4 Duplicates: 0 Warnings: 0
MariaDB [dtest]> select * from ran;
+----+----------+
| id | username |
+----+----------+
| 1 | abc |
| 3 | def |
| 5 | ghi |
| 7 | jkl |
+----+----------+
4 rows in set (0.00 sec) =>检测结果和预想的一样,从1开始,每次步进为2
172.16.26.5 上操作
MariaDB [dtest]> select * from ran;
+----+----------+
| id | username |
+----+----------+
| 1 | abc |
| 3 | def |
| 5 | ghi |
| 7 | jkl |
+----+----------+
4 rows in set (0.00 sec) =>结果已从172.16.26.1同步过来
MariaDB [dtest]> INSERT INTO `ran` (`username`) VALUES ('cba'), ('fed'), ('ihg'), ('lkj'); 再插入些数据
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
MariaDB [dtest]> select * from ran;
+----+----------+
| id | username |
+----+----------+
| 1 | abc |
| 3 | def |
| 5 | ghi |
| 7 | jkl |
| 8 | cba |
| 10 | fed |
| 12 | ihg |
| 14 | lkj |
+----+----------+
8 rows in set (0.00 sec) 数据是接着7开始写入的,也是每次步进两个. 双主模型实现完成