mariadb复制模型主从复制、半同步复制、双主复制、多主复制、以及启用ssl


    环境:虚拟机CentOS6.5x64 mariadb-10.0.23 

    mariadb编译安装方式和mysql类同mariadb下载地址https://downloads.mariadb.org/

    原理:mysql的复制是将主服务器的二进制日志发往从服务器,从服务器保存为中继日志,然后将中继日志执行写入数据库的过程。

    使用show global variables like '%log%';查看与日志相关的全局变量

    使用SET[GLOBAL | SESSION] system_var_name = expr设置全局或当前会话变量值(如果不想重启后失效需要写入到my.cnf的[mysqld]里面)

    二进制日志:记录的数据修改相关的操作,是用来实现数据恢复和复制的凭据。  

 log_bin = {ON|OFF},还可以是一个文件路径                          

 log_bin_trust_function_creators  不阻止任何存储函数

 sql_log_bin = {ON|OFF} 当前会话是否将二进制文件进入进二进制文件

 sql_log_off 是否将一般查询日志记入查询日志

 sync_binlog 同步缓冲中的二进制日志到硬盘的时间,1不基于时间同步,只在事件提交时同步

 binlog_format = {|statement|row|mixed} 基于语句|基于行|混合模式

 max_binlog_cache_size = mysql二进制日志的缓冲区大小,仅用于缓存事务类的语句

 max_binlog_stmt_cache_size 语句缓冲区大小,即事务类和非事务类共用的大小

 max_binlog_size 二进制日志文件的上限,单位为字节

 建议:切勿将二进制日志与数据文件放在同一设备

 可以临时通过sql_log_bin来控制二进制的写入

    中继日志:        

          对于非从服务器 中继日志没有启用

 relay_log_purge = {ON|OFF} 是否自动清理不在需要的中继日志

 relay_log_space_limit 中继大小是否限制

    授权:

        grant 权限类型 ON 操作对象 to 用户@主机 IDENTIFIED BY 密码

        备份:

        mysqldump

        1、完全备份 (--all-databases备份所有表)

mysqldump --databases mdb mydb --lock-all-tables --flush-logs --master-data=2 >/tmp/mariadb.sql

2、导出二进制日志文件进行增量备份head -30 /tmp/mariadb.sql

根据查看完全备份mariadb.sql获取下次开始的二进制日志文件的偏移量MASTER_LOG_POS=367已经日志文件master-bin.000004

        -- CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000004', MASTER_LOG_POS=367;

        3、现在在mdb.class里面插入数据,并删掉mdb数据库,然后恢复到mdb.class插入数据的状态

        insert into mdb.class(classname) values('张三丰'),('碧瑶');

        drop database mdb;

4、恢复,关闭当前会话的二进制日志记录,然后使用mariadb.sql恢复,然后使用二进制日志恢复到插入数据状态。

   1)、 set session sql_log_bin=0 暂时关闭二进制日志;show master status;记录一下档期的二进制偏移量

           2)、 source /tmp/mariadb.sql; 并查看select * from mdb.class;这时还没有插入的数据

           3)、 mysqlbinlog --start-position=367  /mariadb/log-bin/master-bin.000004找到删除之前的哪一点 at位置为截至位置             

                # at 590

                #160121 11:33:45 server id 22  end_log_pos 628 GTID 0-22-190

                /*!100001 SET @@session.gtid_seq_no=190*//*!*/;

                # at 628 

                #160121 11:33:45 server id 22  end_log_pos 712 Querythread_id=4exec_time=0error_code=0

                SET TIMESTAMP=1453347225/*!*/;

                drop database mdb

                /*!*/;

                DELIMITER ;

                 mysqlbinlog --start-position=367 --stop-position=628 /mariadb/log-bin/master-bin.000004 >/tmp/mariadb1.sql

           4)、source /tmp/mariadb1.sql 然后查看select * from mdb.class;                

                MariaDB [mdb]> select * from mdb.class;

                +---------+-----------+

                | classid | classname |

                +---------+-----------+

                |       1 | 华山      |

                |       2 | e mei     |

                |       3 | shao lin  |

                |       4 | xiao yao  |

                |       6 | 张三丰    |

                |       8 | 碧瑶      |

                +---------+-----------+

            Lvm-snapshot:基于LVM快照的备份:前提数据目录本身是一个lv,vg有可用空间。

            创建snapshot的大小并不需要和原始卷一样大,其大小仅仅只需要考虑两个方面:从shapshot创建到释放这段时间内,估计块的改变量有多大;数据更新的频率。一旦snapshot的空间记录满了原始卷块变换的信息,那么这个snapshot立刻被释放,从而无法使用,从而导致这个snapshot无效。            

            lvcreate -L 100M -s -n mydata-snap -p r /dev/myvg/mydata

