mariadb/mysql主从复制

一、mysql的复制原理

至少需要两个节点,一主(master)一从(slave)

那么从节点如何从主节点获得数据呢?

1、主节点开启二进制日志,记录了修改数据的所有语句

2、从节点扮演mysql客户端请求主节点的二进制日志,默认是第一个文件的最开始位置,通常要指定二进制文件的指定位置。从节点收到二进制日志后保存在本地的中继日志中,并且会记录已经读取到哪个二进制日志的哪个位置,用作再次请求二进制日志的起始位置。从节点会读取中继日志中的事件完成重放后从而形成一模一样的数据保存在数据库中。

3、slave节点上负责从master节点上请求二进制日志的线程叫做IO_THREAD,从节点收到二进制日志后,保存在本地中继日志中并由SQL_THREAD做重放后将数据保存在数据库中。

4、主节点会为每个请求二进制日志的从服务器线程IO_THREAD启动一个响应线程dump_thread,该线程负责读取主服务器上的二进制日志并发送给从服务器。

二、mysql基于二进制日志主从复制特点:

1、异步复制

当客户端写入数据时,主节点记录完二进制日志便回复客户端已经写好了,而无需等待从节点写入完成才回复。因此,数据刚刚在主服务器上写入完成,而没有来得及同步到从节点的话,从服务器上是读取不到该数据的。

2、从节点可能会落后于主节点/主从数据不一致

有时候,落后也是有好处的,万一主服务器上误删了数据,从服务器上还是可以保留一段时间的。可以专门部署一台服务器落后于主节点的。

主节点上,事务是可以并行执行提交的,但是二进制日志还是只能串行写入的,而等到从节点过来读取二进制日志并完成重放以后,就必然是落后了。

根据经验:同一机房内,主从之间最多落后1秒,可以接受

问题一:从节点上的中继日志完成重放后需要保留吗?

不需要,SQL_THREAD把中继日志重放完了以后

问题二:从节点上需要保存二进制日志吗?

需要看情况而定

1、二进制日志是用来发给从服务器做事件重放使用,所以从服务器如果没有从服务器的话,是不需要保留二进制日志的,因为保存二进制日志会增加了IO压力。

2、如果mysql从服务器拥有自己的从服务器,这种架构就是mysql的级联复制

补充知识点

二进制日志的事件记录格式:

STATEMENT:只记录修改的语句,虽然节省空间但不推荐,极有可能导致数据不一致

ROW:记录被修改的行的数据,记录数据最精确,需要更多存储空间,推荐

MIXED:默认的记录格式,mysql自行判定以STATEMENT还是ROW的方式来记录,推荐

三、主从复制模型配置过程演示

主节点:开启二进制日志,设定全局唯一的SERVER_ID,创建拥有复制权限的用户账号(需要REPLICATION SLAVE,REPLICATION CLIENT)

从节点:开启中继日志,设定全局唯一的SERVER_ID,使用有复制权限的用户账号连接至主服务器并启动复制线程

node1: 172.16.92.1/16 mariadb主服务器

node2: 172.16.92.2/16 mariadb从服务器

以上节点均为CentOS 7.1

配置环境

1. 配置好光盘yum源

2. 关闭selinux和iptables

