您的位置:首页 > 数据库 > SQL

Mysql DBA 高级运维学习笔记-Mysql主从复制原理及实战部署

2018-02-05 21:58 1426 查看

1. 普通文件数据同步

普通文件(磁盘上的文件)的同步方法

(1)NFS网络文件共享可以同步存储数据。

(2)Samba共享数据:http://blog.51cto.com/taokey/1203553

(3)定时任务或守护进程结合。

(4)Inotify+rsync触发式实时数据同步

(5)ftp数据同步。http://down.51cto.com/data/1094997

(6)ssh key+scp/rsync。

(7)svn版本管理。

(8)rsync,sersync,inotify,union(双向同步),csync(多向同步)。

总结linux运维场景数据同步方案

1.Scp,NFS,Sftp,http,samba,rsync,csync2,union

思想:

(1)文件级别也可以利用mysql,mongodb等软件。

(2)两个服务器同时写数据,双写就是一个同步机制。

2.文件系统级别同步。

Drdb(基于文件系统同步网络RAID1),同步几乎任何业务数据。

Mysql数据库的官方推荐drdb同步数据,所有单点服务例如:NFS,MFS(DRBD)等都可以用drdb。

3.数据库同步方案

a.自谁同步机制:

Mysql replcation,mysql 主从复制(逻辑的SQL从写)。

Oracle dataguard(物理的磁盘块,逻辑的sql语句从写)。

b.第三方drdb。

http://blog.51cto.com/oldboy/1240412

2. MySQL主从复制

2.1 mysql主从复制介绍

MySQL支持单向,双向,链式级联,实时、异步复制,在复制过程中,一台服务器充当主服务器(master),而一个或多个其他的服务器充当从服务器(slave)。

复制可以是单向:M==》S,也可以是双向M《==》M,当然也可以多M环状同步等。

如果设置了链式级联复制,那么,从(slave)服务器本身除了充当从服务器外,也会同时充当其下面从服务器的主服务器。

链式级联复制类似A->B->C->D的复制形式。

1.单向主从同步逻辑图





2.双向主主同步逻辑图



3.线性级联单向双主同步逻辑图



4.环状级联单向多主同步



5.环状级联单向多主多从同步逻辑图



在生产环境中所有对数据库内容的更新就必须在主服务器上进行,以避免用户对主服务器上数据内容的更新与对从服务器上数据库内容的灯芯不一致而导致发生冲突。

2.2 主从复制的应用场景

Mysql主从复制有利于数据库架构的健壮性,提升访问速度和易于维护管理。

(1)主从服务器互为备份

主从服务器架构的设置,可以大大的加强数据库架构的健壮性,例如当主服务器出现问题时,我们可以人工或自动切换到从服务器继续提供服务
http://blog.51cto.com/oldboy/1240412

非人为的硬件,服务故障,对于人为的执行drop,deletc无能为力。

(2)主从服务器读写分离分担网站压力

主从服务器架构可通过程序(php,java)或代理软件(mysql-proxy,amoeba)对用户(客户端)的请求实现读写分离,即通过在从库上仅仅处理用户的select查询请求,降低用户查询响应时间及读写同时在主服务器的压力,对于更新的数据(update,insert,delete)仍然交给主服务器处理,确保主服务器和从服务器保持实时同步。

中大型公司:通过程序(php,java)。

测试环境:代理软件(mysql-proxy,amoeba)。

门户网站:分布式dbproxy(读写分离,hash负载均衡。健康检查)。

(3)根据服务器拆分业务独立并分担压力

可以把几个不同的从服务器,根据公司的业务进行拆分,例如有为用户提供查询功能的从服务器,有DBA用来备份的从服务器,还有提供公司内部人员访问的后台,脚本,日志分析及开发人员服务的从服务器,这样的拆分除了减轻主服务器的压力外使得对外用户浏览,对内处理公司内部用户业务,及DBA备份业务互不受影响。

主从架构生产环境从服务器分业务拆分使用案例:

M—>S1 ==>对外部用户提供服务(浏览帖子、浏览博客、浏览文章)负载均衡。

-->S2 ==>对外部用户提供服务(浏览帖子、浏览博客、浏览文章)负载均衡。

-->S3 ==>对外部用户提供服务(浏览帖子、浏览博客、浏览文章)负载均衡

-->S4 ==>对内部用户提供服务(后台访问、脚本任务、数据分析、开发人员浏览)

-->S5==>数据库备份服务(开启从服务器binlog功能。可实现增量备份及恢复)

停掉SQL线程不停掉IO线程。

提示:轻重S1、S2、S3可以做负载均衡模式。

逻辑图:



2.3 如何实现MySQL主从读写分离

1.通过程序实现读写分离(性能,效率最佳,推荐)

Php和java程序都可以通过设置多个连接文件轻松的实现对数据库的读写分离,及当select时,就去连接读库的连接文件,当update,insert,delete时就连接写库的连接文件。

2.通过软件实现读写分离

MySQL-proxy,Amoeba等代理软件也可以实现读写分离功能,但最好用程序实现读写分离。

3.开发dbproxy

读写分离逻辑图如下所示:



2.4 生产环境MySQL主从复制基本架构

1.MySQL主从复制架构图



Mysql主从复制的原理:

左边是主库右边是从库,首先同步从库需要两个线程来完成,其中一个叫做sql线程另一个叫IO线程,在主库上只有一个线程负责完成主从同步叫IO线程,要想完成主从同步主库必须开启binlog,当用户请求主数据库的时候有增删改请求的时候它会把数据写到数据文件里面,然后把更新的结果写到binlog.在主从同步的时候是由从库找主库的在从库上要change master 在从库上要有master的,主机、用户、密码、端口、binlog文件、master_pos。start master to …start slave开启同步。开启同步之后首先是由从库的IO相主库发起请求,主库接收到从库的IO请求就会验证这个请求合不合法看用户名,密码,IP地址,端口是不是正确如果正确就可以连接了。然后从库在连接主库的时候会通过IO线程中的pos告诉主库我要从你的主库那个位置那个点给从库发binlog,比如说MASTER_LOG_FILE=’mysql-bin.000010’MASTER_LOG_POS的值等于4321,那主库的IO就会收到从库的这个请求,然后就会从binlog10日志的4321这个位置开始会给从库一直发binlog,从库收到log日志会把log日志写到rela-log中(称为中继日志),这时IO线程就不管了。然后还有一个文件较masterinfo这个文件记录了change master的内容,这时IO线程取到的日志扔到relay-log里面会根据最后取到的日志文件的位置点来更新change master。接下来再向主库的IO线程请求要上一次的那个文件的位置点往下的log,然后主库的IO把这些log再给从库发过来将日志写到slave-master里面,更新master info 里面的内容。那我们也没有同步啊,就是要数据;其实在第一次从库的IO线程把binlog放到relay-log里面这个SQL线程就发现了,发现了就会时时把relay-log的语句经过转换写到从库的主句文件里。然后IO不断的往里面写sql不断的读,不断的应用。

注意:如果需要在从库后面再加从库,从库一定要再开binlog。开启binlog的方法:

1.在从库上开binlog两条命令,将binlog打开。

2.再加一个log_slave_update。

总结:

(1)同步的时候从库有两个线程来完成IO,SQL;主库有一个线程来完成IO线程。

(2)要在从库上面配置连接主库的IP、用户名、账号、密码、连接主库的文件位置以及pos点,在从库开启start salve之前要在同步位置点之前的所有数据要灌到从库上面来要不然从位置点以后是一致的前面不一致。

(3)在开启开关之前要保证主从库基于位置点是一致的,就是在文件的位置点以前从库是有完整数据的。

(4)要在主库上建立专门用与主库同步的账号。

(5)主库要打开binlog开关否则没法实现同步。

(6)从库打开开关的过程就是让IO,SQL线程都工作。

3.复制准备

3.1 定义服务器角色

主库(mysql master):ip为192.168.1.115 port为3306

从库1(mysql slave):ip为192.168.1.115 port为3307

从库2 (mysql slave):ip为192.168.1.115 port为3308

提示:

一般常规主从复制在不同的机器上,并且监听的端口均为默认的3306,本文主从复制技术环境以单数据库多实例来讲解学习,上文已经写了怎么配置mysql多实例。虽然不在同一台机器上,但步骤和过程都是一样的。

