在上一篇文章我们说到了在使用二进制日志做主从时候出现的一个典型的报错解决方案,然后在文章结尾提到了使用GTID模式来做mariadb(mysql)主从,这一篇文章主要讲述一下如何使用GTID来搭建主从!不过我们首先要了解一下什么是GTID!
什么是GTID?
GTID就是全局事务ID(global transaction identifier ),他是由服务器的uuid 全局唯一标示,是由128位的随机符组成。GTID在主从结构中是唯一的,每一个 GTID 代表一个数据库事务。官方在MySQL在5.6后才加入该功能,那么这样算要在mariadb10以上才有该功能。GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。自从有了GTID编码之后每一个二进制日志当中在每一个事物的首部都会写上gtid 标记,因此gtid使得追踪和比较复制事物变得非常简单而且能够实现从崩溃中快速恢复,尤其是innodb 引擎要想实现高可用功能必须要借助于gtid来实现。
使用GTID来构建mariadb主从有什么好处?
首先GTID构建形式也需要使用到mariadb的二进制日志读取方能进行更新,但是比原先的手动查看二进制日志好很多,免去了如果手动查看错误回遇到上一篇文章遇到的报错信息。通过GTID,可以在自动切换时对一些复杂的复制拓扑很方便的提升新主库及新备库,而不用去查看什么二进制日志这种让人头皮发麻的事情了。
使用GTID构建mariadb主从的限制性:
- 事务中的更新包含非事务性存储引擎,这可能导致多个GTID分配给同一个事务。
- create table…select语句不被支持,因为该语句会被拆分成create table 和insert两个事务,并且这个两个事务被分配了同一个GTID,这会导致insert被备库忽略掉。
- 不支持CREATE/DROP临时表操作
综上所示看上去有风险,但是 MySQL官方(mariadb也可以使用)也提供了一个选项disable-gtid-unsafe-statements以禁止这些语句的执行,注意:高版本才行!
如何构建mariadb基于GTID搭建主从模式?
其实给予理论还是比较长的,有时间的话可以看看mariadb的官方文档。配置相对简单mariadb和mysql配置方式都类似,但是如果你想要将mariadb和mysql两个不同数据库作为GTID主从那可不行,两者计算GTID绝对是不兼容的!!!切记、切记。
第一步安装mariadb:
我是用mariadb的10.1.16的版本作为主从复制,并且选用两台虚拟机作为它们的实验环境。关于安装的话我这边就简略写写想要查看详细的看这里!
先上拓扑:一共两台机器,分别为172.16.1.60与172.16.1.70。其中1.60主机位mariadb master 而 1.70作为mariadb slave .
mariadb二进制包安装:
#添加用户和组 [root@localhost ~] groupadd -r -g 300 mysql [root@localhost ~] useradd -r -g 300 -u 300 mysql [root@localhost ~] mkdir /opt/sqldata [root@localhost ~] chown mysql:mysql /opt/sqldata/ [root@localhost ~] tar -xf mariadb-10.1.16-linux-x86_64.tar.gz -C /opt/ [root@localhost ~] cd /opt #添加软链接 [root@localhost opt] ln -s mariadb-10.1.16-linux-x86_64/ mysql [root@localhost mysql] scripts/mysql_install_db --datadir=/opt/sqldata --user=mysql #复制启动脚本别忘了看下面需要修改随后再执行收入启动脚本命令 [root@localhost mysql] cp support-files/mysql.server /etc/rc.d/init.d/mysqld [root@localhost mysql] chmod +x /etc/rc.d/init.d/mysqld [root@localhost mysql] systemctl enable mysqld mysqld.service is not a native service, redirecting to /sbin/chkconfig. Executing /sbin/chkconfig mysqld on #拷贝配置文件 [root@localhost mysql] cp support-files/my-large.cnf /etc/my.cnf #写一个环境变量脚本 [root@localhost mysql] vim /etc/profile.d/mysql.sh export PATH=/opt/mysql/bin:$PATH [root@localhost mysql] source /etc/profile.d/mysql.sh
接下来有好多地方要改,首先是配置文件,随后就是启动脚本!
启动脚本mysqld修改内容:
在一开始的地方有basedir=和datadir=添加好程序路径和数据库路径!basedir=”/opt/mysql” datadir=”/opt/sqldata”
这样就算将mariadb安装完毕了,别忘了还得安装从服务器。如果觉得麻烦可以搞ansible进行自动化部署,弄好以后可以不启动关于my.cnf的配置文件我下面来说!
mariadb基于GTID方式进行主从搭建:
首先必须要先弄配置文件,主从可能有点不一样。
主服务器配置文件:
\client\ #\代表[]这边由于代码问题所以转义了! port = 3306 socket = /tmp/mysql.sock # The MariaDB server \mysqld\ #这下面的没啥好说和举例的配置文件相同 port = 3306 socket = /tmp/mysql.sock skip-external-locking key_buffer_size = 256M max_allowed_packet = 1M table_open_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size= 16M # Try number of CPU's*2 for thread_concurrency thread_concurrency = 8 datadir = /opt/sqldata/ #写明data位置 innodb_file_per_table = on skip_name_resolve = on #禁止检查主机名 symbolic-links=0 # Replication Master Server (default) # binary logging is required for replication log-bin=master-bin #二进制日志存放位置和名字 # binary logging format - mixed recommended binlog_format=ROW #二进制日志格式,默认是mixed建议用ROW #当设置隔离级别为READ-COMMITED必须设置二进制日志格式为ROW, #MySQL官方认为STATEMENT这个已经不再适合继续使用, #但mixed类型在默认的事务隔离级别下,可能会导致主从数据不一致 #所以推荐使用row   server-id = 1 #serverID号,主从必须不同 binlog-row-image = minimal #二进制日志为ROW时的日志级别 report-host = 172.16.1.60 #这个可以不要默认为localhost辅助gtid的 report-port = 3306 #也可以省略默认为3306 #gtid-mode = on #这里重点说说从 MariaDB 10.0.2 开始,GTID 是默认自动打开的。而以前没配置所以要手动设置二进制日志配置到slave端。 #enforce-gtid-consistency = true #都是用于辅助gtid的选项 #log-slave-updates = true #都是用于辅助gtid的选项 #下面两项保证服务器意外宕机时候二进制日志安全的功能 master-info-repository = TABLE relay-log-info-repository = TABLE sync-master-info = 1 #启用之后,使二进制日志在每X次binlog写入后与硬盘进行同步 #下面3个选项是二进制日志缓存大小 binlog_cache_size = 64M max_binlog_size = 1G max_binlog_cache_size = 512M #下面的4个选项是二进制日志校验功能 binlog-checksum = CRC32 slave_allow_batching = 1 master-verify-checksum = 1 slave-sql-verify-checksum = 1 #下面的一个选项可以不用开启,开启后向二进制日志写入调试信息 #binlog-rows-query-log_events = 1 slave-parallel-workers = 3 #多线程复制最多为1024 #最后两个表示启用relaylog的自动修复功能,避免由于网络之类的外因造成日志损坏,主从停止。 relay_log_purge = 1 relay_log_recovery = 1 #后面的选项自己看你们都懂得! \mysqldump\ quick max_allowed_packet = 16M \mysqld_safe\ log-error=/var/log/mariadb/mariadb.log pid-file=/var/run/mariadb/mariadb.pid \mysql\ no-auto-rehash # Remove the next comment character if you are not familiar with SQL #safe-updates #\myisamchk\ #这个配置段完全可以不要谁现在还在用myisamchk呢? #key_buffer_size = 128M #sort_buffer_size = 128M #read_buffer = 2M #write_buffer = 2M \mysqlhotcopy\ interactive-timeout
随后把从服务器配置文件进行改动,这里我就不写全了只写[mysqld]下面的gtid配置选项:
log-bin=slave-bin binlog_format=ROW server-id = 2 binlog-row-image = minimal report-host = 172.16.1.70 report-port = 3306 #gtid-mode = on #enforce-gtid-consistency = true #log-slave-updates = true master-info-repository = TABLE relay-log-info-repository = TABLE sync-master-info = 1 binlog_cache_size = 64M max_binlog_size = 1G max_binlog_cache_size = 512M binlog-checksum = CRC32 slave_allow_batching = 1 master-verify-checksum = 1 slave-sql-verify-checksum = 1 slave-parallel-workers = 3 relay_log_purge = 1 relay_log_recovery = 1
启动主节点并添加复制的账户:
[root@localhost mysql] systemctl start mysqld [root@localhost mysql] mysql MariaDB [(none)]> grant replication slave on *.* to 'copyadmin'@'172.16.%.%' identified by 'admin'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec)
从服务器配置,使用主服务器的账号登陆,并开启slave:
[root@localhost mysql] systemctl start mysqld [root@localhost mysql] mysql #使用刚在master服务器上配置账号进行使用,写好主机、用户、密码、端口、开启gtid即可 MariaDB [(none)]> change master to master_host='172.16.1.60',master_user='copyadmin',master_password='admin',master_port=3306,master_use_gtid=current_pos; Query OK, 0 rows affected (0.03 sec) MariaDB [(none)]> start slave; Query OK, 0 rows affected (0.03 sec) MariaDB [(none)]> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.1.60 Master_User: copyadmin Master_Port: 3306 Connect_Retry: 60 Master_Log_File: master-bin.000006 Read_Master_Log_Pos: 644 Relay_Log_File: localhost-relay-bin.000002 Relay_Log_Pos: 937 Relay_Master_Log_File: master-bin.000006 Slave_IO_Running: Yes Slave_SQL_Running: Yes 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: 644 Relay_Log_Space: 1243 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 Master_SSL_Crl: Master_SSL_Crlpath: Using_Gtid: Current_Pos Gtid_IO_Pos: 0-1-2 Replicate_Do_Domain_Ids: Replicate_Ignore_Domain_Ids: Parallel_Mode: conservative 1 row in set (0.00 sec) 看上面的status自动获得二进制日志无需查看主节点的二进制日志的ID!
验证基于GTID主从复制的结果:
首先上master端创建一个数据库:
MariaDB [(none)]> CREATE DATABASE hello_world; Query OK, 1 row affected (0.00 sec) #随后查看: MariaDB [(none)]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | hello_world | | information_schema | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
然后去从服务器上看看数据库有了没有:
MariaDB [(none)]> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | hello_world | | information_schema | | mysql | | performance_schema | | test | +--------------------+ 5 rows in set (0.00 sec)
好了看来这次给予GTID配置已经完毕。主从复制没有问题还省去了使用show master status; 查看二进制日志名字和ID了!
结语:
以上配置纯属在试验环境中进行配置。不过在生产环境也没问题,只要主服务器开启了二进制日志并且格式为ROW,从服务器只需要在配置文件进行上面的配置,随后别忘了在主服务器上创建一个复制用户随后在从服务器使用用户并开启slave模式即可使用二进制日志进行同步!
当然很多场景下新人们都不会开启二进制日志,那么只能到出数据库随后导入到从服务器中,随后和我上面写的一样一个一个的配置->启动->创建使用复制用户->开启slave模式就行!
不过接下来还有个问题!建立完毕了主从服务器后如何调用从库进行读取?就像两个tomcat应用如何做负载均衡的话题一样。难道让程序员在写程序的时候使用读写分离?如果程序写好了怎么办?重新改?这绝对吧开发部起爆了非把运维部掐死不可!不怕下一期我来讲讲在mariadb(mysql)的中间件,程序员只需改变数据库位置即可做到读写分离!
Comments