Mariadb GTID
全局事务ID(Global transaction ID,GTID)为每个Event Group (就是一系列 Event 组成的一个原子单元,要么一起提交要么都无法提交)引入了一个标识,因此 GTID 是标识“事务”的最佳方式(尽管 Event 里面还包含一些非事务的DML语句和DDL,它们可以作为一个单独的 Event Group )。每当一个 Event Group 从Master复制到Slave时,它的 GTID 也通过 GTID Event 被传到Slave。因为每个GTID 在整个复制拓扑结构中都是一个唯一标志,所以这使得在不同的实例之间识别相同的 Binlog Events 非常简单,然而在有 GTID 之前,想做到这点是很困难的。MariaDB 从 10.0.2 开始提供 GTID 支持,但是 MariaDB 的 GTID 与 MySQL 的 GTID 在实现原理上并不相同,因为 MariaDB 支持像多源复制啊、多主复制等官方暂时还没考虑的复制模型。 优势 使用 GTID 有两个主要的优势: 1. 在级联复制、一主多从等复杂的复制场景下,可以更简单地将一个Slave的复制修改到另一个Master上,而不用人工去寻找复制的起始位点。从5.0一路走来的同学应该很能理解这种痛苦。 这是因为Slave会保存最后一个执行的 Event Group 的 GTID,因此可以通过这个 GTID 很容易地在新Master上找到相应的复制起点。而在使用 Binlog File 和 Binlog Pos 的时代,这是很难办到的。 2. Slave的状态是Crash-Safe 的。 Slave的执行状态(最后一个执行的 GTID)被记录在 mysql.gtid_slave_pos 系统表中。如果这张表使用的是事务引擎(例如InnoDB,默认就是),那么修改用户表的数据和修改Slave状态的系统表这两个操作在就可以放在一个事务中完成,这就保证了Slave状态是 Crash-Safe 的,如果Slave崩溃了,那么 Crash Recovery 就可以在重启的时候把用户数据表和Slave状态系统表恢复到一个一致的位点。而在非 GTID 复制的旧版本中,这也是做不到的,Slave状态只是简单的存放在 relay-log.info 文件中(MySQL是可以把 Binlog File 和 Binlog Pos 也存在 slave_relay_log_info 和 slave_master_info 系统表中),而且需要靠不断的 fsync() 调用才能同步到磁盘上,一旦宕机很可能导致Slave状态跟实际不一致(但是也只有事务引擎的DML能保证一致,非事务引擎和DDL本身就不是Crash-Safe的)。 基于这两个优势,通常我们都建议使用GTID复制。并且传统的基于Binlog文件位置的复制方式,和 GTID 的复制方式,在 MariaDB 中是可以相互之间平滑的切换的。 每个GTID,都包含三个数字部分,分别用’-‘号隔开,例如: 0-1-10 第一个数字’0’是Domain ID,这是一个32位的无符号整型。 第二个数字’1’是Server ID,这跟传统的主备复制中Server ID 的含义是一样的,也是一个32位无符号整型。因此在一个复制拓扑中每个实例的Server ID必须是唯一的。 第三个数字是序列号(SequenceNumber)。这是一个64位的无符号整型。每个新产生的 Event Group 记录到Binlog时都会新生成一个单调递增的序列号。 这个规则使得(server_id, sequence_number) 总是唯一的,因此GTID也是全局唯一的。
配置mariadb yum源 # vim /etc/yum.repos.d/MariaDB10.repo [mariadb] name = MariaDB gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck=1
安装mariadb # yum install -y MariaDB-server MariaDB-client tcl bzip2 lsof
创建mariadb 数据和日志目录 # mkdir -p /data/mysql/330{6,7} # mkdir -p /back/binlog/330{6,7} # chown -R mysql.mysql /data/mysql # chown -R mysql.mysql /back/binlog
创建多实例 # mysql_install_db --datadir=/data/mysql/3306 --user=mysql # mysql_install_db --datadir=/data/mysql/3307 --user=mysql
Master3306配置文件,此处的配置是基础配置,优化参数自行添加 # vim /data/mysql/3306/my.cnf [mysqld] datadir=/data/mysql/3306 port=3306 socket=/data/mysql/3306/mysql.sock slow-query-log=1 #开启慢查询日志 slow-query-log-file=/back/binlog/3306/mysql-slow.log #日志存储位置 long_query_time=1 #执行超过多长时间的sql会记录下来 binlog_format=ROW #binlog日志格式 skip-name-resolve #跳过域名解析 server-id=1 log-bin=/back/binlog/3306/master-bin log-bin-index=/back/binlog/3306/master-bin.index log-error=/back/binlog/3306/mysql-err.log
master-info-repository=TABLE relay-log-info-repository=TABLE #此两项为打开从服务器崩溃二进制日志功能,信息记录在事物表而不是保存在文件 sync-master-info=1 #值为1确保信息不会丢失 slave-parallel-threads=2 #同时启动多少个复制线程,最多与要复制的数据库数量相等即可 binlog-checksum=CRC32 #效验码 master-verify-checksum=1 #启动主服务器效验 slave-sql-verify-checksum=1 #启动从服务器效验 binlog-rows-query-log-events=1 #用于在二进制日志详细记录事件相关的信息,可降低故障排除的复杂度;
[mysqld_safe] pid-file=/data/mysql/3306/mysql.pid
[client-server] socket=/data/mysql/3306/mysql.sock
Master 3307配置文件 # vim /data/mysql/3307/my.cnf [mysqld] datadir=/data/mysql/3307 port=3307 socket=/data/mysql/3307/mysql.sock slow-query-log=1 #开启慢查询日志 slow-query-log-file=/back/binlog/3307/mysql-slow.log #日志存储位置 long_query_time=1 #执行超过多长时间的sql会记录下来 binlog_format=ROW #binlog日志格式 skip-name-resolve #跳过域名解析 server-id=1 log-bin=/back/binlog/3307/master-bin log-bin-index=/back/binlog/3307/master-bin.index log-error=/back/binlog/3307/mysql-err.log
master-info-repository=TABLE relay-log-info-repository=TABLE #此两项为打开从服务器崩溃二进制日志功能,信息记录在事物表而不是保存在文件 sync-master-info=1 #值为1确保信息不会丢失 slave-parallel-threads=2 #同时启动多少个复制线程,最多与要复制的数据库数量相等即可 binlog-checksum=CRC32 #效验码 master-verify-checksum=1 #启动主服务器效验 slave-sql-verify-checksum=1 #启动从服务器效验 binlog-rows-query-log-events=1 #用于在二进制日志详细记录事件相关的信息,可降低故障排除的复杂度;
[mysqld_safe] pid-file=/data/mysql/3307/mysql.pid
[client-server] socket=/data/mysql/3307/mysql.sock
Slave 3306配置文件 # vim /data/mysql/3306/my.cnf [mysqld] datadir=/data/mysql/3306 port=3306 socket=/data/mysql/3306/mysql.sock slow-query-log=1 #开启慢查询日志 slow-query-log-file=/back/binlog/3306/mysql-slow.log #日志存储位置 long_query_time=1 #执行超过多长时间的sql会记录下来 binlog_format=ROW #binlog日志格式 skip-name-resolve #跳过域名解析 server-id=2 log-bin=/back/binlog/3306/master-bin log-bin-index=/back/binlog/3306/master-bin.index log-error=/back/binlog/3306/mysql-err.log
master-info-repository=TABLE relay-log-info-repository=TABLE #此两项为打开从服务器崩溃二进制日志功能,信息记录在事物表而不是保存在文件 sync-master-info=1 #值为1确保信息不会丢失 slave-parallel-threads=2 #同时启动多少个复制线程,最多与要复制的数据库数量相等即可 binlog-checksum=CRC32 #效验码 master-verify-checksum=1 #启动主服务器效验 slave-sql-verify-checksum=1 #启动从服务器效验 binlog-rows-query-log-events=1 #用于在二进制日志详细记录事件相关的信息,可降低故障排除的复杂度;
[mysqld_safe] pid-file=/data/mysql/3306/mysql.pid
[client-server] socket=/data/mysql/3306/mysql.sock
Slave 3307配置文件 # vim /data/mysql/3307/my.cnf [mysqld] datadir=/data/mysql/3307 port=3307 socket=/data/mysql/3307/mysql.sock slow-query-log=1 #开启慢查询日志 slow-query-log-file=/back/binlog/3307/mysql-slow.log #日志存储位置 long_query_time=1 #执行超过多长时间的sql会记录下来 binlog_format=ROW #binlog日志格式 skip-name-resolve #跳过域名解析 server-id=2 log-bin=/back/binlog/3307/master-bin log-bin-index=/back/binlog/3307/master-bin.index log-error=/back/binlog/3307/mysql-err.log
master-info-repository=TABLE relay-log-info-repository=TABLE #此两项为打开从服务器崩溃二进制日志功能,信息记录在事物表而不是保存在文件 sync-master-info=1 #值为1确保信息不会丢失 slave-parallel-threads=2 #同时启动多少个复制线程,最多与要复制的数据库数量相等即可 binlog-checksum=CRC32 #效验码 master-verify-checksum=1 #启动主服务器效验 slave-sql-verify-checksum=1 #启动从服务器效验 binlog-rows-query-log-events=1 #用于在二进制日志详细记录事件相关的信息,可降低故障排除的复杂度;
[mysqld_safe] pid-file=/data/mysql/3307/mysql.pid
[client-server] socket=/data/mysql/3307/mysql.sock
3306启动脚本 # vim /etc/init.d/mysql3306 #init port=3306 mysql_user="root" mysql_pwd="123456" CmdPath="/usr/bin"
#startup function function_start_mysql() { printf "Starting MySQL...\n" /bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/mysql/3306/my.cnf 2>&1 > /dev/null & }
#stop function function_stop_mysql() { printf "Stoping MySQL...\n" ${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /data/mysql/3306/mysql.sock shutdown }
#restart function function_restart_mysql() { printf "Restarting MySQL...\n" function_stop_mysql sleep 2 function_start_mysql }
case $1 in start) function_start_mysql ;; stop) function_stop_mysql ;; restart) function_restart_mysql ;; *) printf "Usage: /data/${port}/mysql {start|stop|restart}\n" esac
3307启动脚本 # vim /etc/init.d/mysql3307 #init port=3307 mysql_user="root" mysql_pwd="123456" CmdPath="/usr/bin"
#startup function function_start_mysql() { printf "Starting MySQL...\n" /bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/mysql/3307/my.cnf 2>&1 > /dev/null & }
#stop function function_stop_mysql() { printf "Stoping MySQL...\n" ${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /data/mysql/3307/mysql.sock shutdown }
#restart function function_restart_mysql() { printf "Restarting MySQL...\n" function_stop_mysql sleep 2 function_start_mysql }
case $1 in start) function_start_mysql ;; stop) function_stop_mysql ;; restart) function_restart_mysql ;; *) printf "Usage: /data/${port}/mysql {start|stop|restart}\n" esac
启动mariadb # chown -R mysql.mysql /data/mysql # chmod +x /etc/init.d/mysql330{6,7} # /etc/init.d/mysql3306 start # /etc/init.d/mysql3307 start
设置root密码 # mysqladmin -uroot password "123456" -S /data/mysql/3306/mysql.sock # mysqladmin -uroot password "123456" -S /data/mysql/3307/mysql.sock
添加开机启动 # vim /etc/rc.d/rc.local /etc/init.d/mysql3306 start /etc/init.d/mysql3307 start # chmod +x /etc/rc.local
安装jemalloc # tar -xjf jemalloc-4.2.0.tar.bz2 # cd jemalloc-4.2.0 # ./configure --prefix=/usr/local/jemalloc --libdir=/usr/local/lib # make && make install # make clean # echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf # /sbin/ldconfig
配置mariadb使用jemalloc # sed -i 's@executing mysqld_safe@executing mysqld_safe\nexport LD_PRELOAD=/usr/local/lib/libjemalloc.so@' /usr/bin/mysqld_safe # lsof -n | grep jemalloc
配置GTID模式的主从 Master 3306创建主从同步用户 # mysql -uroot -p123456 -S /data/mysql/3306/mysql.sock >grant replication slave,replication client on *.* to 'rep'@'192.168.1.%' identified by '123456'; >flush privileges; 导出数据库,将导出的数据放到从库上 # mysqldump -uroot -p123456 -S /data/mysql/3306/mysql.sock -A > dataall-3306.sql
Master 3307创建主从同步用户 # mysql -uroot -p123456 -S /data/mysql/3307/mysql.sock >grant replication slave,replication client on *.* to 'rep'@'192.168.1.%' identified by '123456'; >flush privileges; 导出数据库,将导出的数据放到从库上 # mysqldump -uroot -p123456 -S /data/mysql/3307/mysql.sock -A > dataall-3307.sql
Slave 3306开启主从同步 # mysql -uroot -p123456 -S /data/mysql/3306/mysql.sock < dataall-3306.sql # mysql -uroot -p123456 -S /data/mysql/3306/mysql.sock >CHANGE MASTER TO master_host="192.168.1.1", master_port=3306, master_user="rep",MASTER_PASSWORD='123456',master_use_gtid=slave_pos; >start slave; >show slave status\G;
Slave 3307开启主从同步 # mysql -uroot -p123456 -S /data/mysql/3307/mysql.sock < dataall-3307.sql # mysql -uroot -p123456 -S /data/mysql/3307/mysql.sock >CHANGE MASTER TO master_host="192.168.1.1", master_port=3307, master_user="rep",MASTER_PASSWORD='123456',master_use_gtid=slave_pos; >start slave; >show slave status\G;
在数据库重新初始化时,可能会出现输入密码无法登陆问题,需要重新设置密码 # vim my.cnf skip-grant-tables # /etc/init.d/mysql3307 start # mysql -uroot -p -S /data/mysql/3307/mysql.sock >use mysql >update user set password = password("123456") where user = "root"; 删除my.cnf中的skip-grant-tables,重启mysql就可以了
mysql锁定所有表 > flush tables with read lock; > unlock tables; 这个命令是全局读锁定,执行了命令之后所有库所有表都被锁定只读,一般都是用在数据库联机备份,这个时候数据库的写操作将被阻塞,读操作顺利进行 mysql锁定单个表 > lock tables tbl_name [AS alias] {read [local] | [low_priority] write} > unlock tables; 这个命令是表级别的锁定,可以定制锁定某一个表,不影响其它表的写操作 这两个锁表语句在执行的时候都需要注意个特点,就是隐式提交的语句,在退出mysql终端的时候都会隐式的执行unlock tables,也就是如果要让表锁定生效就必须一直保持会话
|