3.2 数据库环境准备

(1)具备单机单数据库多实例的环境。

(2)或两台服务器每个机器一个数据库环境。

3.3 数据库读法的约定

主库,也称master 3306

从库,也称slave 3307

4.主库上执行的操作

4.1 设置server-id值并开启binlog参数

MySQL的主从同步原理,复制的关键因素就是binlog日志,所有首先打开bin-log日志,按如下两个参数修改。重启服务器生效。

[root@mysqlduoshili ~]# egrep "\[mysqld]|log-bin|server-id" /data/3306/my.cnf
[mysqld]
log-bin = /data/3306/mysql-bin
server-id = 1

提示:

a.上面的两个参数要放在my.cnf中的[mysqld]模块下,否则会出错。

b.一般server的值使用服务器ip地址的最后8位如19,目的是避免不同机器或实例ID重复(不适合多实例)。

1.查看主库log_big是否开启

[root@mysqlduoshili ~]# mysql -usystem -p123456 -S /data/3306/mysql.sock -e "show variables;" |egrep "log_bin|server_id"
log_bin    ON
log_bin_trust_function_creators    OFF
server_id    1
sql_log_bin    ON

2.看3306下面有没有日志,有就生效了



4.2 建立用于同步的账号

登录mysql 3306实例主数据库

[root@mysqlduoshili ~]# mysql -usystem -p123456 -S /data/3306/mysql.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.5.32-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

建立用于从库用于复制的账号rep,别忘了刷新

mysql> grant replication slave on *.* to 'rep'@'192.168.1.%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> show grants for rep@'192.168.1.%'\G
*************************** 1. row ***************************
Grants for rep@192.168.1.%: GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.1.%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'
1 row in set (0.00 sec)

提示:

(1)replication slave同步的必须权限,不要授权all。

(2).表示所有库所有表。

(3)'rep'@'192.168.1.%' rep为同步账号,192.168.1.%授权主机段。

4.3 对数据库锁表只读(当前窗口不要关掉)

生产环境操作主从复制需要申请停机时间,数据量很大锁表会影响业务后面有一键完成主从的方案。

mysql> flush table with read lock;
Query OK, 0 rows affected (0.00 sec)

提示:这个锁表命令的时间,在不同引擎的情况下,会受到下面参数的限制,超过设置的时间会自动解锁。

Interaction_timeout = 28800
wait_timeout = 28800

默认情况下的时间长为:28800,主要看interactive_timeout和wait_timeout这两个参数。

mysql> show variables like '%timeout%';
+----------------------------+----------+
| Variable_name  | Value|
+----------------------------+----------+
| connect_timeout| 10   |
| delayed_insert_timeout | 300  |
| innodb_lock_wait_timeout   | 120  |
| innodb_rollback_on_timeout | OFF  |
| interactive_timeout| 28800|
| lock_wait_timeout  | 31536000 |
| net_read_timeout   | 30   |
| net_write_timeout  | 60   |
| slave_net_timeout  | 3600 |
| wait_timeout   | 28800|
+----------------------------+----------+

4.4 查看主库的状态

查看主库的状态及当前binlog日志文件名和二进制binlog日志偏移量
Show master status;命令显示的数据要记录下来,后面的从库复制时是从这个位置开始的。

mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000036 |  335 |  |  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

4.5 导出数据库数据

单开新窗口,导出数据库数据,如果数据量很大,并且允许停机,可以挺库直接打包数据文件迁移

[root@mysqlduoshili ~]# mysqldump -usystem -p123456 -S /data/3306/mysql.sock -A -B --events|gzip >/opt/rep.sql.gz

--master-data 最小化备份mysql数据库直接找到binlog的位置
[root@mysqlduoshili ~]# mysqldump -usystem -p123456 -S /data/3306/mysql.sock -A -B --events --master-data=2 >/opt/rep.sql

提示:-A表示所有数据库-B增加use DB和drop等(导库时会覆盖所有的)

为了保证导库期间,数据库没有数据写入,可以再检查主库状态信息,如果和之前查看的不对就出问题了没锁住表。

