Mysql循环复制拓扑实验

1、注意:由于 MySQL 使用了 GUID 标识和管理复制拓扑中的事务,它要求每台服务器的 UUID 必须不 能重复,因此,务必不要使用虚拟机克隆来创建 repl-server2 和 repl-server3。

        UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部份。

        UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。目前最广泛应用的 UUID,即是微软的 Microsoft's Globally Unique Identifiers (GUID),而其他重要的应用,则有 Linux ext2/ext3 档案系统、LUKS 加密分割区、GNOME、KDE、Mac OS X 等等。

UUID格式:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16)

GUID格式:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)

注:x代表0-9或a-f范围内的一个十六进制的数字。

UUID由以下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。

2、配置Linux主机

(1)# ip a s 命令查看是否有动态分配的网卡 IP 地址,使用 # dhclient 命令分配动态 IP

(2)配置网络

修改网卡:

# ip a s
# nmcli connection show
# nmcli connection modify "ens33" ipv4.addresses 192.168.30.121/24 
connection.autoconnect yes
# nmcli connection up "ens33"

设置主机名称,关闭防火墙:

# hostnamectl set-hostname server1
# systemctl stop firewalld
# systemctl disable firewalld
# cat >> /etc/hosts <<EOF
> 192.168.30.121 server1
> 192.168.30.122 server2
> 192.168.30.123 server3
> EOF

使用 reboot 重启 server1,使用静态 IP 连接 server1,使用 ping 测试解析:

# reboot
# ping server1 -c 4  //-c 4:这个选项指定发送4个ICMP数据包来测试server1。

3、安装MySQL服务器

使用虚拟光驱提取MySQL镜像文件到Linux文件系统,勾选“已连接”。

(1)在 server1 创建光盘镜像的挂载目录/mnt/cdrom,然后从挂载目录复制到根目录:

# mkdir /mnt/cdrom
# mount /dev/cdrom /mnt/cdrom
# cp -R /mnt/cdrom/stage /     //-r 或 --recursive:用于复制目录及其所有的子目录和文件,如果要复制目录,需要使用该选项。
# ls -l /stage/

(2)将 MySQL8.0 程序解压到 /opt 目录,再创建到 MySQL 默认安装目录 /usr/local/mysql 的软连接, 访问默认安装目录时就会连接到实际的安装目录,这种方法非常方便后续软件版本升级:

# cd /opt
# tar xf /stage/mysql-commercial-8*.tar.gz
# ln -s /opt/mysql* /usr/local/mysql
# ls /usr/local/mysql/bin

(3)将 mysql 客户机和使用程序的路径添加到 PATH 系统环境变量中,以便随时使用这些程序。

# vim ~/.bashrc
添加export PATH=$PATH:/usr/local/mysql/bin

# source ~/.bashrc   //使修改在当前 shell 立即生效。

(4)接着复制已经编写好的my.cnf配置文件到系统默认位置 /etc目录,并添加mysql用户,将来MySQL8 数据库服务器属于 mysql 所拥有,adduser-r 选项会创建一个非登录账户,以利于安全考虑。

# cp /stage/my.cnf /etc/my.cnf
# adduser -r mysql

adduser -r命令的作用是创建一个系统用户,也就是一个没有登录账户的用户。这种用户通常用于运行系统服务,因为它们不具有交互式shell访问权限,而且他们的权限通常比常规用户更受限制。使用-r选项创建的用户具有以下特点:

  1. 没有密码:无法通过登录来访问该用户账户。
  2. 没有家目录:不会为该用户创建/home目录,节省磁盘空间。
  3. 没有登录Shell:无法以该用户身份进行交互式登录,因为Shell被设置为/sbin/nologin或/bin/false。

在Linux系统中,系统用户通常以uid小于1000的数字标识符表示。使用adduser -r命令创建的系统用户的UID通常开始于100,以确保与普通用户的UID不冲突。

(5)使用 mysqld –initialize 命令创建数据库,该命令会在默认的数据目录 /var/lib/mysql 目录生 成新数据库运行所必须的文件,包括三个系统数据库目录:msyql、performance_schema、sys;innodb 存储引擎的系统表空间文件;服务器和客户端的 ssl 加密公钥和私钥文件;重做日志文件;还原表空间文件等。

        在建库的同时,该命令还给 MySQL 服务器的最高管理账户 root 生成了一个临时口令,在初次登陆 时需要重置 root 口令,否则不能执行进一步的操作。记录下该临时口令备用。

# mysqld --initialize
# ls /var/lib/mysql/

        由于 pid-file 选项引用的是 /var/run/mysqld 目录,但该目录尚不存在,创建该目录并将其所有权 授予 mysql 用户和组。

# cat /etc/my.cnf
# mkdir /var/run/mysqld
# chown mysql:mysql /var/run/mysqld/