-L 指定大小

-s 指定创建快照 snapshot

-n 指定名称 name 

-p 指定类型 读,写

/dev/myvg/mydata 原卷对谁做快照

                注意事项:

                1、事务日志跟数据文件必须在同一个卷上;

2、创建快照卷之前要,请求MySQL的全局锁,在快照创建完成后释放锁;

3、在请求全局锁完成之后,做一次日志滚动;做二进制日志文件及位置标记(手动进行mysql -e 'show master status' > /backups/master.info)

4、数据目录所在的逻辑卷的卷组应该有空余空间可以满足短时间的数据修改               

                步骤:

1、请求全局锁,并滚动日志

mysql>FLUSH TABLES WITH READ LOCK;

mysql>FLUSH LOGS;

2、做二进制日志文件及位置标记(手动进行)

mysql -e 'show master status' > /backups/master.info

3、创建快照卷

lvcreate -L size -s -n name -p r /path/to/some_lv

4、释放全局锁

mysql> UNLOCK TABLES

5、挂在快照卷并备份

mount /dev/myvg/mydata-snap /mnt

#cp -ar /mnt/* /backup/ 

6、备份完成之后,删除快照卷

umount /mnt

lvremove /dev/myvg/mydata-snap                

                恢复:

                    1、先复制出数据目录的二进制日志文件,前提二进制日志没有损坏,需要定期备份

    2、恢复时直接复制备份目录下的文件到数据目录***意保留文件的权限属主属组信息(直接删除之前的数据目录里的数据)

                    3、做即时点还原和上边的mysqldump恢复的3类同

                mysqldump是一个单线程工具能完成InnnoDB热备(热备是使用-singe-transaction代替--lock-all-tables)、MyISAM温备、Aria温备 备份和恢复过程较慢               

                lvm-snapshot:接近于热备的工具;因为要先请求全局锁,而后创建快照,并在创建快照完成后释放全局锁;

使用cp,tar等工具进行物理备份;

备份和恢复速度较快;