[root@mysqlduoshili ~]# mysql -usystem -p123456 -S /data/3306/mysql.sock -e "show master status\G"
*************************** 1. row ***************************
File: mysql-bin.000036
Position: 335
Binlog_Do_DB:
Binlog_Ignore_DB:

导库后,解锁主库,恢复可写;

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

4.6 把主库导出的mysql数据迁移到从库

可以就用scp将备份的日志文件传给从服务器就可以,这里使用多实例就不讲解了。

5.从库上执行的操作

5.1 设置server-id值并关闭binlog参数

数据库的server-id值一般在LAN内是唯一的,这里的server-id要和主库及其他从库不同,并注释掉从库里的binlog参数配置

[root@mysqlduoshili 3307]# egrep "\[mysqld]|server-id|log-bin" /data/3307/my.cnf
[mysqld]
#log-bin = /data/3307/mysql-bin
server-id = 2

有两种情况需要打开log-bin记录数据库更新的sql语句

a.级联同步A->B->C;那中间的B就要开启log-bin

b.在从库做数据备份数据备份必须要有全备和binlog日志,才是完整的备份。

重启从数据库。

/data/3307/mysql restart

5.2 还原主库导出的数据到从库

[root@mysqlduoshili ~]# mysql -uroot -p123456 -S /data/3307/mysql.sock </opt/rep.sql

5.3 登录从库配置同步参数

mysql> CHANGE MASTER TO
-> MASTER_HOST='192.168.1.115',   主库的IP
-> MASTER_PORT=3306, 主库的端口,从库端口可以和主库不同
-> MASTER_USER='rep',主库上建立的用于复制的用户rep
-> MASTER_PASSWORD='123456', 这里是rep的密码
-> MASTER_LOG_FILE='mysql-bin.000036',这里是show master status;查看到的二进制日志文件名称注意不能有空格。
-> MASTER_LOG_POS=335;这里也是show master status时看到的二进制日志偏移量注意不能多空格。
Query OK, 0 rows affected (0.02 sec)

也可以不登录数据库执行CHANGE MASTER 的语句(适合在脚本中批量建slave库用)

Cat |mysql -uroot –p123456 -S /data/3307/mysql.sock<<EOF
CHANGE MASTER TO
MASTER_HOST='192.168.1.115',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000036',
MASTER_LOG_POS=335;
EOF

上述操作原理实际就是把用户密码等信息写入从库的master.info

[root@mysqlduoshili data]# cat master.info
18
mysql-bin.000036
335
192.168.1.115
rep
123456
3306
60

5.4 启动从库同步开关

启动从库同步开关并查看同步状态

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.115 当前的mysql master服务器主机
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000036
Read_Master_Log_Pos: 335
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000036
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: mysql
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: 335
Relay_Log_Space: 403
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0 和主库比同步延迟的秒数这个参数很重要
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec)

判断复制是否搭建成功就看如下IO和SQL两个线程是否显示yes状态

[root@mysqlduoshili 3307]# mysql -uroot -p123456 -S /data/3307/mysql.sock -e "show slave status\G;"|egrep "IO_Running|SQL_Running|Seconds"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0

5.5 测试复制结果

在主数据库上创建一个库并查看一下

mysql> create database linzhongniao;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database   |
+--------------------+
| information_schema |
| d3306  |
| linzhongniao   |
| mysql  |
| performance_schema |
| test   |
+--------------------+
6 rows in set (0.00 sec)

接下来在查看一下从库

mysql> show databases;
+--------------------+
| Database   |
+--------------------+
| information_schema |
| d3306  |
| d3307  |
| linzhongniao   |
| mysql  |
| performance_schema |
| test   |
| zbf|
+--------------------+
8 rows in set (0.13 sec)

从库中也出现linzhongniao库说明主从复制搭建成功。

Master-info和relay-info中继日志都会自动记录主库binlog更新数据的位置,例如我们在主库上创建一个库,master-info和relay-info中记录主库binlog日志的位置就由335变成了434。

[root@mysqlduoshili 3307]# cat relay-log.info
/data/3307/relay-bin.000002
352
mysql-bin.000036
434
[root@mysqlduoshili 3307]# cat data/master.info
18
mysql-bin.000036
434
192.168.1.115
rep
123456
3306
60
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Mysql