(6)现在就可以启动 mysqld 服务器进程,& 选项指示在后台运行:

# mysql_safe &

(7)为了能从 server1 主机上的 Linux 客户机访问 mysqld 服务器进程,需要配置 client 的 socket 选项, 使用 vim 打开 /etc/my.cnf 配置文件,添加如下代码,保存退出。

[client]
socket=/var/lib/mysql/mysql.sock

使用 mysql 客户机以 root 用户登陆,输入建库时系统生成的临时口令:

# mysql -uroot -p

输入 ALTER USER USER() IDENTIFIED BY 'oracle'; 语句重置 root 口令后,才能正常执行数据库操作:

mysql> ALTER USER USER() IDENTIFIED BY 'oracle';
mysql> show databases;

(8)最后,配置 mysqld 系统服务,以便可以使用 Linux 操作系统的 systemctl 命令来管理 mysqld 服务。

关闭 mysqld 服务:

# mysqladmin -uroot -p shutdown

复制 mysqld.service 服务配置文件到 systemd 系统目录,启用即可:

# cp /stage/mysqld.service /usr/lib/systemd/system
# systemctl enable mysqld.service
# systemctl start mysqld
# systemctl status mysqld

从操作系统检查 mysqld 的状态:

# ps aux | grep mysqld

提示:server1 上的 /stage 目录可以更方便地使用 scp 命令直接发送到其它机器的根目录,而不 必使用光驱镜像方式。

[root@server1~]# scp -r /stage root@server2:/
[root@server1~]# ssh root@server2 "ls /stage"

4、配置复制拓扑

        本节实验的操作需同时在三台主机上进行,因此要确保各个主机上的 MySQL 服务器都正常运行, 同时各主机之间的网络均可相互访问。

        典型的复制拓扑是主/从属服务器的一对多关系,高级复杂复制拓扑有双向复制、循环复制以及多源复制等。本章节实验涵盖了在三个独立节点上构建循环复制拓扑的技术内容。

(1)配置基本复制结构

分别在三台主机上停止 mysqld 服务,并对状态进行确认:

# systemctl stop mysqld
# systemctl status mysqld

对三个 MySQL 服务器的配置文件/etc/my.cnf分别进行编辑,在 [mysqld] 选项组中添加以下条目:

server-id=11
...
log-bin=server1-bin   //定义二进制日志文件
relay-log=server1-relay-bin   //定义中继二进制日志文件
# gtid-mode=ON
# enforce-gtid-consistency

注意,一个复制结构中的每台 mysqld 实例必须要有唯一的 server-id, id 值分别为 11、12 和 13。 其中被注释的两行将在后面启用 gtid 时使用。 log-bin 和 relay-log 分别用来定义二进制日志文件和中继二进制日志文件,也要注意区分编号。

分别启动三台服务器并检查进程状态:

# systemctl start mysqld
# ps aux | grep mysqld         //-aux 显示所有包含其他使用者的进程

在数据目录下可以看到二进制日志文件按照 log-bin 选项的格式进行了设置:

# ls /var/lib/mysql/

使用 mysql 客户机以 root 用户登陆到 server1,执行 show master status 命令检查服务器的状态, 记下该二级制日志文件的名称和坐标位置 155,这是开始复制时的起始位置。所有服务器的默认角色都是 master 主服务器。

mysql> SHOW MASTER STATUS\G

在 server1 上创建用于执行复制的 MySQL 用户,并授予 replication slave 权限。注意,基于简化配置的考虑,在 repl 用户创建时特别指定了使用非加密验证插件 mysql_native_password,而不是默 认的 caching_sha2_password 插件,主要是 caching_sha2_password 要求配置加密连接,而这个实验的重点在于复制技术本身。

mysql> CREATE USER 'repl' IDENTIFIED WITH mysql_native_password BY 'oracle';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl';

在 server1 上创建测试用数据库 world 并填充数据,数据来自转储文件 world.sql:

mysql> CREATE DATABASE world;
mysql> USE world
mysql> SOURCE /stage/world.sql
mysql> show databases;

mysql中的source命令用于执行外部SQL脚本,它可以加载指定文件中的SQL语句并执行。使用source命令可以方便地管理和执行大型SQL脚本,而不需要手动复制和粘贴每个SQL语句。

使用方法如下:

source <path to sql file>

其中,<path to sql file>指定了要执行的SQL脚本文件的路径。执行后,MySQL将会自动读取文件中的SQL代码并执行它们。需要注意的是,被执行的SQL脚本文件必须是可读的,并且对于该脚本文件的用户,必须具有足够的权限来执行其中的SQL语句。

source命令还有一个常用的用途是在MySQL控制台中加载一个已保存的查询文件,在控制台中执行查询语句。例如:

source /home/user/queries/query1.sql

这个命令会在MySQL控制台中加载指定路径下的query1.sql文件,并执行其中的查询语句。这样可以方便地重复使用保存的查询,并减少手动输入SQL语句的错误。

接着配置 server2 成为 server1 的 slave,并启动复制线程,观察数据的同步。

登陆到 server2 服务器,首先执行 CHANGE MASTER TO 命令将 server2 角色更改成为 server1 的从属服务器,再启动复制线程,最后检查 world 数据库是否同步到了 server2:

mysql> CHANGE MASTER TO
    -> MASTER_HOST='server1',
    -> MASTER_POST=3306,
    -> MASTER_LOG_FILE='server1-bin.000001',
    -> MASTER_LOG_POS=155;
mysql> START SLAVE USER='repl' PASSWORD='oracle';
mysql> SHOW DATABASES;

在 server1 和 server2 上分别执行 show processlist 命令来检查复制的相关线程: server1 上可以看到有转储线程,它将二进制日志已经发送到 server2 上:

 在 server2 上可以看到 I/O 线程和 SQL 线程:

基本的复制拓扑已经配置好,在 server1 上的更改会立即同步到 server2。

(2)给复制拓扑添加新节点

把 server3 加入到前面由 server1 和 server2 组成的复制结构中,server3 会成为 server2 的从属服务器,三个节点共同组成了一个三层的主从简单复制拓扑:server1 -> server2 -> server3。

要将 server3 作为 server2 的从属服务器,首先要把 server2 的历史数据复制到 server3 以保证数据库数据的完整性,这需要使用 mysqldump 工具以逻辑备份的方式将 world 数据库整体转储到一个 sql 文件中保存,然后把该文件发送到 server3 并导入即可。

使用mysqldump工具时可以添加--master-data=2选项,它会在输出文件中添加注释起来的CHANGE MASTER TO 语句,这样在 server3 上导入数据的同时会将 server3 的角色更改为 server2 的 slave。

[root@server2 ~]# mysqldump -uroot -p --master-data=2 \
> -B world > /tmp/server2.sql
[root@server2 ~]# ll /tmp/server2.sql

编辑导出的文件,去掉注释,并添加 MASTER_HOST='server2', MASTER_PORT=3306, 也就是 server3 的主服务器 server2,保存。

CHANGE MASTER TO MASTER_HOST='',MASTER_POST=3306,MASTER_LOG_FILE='',MASTER_LOG_POS=736143;

将修改后的转储文件发送到 server3,使用 scp 命令:

[root@server2 ~]# scp /tmp/server2.sql root@server3:/tmp/

在 server3 确认转储文件:

[root@server3 ~]# ll /tmp/server2.sql

登陆 server3 服务器,使用 source 命令导入转储文件:

mysql> SOURCE /tmp/server2.sql

启动复制线程:

mysql> START SLAVE USER='repl' PASSWORD='oracle';

检查 slave 从属服务器的状态,可以看到 I/O 线程和 SQL 线程都正常运行:

mysql> SHOW SLAVE STATUS\G

SHOW SLAVE STATUS 命令用于显示MySQL复制从库的状态信息。通过添加 \G,可以以更易读的格式显示输出,每个状态变量都显示在单独的行上。

 

 至此,由三个节点构建的多级主从复制结构就已配置完成,下面进行验证。

在 server1 上删除 city 表的 id 大于 4070 的行,然后在 server2 和 server3 上验证。

server1:

 server2:

 server3:

 可以看到,server1 上的删除操作,在 server2 和 server3 上都同步进行了删除,保持了数据的一 致性。 另外,在 server2 和 server3 上执行 show slave status 命令检查复制的状态,中继日志坐标位置分别是 736780 和 875,最后,自行在 server3 添加 repl 用户,并授予 replication slave 权限,以备下节使用。

(3)启用 GUID 并配置循环复制

二进制日志坐标只适应于简单的复制结构,对于复杂的比如循环、双向和多源复制,二进制日志 坐标就不能唯一标识一个事务了,这个时候必须使用 GTID(全局事务标识符)来记录产生更改的 事务。

每个 GTID 记录了一次修改,GTID 的格式为<source-uuid>:<transaction-id>,

例如单个事务: 0ed18583-47fd-11e2-92f3-0019b944b7f7:338

或者记录一组事务的集合: 0ed18583-47fd-11e2-92f3-0019b944b7f7:1-338

其中,UUID 用来唯一标识每一个服务器,事务的编号记录了在该服务器上执行的事务的顺序。

使用 SELECT @@server_uuid\G 命令可以查看服务器的 UUID,sever1 的 UUID 值显示如下:

 在复杂复制拓扑中,必须使用 GTID 才能唯一标识某一个事务。

下面我们将在三个服务器上启用 GTID,并构建循环拓扑,也即将 server1 设置为 server3 的 slave, 在这种结构中,每一个服务器既是 master,同时又是 slave,在任何一个服务器上的修改,都会同 步到其余的两个服务器上。

在三个节点上分别操作,先关闭 mysqld 实例,然后修改 my.cnf 配置文件,去除 gtid-mode=ON 和 enforce-gtid-consistency 两个选项的注释,保存。

# systemctl stop mysqld
# vim /etc/my.cnf
# cat /etc/my.cnf

分别启动三个 mysqld 实例:

# systemctl start mysqld
# systemctl status mysqld

在 server2 和 server3 上执行 stop slave 命令以停止从属服务器上的 I/O 和 SQL 线程。

mysql> STOP SLAVE;

在 sever1、server2 和 server3 上分别执行 reset master 命令,该命令会复位现有的二进制日志文 件,并将 gtid_executed 和 gtid_purged 设置为空字符串,以便日志文件仅包含使用 GTID 的事件。

在MySQL GTID(全局事务标识符)复制中,

        gtid_executed记录了主库上已经提交的事务GTID,从库要将主库的变更同步到自己的数据库中,就需要使用gtid_executed来判断自己是否执行过这个事务,如果没有执行过,则需要执行该事务,否则忽略该事务。

        gtid_purged具体作用如下:标识当前MySQL实例已经执行过的事务;用于保证在主从复制中避免重复执行已经执行过的事务;用于在故障恢复时快速确定需要恢复的事务;用于检查GTID是否在有效的GTID集合中,以便正确地应用更新。在MySQL GTID复制机制中,gtid_purged非常重要,因为它确保了数据的正确性和一致性。

        将它们设置为空字符串可能会导致MySQL服务器无法正确地识别其复制状态,从而可能会导致数据不一致或复制中断的情况。

mysql> RESET MASTER;
mysql> SELECT @@server_uuid\G

在 server2 和 server3 上分别执行 CHANGE MASTER TO MASTER_AUTO_POSITION=1;和 START SLAVE USER='repl' PASSWORD='oracle'; 恢复前面的三层复制结构,注意这次使用的是 GTID。

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION=1;
mysql> START SLAVE USER='repl' PASSWORD='oracle';
mysql> SHOW SLAVE STATUS\G

验证复制功能,在 server1 上删除 city 表 ID 大于 4060 的行:

mysql> DELECT FROM world.city WHERE ID > 4060;

在 server2 和 server3 上查看到相同的同步结果,复制成功:

SELECT ID,Name FROM world.city ORDER BY ID DESC LIMIT 5;

在 server3,检查从属服务器状态:

mysql> SHOW SLAVE STATUS\G

可以看到,server3 上执行的事务,其事务初始执行位置是在 server1。

继续,在 server1 上执行 change master to 命令,更改 server3 为 server1的 master,并启动复制:

mysql> CHANGE MASTER TO MASTER_HOST='server3',MASTER_AUTO_POSITION=1;
mysql> START SLAVE USER='repl' PASSWORD='oracle':
  1. MASTER_HOST:指定主服务器的主机名或IP地址。

  2. MASTER_AUTO_POSITION:指定MySQL GTID复制机制是否启用。如果设置为1,则启用GTID复制机制;如果设置为0,则禁用GTID复制机制。

在 server2 上删除 city 表 ID 大于 4050 的行:

mysql> DELECT FROM world.city WHERE ID > 4050;
mysql> SELECT ID,Name FROM world.city ORDER BY ID DESC LIMIT 5;

在 server1 上大于 4050 的行也被删除,查询 server1 的 gtid_executed 变量可以看到该删除操作的 初始执行位置是 server2 (server2 的 UUID=0469d41c-f7db-11ed-aa03-000c29bd1425):

mysql> SELECT ID,Name FROM world.city ORDER BY ID DESC LIMIT 5;
mysql> SELECT @@global.gtid_executed\G
  1. SELECT @@global.gtid_executed:这是一个查询语句,用于查询MySQL数据库服务器上已经执行的GTID列表。

  2. @@global.gtid_executed:这个变量表示MySQL数据库服务器上已经执行的GTID列表。

  3. \G:这是一个命令行工具中的快捷方式,它可以将结果集转换为垂直格式并进行显示,使得我们可以更加容易地阅读结果。

在MySQL GTID复制机制中,GTID是指全局事务标识符,它是由MySQL服务器生成的一个全局唯一的标识符,用于标识每个已提交的事务。这使得在主从复制过程中可以更加准确地确定哪些事务已经被执行,避免主从数据不一致的问题。

通过执行以上命令,我们可以查看已经执行的GTID列表,以便更好地管理MySQL主从复制,并排查主从数据同步的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值