很难实现增量备份,并且请求全局锁需要等待一段时间,在繁忙的服务器上尤其如此;                

                Xtrbackup:由Percona提供的开源备份工具,InnoDB热备,增量备份;MyISAM温备,不支持增量;(这里不想结)

            MySQL(MariaDB )SSL配置:目的是为了进行加密复制 默认时关闭的(show global variables like '%ssl%';查看)

                    1、自签根证书

                        创建证书目录 这里

                        mkdir /usr/local/mariadb/ssl/ 

                        openssl genrsa 2048 > ca-key.pem                      

                        openssl req -new -x509 -nodes -days 1000 -key ca-key.pem > ca-cert.pem

                    2、签发服务器证书

                        openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem > server-req.pem

                        openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem

                        openssl rsa -in server-key.pem -out server-key.pem 

                    3、签发客户端证书                         

                        openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem > client-req.pem                         

                        openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem

                        openssl rsa -in client-key.pem -out client-key.pem 

                    验证:openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem

                    4.发送证书至客户端,停止Mysqld修改my.cnf重启,建立复制用户,开启复制线程

                        scp ca-cert.pem client-cert.pem client-key.pem 192.168.1.201:/usr/local/mariadb/ssl/

                        service mysqld stop                         

                        vim /usr/local/mariadb/my.cnf        这是我的配置文件路径          

                        ssl-ca=/usr/local/mariadb/ssl/ca-cert.pem

                        ssl-cert=/usr/local/mariadb/ssl/server-cert.pem

                        ssl-key=/usr/local/mariadb/ssl/server-key.pem    

                        MariaDB [(none)]> show global variables like '%ssl%';

                        +---------------+----------------------------------------+

                        | Variable_name | Value                                  |

                        +---------------+----------------------------------------+

                        | have_openssl  | YES                                    |

                        | have_ssl      | YES                                    |

                        | ssl_ca        | /usr/local/mariadb/ssl/ca-cert.pem     |

                        | ssl_capath    |                                        |

                        | ssl_cert      | /usr/local/mariadb/ssl/server-cert.pem |

                        | ssl_cipher    |                                        |

                        | ssl_crl       |                                        |

                        | ssl_crlpath   |                                        |

                        | ssl_key       | /usr/local/mariadb/ssl/server-key.pem  |

                        +---------------+----------------------------------------+

                        授权重读授权表测试连接

                        grant REPLICATION SLAVE,REPLICATION CLIENT on *.* to 'mysql'@'192.168.1.%' IDENTIFIED BY 'mysql' REQUIRE SSL;

                        flush privileges;

                        mysql -umysql -pmysql -h192.168.1.200 --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem 

                        连上去后\s查看                        

                        mysql  Ver 15.1 Distrib 10.0.23-MariaDB, for Linux (x86_64) using readline 5.1

                        Connection id:7

                        Current database:

                        Current user:[email protected]

                        SSL:Cipher in use is DHE-RSA-AES256-GCM-SHA384

                        Current pager:stdout

                        Using outfile:''

                        Using delimiter:;

                        Server:MariaDB

                        Server version:10.0.23-MariaDB-log Source distribution

                        Protocol version:10

                        Connection:192.168.1.200 via TCP/IP

                        Server characterset:utf8

                        Db     characterset:utf8

                        Client characterset:utf8

                        Conn.  characterset:utf8

                        TCP port:3306

                        Uptime:14 min 45 sec

                    主从复制:

                        开启从服务器的中继日志,更改serverID,关掉从的二进制日志(可选)如果是级联复制那么该二进制日志必须开启。                        

                         server-id       = 11    serverID

                         skip_slave_start 跳过重启后自动开启复制线程

                         relay_log       = /mariadb/relay-log/relay-bin 中继日志                                    ssl-ca=/usr/local/mariadb/ssl/ca-cert.pem 根证书

                         ssl-cert=/usr/local/mariadb/ssl/client-cert.pem 证书

                         ssl-key=/usr/local/mariadb/ssl/client-key.pem 秘钥

                    查看主服务器当前使用的日志文件,及偏移量                        

                         MariaDB [(none)]> show master status\G                        

                         *************************** 1. row ***************************                                            File: master-bin.000006

                                    Position: 1128

                    将从服务器只想主服务器前提指向之前需要确保两个数据库本身数据一致,不一致的话可以将主服务器备份在从服务器上恢复。                    

                        CHANGE MASTER TO MASTER_HOST='192.168.1.200', MASTER_USER='mysql', MASTER_PASSWORD='mysql', MASTER_LOG_FILE='master-bin.000006', MASTER_LOG_POS=1128, MASTER_SSL=1, MASTER_SSL_CA = '/usr/local/mariadb/ssl/ca-cert.pem', MASTER_SSL_CERT = '/usr/local/mariadb/ssl/client-cert.pem', MASTER_SSL_KEY = '/usr/local/mariadb/ssl/client-key.pem';

                   然后开启复制线程并查看状态,START SLAVE [IO_THREAD|SQL_THREAD] IO_THREAD读取主服务器二进制文件写入从中继日志SQL_THREAD读取中继日志并执行

                    start slave;                    

                    show slave status\G 

                    验证在主服务器创建一个数据库看看从服务器有没有。基本上结束

                        

                    半同步复制:主服务器完成一个事物时需要等待从服务器中的某一个完成了该事物后才返回结果,注:只需要等待其中一个,所以称为半同步 

                    安装插件启用参数

                    ls /usr/local/mariadb/lib/plugin/ semisync_master.so  

                    主                

                    INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

                    show global variables like '%semi%';

                    rpl_semi_sync_master_wait_no_slave :是否允许master 每个事物提交后都要等待slave的receipt信号。默认为on ,每一个事务都会等待,如果slave当掉后,当slave追赶上master的日志时,可以自动的切换为半同步方式,如果为off,则slave追赶上后,也不会采用半同步的方式复制了,需要手工配置。

                    set global rpl_semi_sync_master_enabled=1;开启半同步复制

                    set global rpl_semi_sync_master_timeout=1000;设置超时时间如果第一次超时下一次直接跳过从服务器

                    rpl_semi_sync_master_trace_level 监控等级:

                    从

                    INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';安装插件从

                    show global variables like '%semi%';

                    set global rpl_semi_sync_slave_enabled=1;开启从服务半同步复制

                    stop slave io_thread; 关闭Io线程

                    start slave io_thread; 启动io线程

                    在主服务器

                    show global status like '%semi%';

                    

                    MariaDB [(none)]> show global status like '%semi%';

                    +--------------------------------------------+-------+

                    | Variable_name                              | Value |

                    +--------------------------------------------+-------+

                    | Rpl_semi_sync_master_clients               | 1     |  #记录支持半同步的slave的个数

                    | Rpl_semi_sync_master_net_avg_wait_time     | 0     |  #master 等待slave回复的平均等待时间,单位微秒

                    | Rpl_semi_sync_master_net_wait_time         | 0     |  #master 总的等待时间

                    | Rpl_semi_sync_master_net_waits             | 0     |  #master 等待slave回复的的总的等待次数

                    | Rpl_semi_sync_master_no_times              | 0     |  #master 关闭半同步复制的次数

                    | Rpl_semi_sync_master_no_tx                 | 0     |  #master 没有收到slave的回复而提交的次数

                    | Rpl_semi_sync_master_status                | ON    |  #标记master现在是否是半同步复制状态

                    | Rpl_semi_sync_master_timefunc_failures     | 0     |  #时间函数未正常工作的次数

                    | Rpl_semi_sync_master_tx_avg_wait_time      | 0     |  #开启Semi-sync,事务返回需要等待的平均时间

                    | 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     |  #当前有多少个session 因为slave 的回复而造成等待

                    | Rpl_semi_sync_master_yes_tx                | 0     |  #master 成功接收到slave的回复的次数

                    +--------------------------------------------+-------+

                    双主模式;

                    原理就是两台互为主从,很显然需要都开启中继日志和二进制日志,并且需要注意的是mariadb中的一个服务器函数auto-increment需要调整,以及要有一个具有复制权限的账号,然后修改配置文件互指对方为主就可以 

                    授权参照SSL里的授权 

                        # 主服务器A上                  

                        [mysqld]