node1: mariadb主服务器[root@node1 ~]# yum -y install mariadb-server[root@node1 ~]# vim /etc/my.cnf[mysqld]datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.sock# Disabling symbolic-links is recommended to prevent assorted security riskssymbolic-links=0# Settings user and group are ignored when systemd is used.# If you need to run mysqld under a different user or group,# customize your systemd unit file for mariadb according to the# instructions in http://fedoraproject.org/wiki/Systemd#######以下的内容为添加#########二进制变更日志log-bin=mysql-bin#二进制日志格式为混合模式binlog_format=mixed#为主服务器node1的ID值server-id = 1port = 3306skip-external-lockingkey_buffer_size = 256Mmax_allowed_packet = 1Mtable_open_cache = 256sort_buffer_size = 1Mread_buffer_size = 1Mread_rnd_buffer_size = 4Mmyisam_sort_buffer_size = 64Mthread_cache_size = 8query_cache_size= 16Mthread_concurrency = 4innodb_file_per_table = onskip_name_resolve = on##################################### 以下的内容可选 ########[mysqldump]quickmax_allowed_packet = 16M[mysql]no-auto-rehash[myisamchk]key_buffer_size = 128Msort_buffer_size = 128Mread_buffer = 2Mwrite_buffer = 2M[mysqlhotcopy]interactive-timeout#############################[mysqld_safe]log-error=/var/log/mariadb/mariadb.logpid-file=/var/run/mariadb/mariadb.pid## include all files from the config directory#!includedir /etc/my.cnf.d############### End for my.cnf #################[root@node1 ~]# systemctl start mariadb[root@node1 ~]# mysqlMariaDB [(none)]> grant replication client,replication slave on *.* to 'repluser'@'172.16.92.2' identified by 'replpass';MariaDB [(none)]> flush privileges;MariaDB [(none)]> show master status\G*************************** 1. row ***************************            File: mysql-bin.000003        Position: 497    Binlog_Do_DB: Binlog_Ignore_DB: ##### 记下mysql-bin.000003 和 497 , 设置从服务器中继日志时有用 ####node2: mariadb从服务器[root@node2 ~]# yum -y install mariadb-server[root@node2 ~]# vim /etc/my.cnf[mysqld]datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.sock# Disabling symbolic-links is recommended to prevent assorted security riskssymbolic-links=0# Settings user and group are ignored when systemd is used.# If you need to run mysqld under a different user or group,# customize your systemd unit file for mariadb according to the# instructions in http://fedoraproject.org/wiki/Systemd########## 添加以下内容 ##########log-bin=mysql-binbinlog_format=mixedserver-id = 2relay-log = relay-binlog_slave_updates = 1read_only = onport = 3306skip-external-lockingkey_buffer_size = 256Mmax_allowed_packet = 1Mtable_open_cache = 256sort_buffer_size = 1Mread_buffer_size = 1Mread_rnd_buffer_size = 4Mmyisam_sort_buffer_size = 64Mthread_cache_size = 8query_cache_size= 16Mthread_concurrency = 4innodb_file_per_table = onskip_name_resolve = on############################################ 以下内容可选 ############[mysqldump]quickmax_allowed_packet = 16M[mysql]no-auto-rehash[myisamchk]key_buffer_size = 128Msort_buffer_size = 128Mread_buffer = 2Mwrite_buffer = 2M[mysqlhotcopy]interactive-timeout####################################[mysqld_safe]log-error=/var/log/mariadb/mariadb.logpid-file=/var/run/mariadb/mariadb.pid## include all files from the config directory#!includedir /etc/my.cnf.d############# End of my.cnf ###############[root@node2 ~]# systemctl start mariadb[root@node2 ~]# mysqlMariaDB [(none)]> show global variables like '%read_only%';| read_only     | ON    |MariaDB [(none)]> show global variables like '%read_only%'\G*************************** 1. row ***************************Variable_name: read_only        Value: ONMariaDB [(none)]> change master to master_host='172.16.92.1',master_user='repluser',master_password='replpass',master_log_file='mysql-bin.000003',master_log_pos=497,master_connect_retry=5,master_heartbeat_period=2;MariaDB [(none)]> show slave status\G*************************** 1. row ***************************               Slave_IO_State:                   Master_Host: 172.16.92.1                  Master_User: repluser                  Master_Port: 3306                Connect_Retry: 5              Master_Log_File: mysql-bin.000003          Read_Master_Log_Pos: 497               Relay_Log_File: relay-bin.000001                Relay_Log_Pos: 4        Relay_Master_Log_File: mysql-bin.000003             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: 497              Relay_Log_Space: 245              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: NULLMaster_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: 0MariaDB [(none)]> start slave;MariaDB [(none)]> show slave status\G*************************** 1. row ***************************               Slave_IO_State: Waiting for master to send event                  Master_Host: 172.16.92.1                  Master_User: repluser                  Master_Port: 3306                Connect_Retry: 5              Master_Log_File: mysql-bin.000003          Read_Master_Log_Pos: 497               Relay_Log_File: relay-bin.000002                Relay_Log_Pos: 529        Relay_Master_Log_File: mysql-bin.000003             Slave_IO_Running: Yes            Slave_SQL_Running: Yes    ........ 其余信息略 ........MariaDB [(none)]> show processlist\G*************************** 3. row ***************************      Id: 4    User: system user    Host:       db: NULL Command: Connect    Time: 144   State: Slave has read all relay log; waiting for the slave I/O thread to update it    Info: NULLProgress: 0.000#说明: 从节点已经接收到所有的中继日志node1 主节点上可查看到此进程MariaDB [(none)]> show processlist\G*************************** 2. row ***************************      Id: 4    User: repluser    Host: 172.16.92.2:56821      db: NULL Command: Binlog Dump    Time: 212   State: Master has sent all binlog to slave; waiting for binlog to be updated    Info: NULLProgress: 0.000在主节点上创建数据库测试是否能主从同步MariaDB [(none)]> create database testdb;在从节点上可看到testdb数据库, 说明主从同步成功!MariaDB [(none)]> show databases;+--------------------+| Database           |+--------------------+| information_schema || mysql              || performance_schema || test               || testdb             |+--------------------+再来看一下 从节点 的状态MariaDB [(none)]> show slave status\G*************************** 1. row ***************************               Slave_IO_State: Waiting for master to send event                  Master_Host: 172.16.92.1                  Master_User: repluser                  Master_Port: 3306                Connect_Retry: 5              Master_Log_File: mysql-bin.000003          Read_Master_Log_Pos: 584        #497->584               Relay_Log_File: relay-bin.000002                Relay_Log_Pos: 616            #529->616        Relay_Master_Log_File: mysql-bin.000003             Slave_IO_Running: Yes            Slave_SQL_Running: Yes############# mysql主从复制结束 ##############复制过滤器(1) 基于库的白名单的实现在从节点上设置MariaDB [(none)]> stop slave;MariaDB [(none)]> set global replicate_do_db='testdb';MariaDB [(none)]> start slave;MariaDB [(none)]> show global variables like '%replicat%';| replicate_do_db                  | testdb    |    #只同步该数据库的数据在主节点上创建新数据库, 查看是否能同步过来MariaDB [(none)]> create database mydb;从节点上并未看到mydb数据库MariaDB [(none)]> show databases;+--------------------+| Database           |+--------------------+| information_schema || mysql              || performance_schema || test               || testdb             |+--------------------+在主节点的testdb中插入数据, 查看是否能同步过来MariaDB [(none)]> use testdb;MariaDB [testdb]> create table t1(id int);MariaDB [testdb]> desc t1\G*************************** 1. row ***************************  Field: id   Type: int(11)   Null: YES    Key: Default: NULL  Extra: 从节点上查看一样的数据, 说明从服务器现在只能同步一个数据库MariaDB [(none)]> use testdb;MariaDB [testdb]> show tables\G*************************** 1. row ***************************Tables_in_testdb: t1MariaDB [testdb]> desc t1\G*************************** 1. row ***************************  Field: id   Type: int(11)   Null: YES    Key: Default: NULL  Extra: