MariaDB是MySQL的一个主要的开源分支。由于oracle收购MySQL之后,担心将其闭源,MySQL之父monty主导开发了MariaDB,用自己小女儿的名字命名。Maria DB完全兼容MySQL,可以轻松切换。在存储引擎方面,MariaDB 10.1及之前版本均使用Percona XtraDB做为默认引擎,从10.2开始使用MySQL官方的InnoDB做为默认引擎。XtraDB是 InnoDB 存储引擎的增强版,用来更好地发挥最新的计算机硬件系统性能,同时还包含一些在高性能环境下的新特性。在MySQL 5.1和5.5版本上有很好的性能表现。但是后来MySQL官方几乎把所有的优秀特性都实现了,所以MariaDB 10.2开始又切换到了InnoDB。在新功能特性方面,MariaDB优化了子查询,增加了多源复制(基于表的并行复制),Galera Cluster集群等。虽然MySQL 5.7以后也增加了相关特性,比如基于表的并行复制,但MySQL社区版毕竟一个阉割版本,企业版又是闭源收费的。此外MariaDB在高并发环境下稳定性比MySQL好很多,压测的时候随着连接数的增大性能曲线不会大幅抖动,很平稳。
安装MariaDB
我是在虚拟机在中安装了centos6.9,数据库版本选择是mariadb10.2。通过yum的方式进行安装,在线查找安装源:在线源信息
新建MariaDB.repo文件:
选择自己将安装版本,将源信息复制到MariaDB.repo中。在安装的过程中可能因为网络或者缺少库文件而造成安装失败。在这里推荐大家使用国内的镜像:http://mirrors.ustc.edu.cn/mariadb/yum/。选择合适的操作系统合适数据库版本。
# MariaDB 10.2 CentOS repository list -created 2018-06-22 02:15 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://mirrors.ustc.edu.cn/mariadb/yum/10.2/centos/6.9/x86_64
gpgkey=http://mirrors.ustc.edu.cn/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck=1
(↑国内源信息内容)
安装MariaDB:sudo yum install MariaDB-server MariaDB-client
启动MariaDB:service mysql start
开机启动:chkconfig mysql on
初始设置MariaDB:mysql_secure_installation
设置一下root用户密码,其他设置全部按回车就可以了。
通过客户端访问数据库:mysql -u root -p
接下来设置权限,允许远程机器通过root用户访问数据库。
GRANT ALL PRIVILEGES ON *.* to 'root'@'%' identified by 'root';(可以指定特定IP访问,如果是%表示任意IP访问)
别忘了刷新权限:flush privileges;
如果防火墙处于开启状态,先关闭掉。service iptables stop
MariaDB主从同步原理
先说一下,数据库主从同步复制能解决的问题,我能想到就是数据备份和负载均衡。数据备份自然不用说,负载均衡读写分离的前提就是主从同步复制,然后通过数据库代理(比如:mycat、mysql router等)分流应用的读写请求,降低数据库的压力,提高访问性能。至于高可用和容错性,我认为主从单向同步无法解决。首先,如果主库宕机,数据库代理会把从库也变为不可用,或者只能读不能写。而且,写操作只能在主库上进行,如果在从库也不小心写入操作,那么就会造成数据不一致或者同步状态异常等问题。
a) MariaDB的数据变化会记录在二进制日志中(bing log),我们需要在主库的配置文件中开启这个日志功能。
b) 从库有一个I/O线程会监听主库的二进制日志改变事件,把事件内容记录到中继日志(Relay log)中。我们需要在从库中开启这个日志功能。
c) 从库的SQL线程会从中继日志中读取事件,并重放事件更新到从库中。
Binglog的复制类型分为三种:
基于sql语句的复制(statement),每一条会修改数据的 SQL 都会记录到 master 的 bin-log 中。slave 在复制的时候 SQL 进程会解析成和原来 master 端执行过的相同的 SQL 再次执行。
基于行内容的复制(row),日志中会记录成每一行数据被修改的形式,然后在 slave 端再对相同的数据进行修改。
混合复制模式(mixed),就是前两种模式的结合。在 Mixed 模式下,MySQL 会根据执行的每一条具体的 SQL 语句来区分对待记录的日志形式,也就是在 statement 和 row 之间选择一种。
statement的方式产生的binglog日志文件量小,节省了I/O和存储资源。但在执行一些特定函数比如now()、 last_insert_id()在主库和从库上会产生不一样的结果。而且复制的时候相对于row的模式会产生更多的行级锁表。row的方式任何情况都可以被复制,这对复制来说是最安全可靠的。最大的一个问题是产生的日志量太大,因为要记录数据改动的内容。尤其是对一个大表执行了alert tbale产生的日志量是惊人的。新版的MySQL和MariaDB对row模式进行的优化,并不是所有的修改都会以 row 模式来记录,比如遇到表结构变更的时候就会以 statement 模式来记录。
默认情况下复制都是异步进行的,这样的性能最佳。但问题在于,异步情况下,如果从库没有接受到主库发过来的二级制事件日志,而且主库并没有感知到这个情况的发生,这样就会出现主从数据不一致的情况发生,造成数据丢失。为了解决异步复制数据丢失的问题,从MySQL5.5开始的数据库引入了半同步的复制模式。该模式下从库接受到主库的日志信息,并写入到自己的中继日志中,然后会给主库一个反馈,主库接受到这个反馈才会告知当前会话操作完成。主库确认从库反馈有一个超时时间(rpl_semi_sync_master_timeout),默认是10秒。如果超出这个时间,从还没有反馈的话,就会切换到异步模式,不再等待slave从库。如果主库再次探测到slave从库恢复,则会自动回到半同步复制模式。
注:半同步复制模式必须在主从节点同时启用,否则主节点默认使用异步复制模式。
MariaDB主从同步复制配置
本文采用的半同步复制模式。首先查找MariaDB的安装包中是否存在半同步复制插件:find / -name semisync*
在主库中安装插件:install plugin rpl_semi_sync_master soname 'semisync_master.so';
开启主库半同步复制:SET GLOBAL rpl_semi_sync_master_enabled =1;
在从库中安装插件:install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
开启从半同步复制:SET GLOBAL rpl_semi_sync_slave_enabled =1;
配置主库的server.cnf:vi /etc/my.cnf.d/server.cnf
skip_name_resolve = ON
innodb_file_per_table = ON
server-id = 10001 #主库唯一标识
log-bin=master-bin #开启二级制日志
log-bin-index=master-bin.index
rpl_semi_sync_master_enabled=1 #开启半同步复制,需要先安装插件
rpl_semi_sync_master_timeout=10000 #主库半同步复制模式等待从库反回信息的超时时间
expire_logs_days = 5 #日志的有效天数
binlog_format = row #基于行内容的复制
binlog_row_image = minimal #行内容复制时,只保存修改过列。
重启主库:service mysql restart
查看主库配置:show variables like 'rpl%';
rpl_semi_sync_master_enabled=ON 表示在master主库上开启半同步复制模式。
配置从库的server.cnf:vi /etc/my.cnf.d/server.cnf
skip_name_resolve = ON
innodb_file_per_table = ON
server_id=10002 #从库唯一标识
relay_log_index = slave_relay_bin.index
relay_log = slave_relay_bin #开启中继日志
rpl_semi_sync_slave_enabled =1 #开启半同步复制,需要先安装插件
重启从库,并查看从库配置:show variables like 'rpl%';
rpl_semi_sync_slave_enabled=ON 表示在slave从库上开启半同步复制模式。
查看主库master状态:show master status;
记录File和Position,然后在主库创建同步复制用户:GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO 'repluser'@'%' IDENTIFIED BY '123456';
登录到从库中执行下面的操作:
CHANGE MASTER TOMASTER_HOST='192.168.1.56',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=621;
启动从库同步状态:start slave;
查看从库同步状态:show slave status \G
只要Slave_IO_Running和Slave_SQL_Runing这两个参数为YES,证明主从同步已经开始正常工作了。
异常情况
Slave_IO_Running为No的情况一般是网络问题或者读取主机binglog文件位置不对。重新查看主库状态,记录FIle和Position。然后stop slave;修改从库指向的File和Position:
CHANGE MASTER TOMASTER_LOG_FILE='master-bin.000004', MASTER_LOG_POS=621;
启动同步:start slave;
Slave_SQL_Running为NO的情况是有可能在主从同步之前没有把主库中完整数据导入到从库中,这时候如果删除一个从库中没有的数据,会造成Slave_SQL_Running状态不可用。
同样先停止同步:stop slave;
set global sql_slave_skip_counter=1; //从库直接跳过
启动同步:start slave;
不管遇到同步的什么问题,我们都可以先通过last_errno和last_error信息来进行定位。
我们可以通过在从库配置文件中设置:read_only=on,或则在从库客户端运行:set global read_only=1;来开启从库只读模式,防止在从库中写入数据。这种方式不影响主从复制,只是禁止用户在从库上写操作。但是对于super权限(ALL PRIVILEGES)的用户这个设置是无效的,比如root用户,所以我们要保证拥有super权限的用户只能本机访问。如果之前授权了root用户远程访问的权限,那么先撤销授权。修改或删除myql库中user表的对应数据。创建一个新的用户并授予增删查改的权限:GRANT select,insert,update,delete ON *.* to 'myuser'@'%' identified by '123456';
这时候我们用这个myuser远程登录到从库,虽然授予了该用户写的权限,但执行写操作的时候就会提示从库是只读的。这样就可以保证从库不会被意外写入造成同步数据不一致。
如果想要禁止super权限的用户也不能写入,需要设置全局锁:flush tables with read lock;但是这样会造成从库复制操作也无法进行。
一般会在主库进行数据迁移的时候执行:flush tables with read lock;set global read_only=1;禁止所有用户修改数据库,等待数据迁移完成后,通过unlock tables;set global read_only=0;恢复主库的写入功能。
至此,关于MariaDB的主从同步就描述完成。在我学习的过程中参考了很多来自网络的相关资料,由于来源很多,就不一一列举了,感谢大家的分享。我也希望我的这个总结能对其他人有一点帮助。还有就是认真写一点东西真的很耗时间,但这些时间上的投入我认为是很有必要的。