server-id = 10

log-bin = mysql-bin

relay-log = relay-mysql

auto-increment-offset = 1

auto-increment-increment = 2

skip_slave_start 开启服务时不自动开启slave复制线程

# 主服务器B上

[mysqld]

server-id = 20

log-bin = mysql-bin

relay-log = relay-mysql

auto-increment-increment = 2 # 步长

auto-increment-offset = 2 # 起始值

    重启后互指 需要提前查看对方服务器的二进制日志文件和偏移量show master status\G 参照主从里面的change master to如果没有配置ssl去掉ssl选项即可。

                    主从的问题:当两个用户在对同一个表修改时,这时就会出现数据的不一致性。

                    多源模式:常用来收集数据 如果多个主中有数据库名相同的就会出现数据不一致                    

                    和主从类似只需要从服务同时制定多个主服务器,只是使用的命令有一些变化,其它一致                    

                    CHANGE MASTER ['connection_name'] TO MASTER_HOST = 'host_name',MASTER_USER = 'user_name',MASTER_PASSWORD = 'password',MASTER_LOG_FILE = 'master_log_name',MASTER_LOG_POS = master_log_pos

     SHOW SLAVE ['connection_name'] STATUS

     SHOW ALL SLAVES STATUS

     START SLAVE ['connection_name'...]]

     START ALL SLAVES ...

     STOP SLAVE ['connection_name'] ...

     STOP ALL SLAVES ...

                    2个安全变量                     

                    sync_binlog=1 or N 将二进制日志内容同步到磁盘0表示有服务器自己判断性能最好,1表示每次有事务提交都会同步到磁盘(性能最差最安全),N表示N次事务后同步                                      

                    innodb_flush_log_at_trx_commit = 1

    innodb_flush_log_at_trx_commit = 0,Innodb 中的Log Thread 没隔1 秒钟会将log buffer中的数据写入到文件,同时还会通知文件系统进行文件同步的flush 操作,保证数据确实已经写入到磁盘上面的物理文件。但是,每次事务的结束(commit 或者是rollback)并不会触发Log Thread 将log buffer 中的数据写入文件。所以,当设置为0 的时候,当MySQL Crash 和OS Crash 或者主机断电之后,最极端的情况是丢失1 秒时间的数据变更。

    innodb_flush_log_at_trx_commit = 1,这也是Innodb 的默认设置。我们每次事务的结束都会触发Log Thread 将log buffer 中的数据写入文件并通知文件系统同步文件。这个设置是最安全的设置,能够保证不论是MySQL Crash 还是OS Crash 或者是主机断电都不会丢失任何已经提交的数据。

    innodb_flush_log_at_trx_commit = 2,当我们设置为2 的时候,Log Thread 会在我们每次事务结束的时候将数据写入事务日志,但是这里的写入仅仅是调用了文件系统的文件写入操作。而我们的文件系统都是有缓存机制的,所以Log Thread 的这个写入并不能保证内容真的已经写入到物理磁盘上面完成持久化的动作。文件系统什么时候会将缓存中的这个数据同步到物理磁盘文件Log Thread 就完全不知道了。所以,当设置为2 的时候,MySQL Crash 并不会造成数据的丢失,但是OS Crash 或者是主机断电后可能丢失的数据量就完全控制在文件系统上了。各种文件系统对于自己缓存的刷新机制各不一样,大家可以自行参阅相关的手册。