MYSQL的复制场景

文章目录

1. MySQL开启二进制

# 查看二进制是否开启
(root@localhost) [hellodb]> select @@log_bin;
+-----------+
| @@log_bin |
+-----------+
|         1 |
+-----------+
1 row in set (0.01 sec)

# 二进制日志记录的格式
(root@localhost) [hellodb]> select @@binlog_format;
STATEMENT:每个会更改数据的SQL语句都会被记录。
ROW:对于每个更改,更改的行的内容都会被记录。
MIXED:MySQL决定何时使用STATEMENT格式,何时使用ROW格式。

#log_bin和sql_log_bin的区别:
log_bin:
这是一个服务器系统变量。
当你设置了 log_bin,MySQL 服务器会启动二进制日志功能,记录所有数据库的更改。
这主要用于复制和恢复的目的。如果你希望从主服务器复制数据到从服务器,你需要在主服务器上启用 log_bin。
该变量还指定了日志文件的基本名。例如,如果你设置 log_bin=/var/log/mysql/mysql-bin, 那么你的二进制日志文件可能会是 mysql-bin.000001, mysql-bin.000002, 等等。

sql_log_bin:
这是一个会话级别的变量。
当 sql_log_bin 设置为 TRUE(默认值),那么在当前会话中进行的更改将记录到二进制日志中(前提是 log_bin 也已启用)。
如果你希望某个特定的会话中的更改不记录到二进制日志中,可以设置 SET sql_log_bin = 0; 以禁用它。这对于某些管理任务,例如备份或导入大量数据,可能是有用的,因为这样可以防止将这些大量的更改复制到从服务器上。
请注意,只有具有 SUPER 权限的用户才能更改 sql_log_bin。

# 临时关闭二进制日志
 set sql_log_bin=0;

# 查看当前拥有的MYSQL二进制日日志
(root@localhost) [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       328 |
| mysql-bin.000002 |       375 |
| mysql-bin.000003 |       394 |
| mysql-bin.000004 |       351 |
| mysql-bin.000005 |       601 |
| mysql-bin.000006 |       432 |
| mysql-bin.000007 |       385 |
+------------------+-----------+
7 rows in set (0.000 sec)

(root@localhost) [hellodb]> 

# 也可以查看二进制文件的位置
[root@Rocky9 logbin]# ll /data/logbin/ -h
total 32K
-rw-rw---- 1 mysql mysql 328 Sep 20 14:32 mysql-bin.000001
-rw-rw---- 1 mysql mysql 375 Sep 25 11:38 mysql-bin.000002
-rw-rw---- 1 mysql mysql 394 Sep 30 15:32 mysql-bin.000003
-rw-rw---- 1 mysql mysql 351 Oct  2 20:33 mysql-bin.000004
-rw-rw---- 1 mysql mysql 601 Oct  3 00:00 mysql-bin.000005
-rw-rw---- 1 mysql mysql 432 Oct  7 11:14 mysql-bin.000006
-rw-rw---- 1 mysql mysql 385 Oct  7 11:14 mysql-bin.000007
-rw-rw---- 1 mysql mysql 210 Oct  7 11:14 mysql-bin.index
[root@Rocky9 logbin]# 
# 查看当前MYSQL使用的二进制
(root@localhost) [hellodb]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000007 |      385 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.000 sec)
(root@localhost) [hellodb]> 
# 查看二进制文件最大的容量(达到这个最大的size或者重启数据库服务都会重新生成一个二进制文件)
(root@localhost) [hellodb]> select @@max_binlog_size;
+-------------------+
| @@max_binlog_size |
+-------------------+
|        1073741824 |
+-------------------+
1 row in set (0.018 sec)

(root@localhost) [hellodb]> 
# 在线查看指定二进制文件的内容
(root@localhost) [hellodb]> show binlog events in 'mysql-bin.000008';
+------------------+-----+-------------------+-----------+-------------+-----------------------------------------------------------+
| Log_name         | Pos | Event_type        | Server_id | End_log_pos | Info                                                      |
+------------------+-----+-------------------+-----------+-------------+-----------------------------------------------------------+
| mysql-bin.000008 |   4 | Format_desc       |         1 |         256 | Server ver: 10.5.16-MariaDB-log, Binlog ver: 4            |
| mysql-bin.000008 | 256 | Gtid_list         |         1 |         299 | [0-1-1]                                                   |
| mysql-bin.000008 | 299 | Binlog_checkpoint |         1 |         342 | mysql-bin.000008                                          |
| mysql-bin.000008 | 342 | Gtid              |         1 |         384 | BEGIN GTID 0-1-2                                          |
| mysql-bin.000008 | 384 | Intvar            |         1 |         416 | INSERT_ID=10                                              |
| mysql-bin.000008 | 416 | Query             |         1 |         528 | use `hellodb`; insert teachers values(null,'test',22,'F') |
| mysql-bin.000008 | 528 | Xid               |         1 |         559 | COMMIT /* xid=20 */                                       |
+------------------+-----+-------------------+-----------+-------------+-----------------------------------------------------------+
7 rows in set (0.000 sec)

(root@localhost) [hellodb]> 
# 不登录数据库查看二进制文件的内容,不指定--start-position和--stop-position的话,那么就是查看全部文件的内容
[root@Rocky9 logbin]# mysqlbinlog /data/logbin/mysql-bin.000008 --start-position=516 --stop-position=528
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#231008 11:50:27 server id 1  end_log_pos 256 CRC32 0x23800a0e  Start: binlog v 4, server v 10.5.16-MariaDB-log created 231008 11:50:27 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
AyciZQ8BAAAA/AAAAAABAAABAAQAMTAuNS4xNi1NYXJpYURCLWxvZwAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAADJyJlEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEEwQADQgICAoKCgEOCoAj
'/*!*/;
ERROR: Error in Log_event::read_log_event(): 'Event truncated', data_len: 2099353352, event_type: 39
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@Rocky9 logbin]# 
# 清理某个二进制文件之前的日志文件
(root@localhost) [hellodb]> purge binary logs to 'mysql-bin.000009';
Query OK, 0 rows affected (0.021 sec)
(root@localhost) [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000009 |       554 |
| mysql-bin.000010 |      1439 |
+------------------+-----------+
2 rows in set (0.000 sec)

(root@localhost) [hellodb]> 
# 清除所有二进制日志
(root@localhost) [hellodb]> reset master;
Query OK, 0 rows affected (0.005 sec)

(root@localhost) [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       328 |
+------------------+-----------+
1 row in set (0.000 sec)

(root@localhost) [hellodb]> 
[root@Rocky9 logbin]# ll
total 8
-rw-rw---- 1 mysql mysql 328 Oct  8 14:25 mysql-bin.000001
-rw-rw---- 1 mysql mysql  30 Oct  8 14:25 mysql-bin.index
[root@Rocky9 logbin]# cat mysql-bin.index
/data/logbin/mysql-bin.000001
[root@Rocky9 logbin]# 
# 刷新日志,重新生成一个二进制日志
(root@localhost) [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       328 |
+------------------+-----------+
1 row in set (0.000 sec)

(root@localhost) [hellodb]> flush logs;
Query OK, 0 rows affected (0.007 sec)

(root@localhost) [hellodb]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       375 |
| mysql-bin.000002 |       371 |
+------------------+-----------+
2 rows in set (0.000 sec)

(root@localhost) [hellodb]> 
# 或者
mysqladmin -uroot -pxxxx flush-logs

mysql修改命令提示符

# 当我们安装好mysql服务器的时候,需要使用“mysql”这个客户端命令来查看相应的设置,但是提示符显示不是很友好。
eg:
mysql >

# 进入mysql的配置目录
cd /etc/my.cnf.d

# 在该目录下创建任何文件mysql都会识别并且加载
touch mysql.cnf

[mysql]
prompt=(\\u@\\h mysql\\v) [\\d]>\\_

# 解释:
在MySQL的配置文件或者交互式提示符中,这些是用于设置MySQL命令行客户端提示符的转义序列。

\\u: 当前MySQL用户。
\\h: 连接的MySQL服务器的主机名。
\\d: 当前选择的数据库。
\\_: 显示一个'>'字符。
\\c: 显示MySQL命令计数器。
\\l: 显示当前delimiter字符。
\\p: 显示当前端口。
\\P: 显示当前mysqlnd库端口。
\\r: 显示当前协议版本。
\\s: 显示当前服务器版本。
\\v: 显示当前版本信息。
\\n: 新行。
\\t: 制表符

#再次进入发现提示符已经变化了
root@localhost mysql8.0.32) [(none)]>

2. MySQL备份与还原

# 备份类型
1.完全备份
2.增量备份:备份的速度的快,还原麻烦
3.差异备份:备份的越来越慢,还原简单(只需要还原第一次的完全备份和差异备份),必须先做一次完全备份
# 增量备份和差异备份是基于完全备份上的

#MyISAM:支持温备,不支持热备,因为MyISAM不支持事务,无法隔离

# 事务(4个隔离级别):
1.读未提交(READ UNCOMMITTED)
2.读已提交(READ COMMITTED)
3.可重复读(REPEATABLE READ)
4.串行、序列化(SERIALIZABLE)

#冷备份(Mariadb 10)
# 第一步:必须停止数据库
systemctl stop mysqld

# 第二歩:使用rsync同步到远程主机上
rsync -a /var/lib/mysql 10.0.0.134:/data/
# 如果配置文件修改了,也需要拷贝
# 例如:scp /etc/my.cnf.d/mariadb-server.cnf 10.0.0.134:/etc/my.cnf.d/

# 第三步:安装mysql,将备份文件cp到对应的mysql目录下
yum -y install mysql-server
cp -a /data/mysql/* /var/lib/mysql

# 第四步:启动
systemct enable --now mysqld

# 冷备份(Mysql 8.0)
# 参照上述Mariadb

#温备份
# 使用mysqldump命令进行备份
# 备份所有数据库
mysqldump -uroot -pxxxx -B/--all-databases > /data/xxx.sql


开启二进制日志

# mysql8.0默认开启二进制日志,但是Mariadb 10默认不开启二进制日志,需要手动开启
vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
#开启二进制日志
log-bin=/data/logbin/mysql-bin
#二进制日志的存储方式
binlog_format=row
#将上面的文件夹创建出来
mkdir /data/logbin
#修改所有者所属组
chown mysql.mysql /data/logbin
#重启数据库服务
systemctl restart mysqld

完全备份+二进制日志备份

# 备份并压缩
[root@Rocky9 ~]# mysqldump -A --master-data=2 | gzip > /data/all.sql.gz

# 登录数据库做增删操作
(root@localhost) [hellodb]> delete from teachers where tid=11;
(root@localhost) [hellodb]> insert teachers values (null,'xiaoming',22,'F');
Query OK, 1 row affected (0.006 sec)

(root@localhost) [hellodb]> insert teachers values (null,'xiaohong',23,'M');
Query OK, 1 row affected (0.013 sec)

(root@localhost) [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
|  12 | xiaoming      |  22 | F      |
|  13 | xiaohong      |  23 | M      |
+-----+---------------+-----+--------+
6 rows in set (0.001 sec)

# 确定当前的二进制日志使用的是哪个
(root@localhost) [hellodb]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000012 |     1120 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.000 sec)


# 查看二进制日志
[root@Rocky9 ~]# ll /data/logbin/
total 84
-rw-rw---- 1 mysql mysql   375 Oct  8 14:27 mysql-bin.000001
-rw-rw---- 1 mysql mysql   418 Oct  8 14:29 mysql-bin.000002
-rw-rw---- 1 mysql mysql   925 Oct  9 09:00 mysql-bin.000003
-rw-rw---- 1 mysql mysql   736 Oct  9 09:41 mysql-bin.000004
-rw-rw---- 1 mysql mysql   342 Oct 12 13:45 mysql-bin.000005
-rw-rw---- 1 mysql mysql   365 Oct 16 16:11 mysql-bin.000006
-rw-rw---- 1 mysql mysql   389 Oct 17 09:08 mysql-bin.000007
-rw-rw---- 1 mysql mysql   385 Oct 17 09:08 mysql-bin.000008
-rw-rw---- 1 mysql mysql   389 Oct 19 09:15 mysql-bin.000009
-rw-rw---- 1 mysql mysql   408 Oct 19 09:28 mysql-bin.000010
-rw-rw---- 1 mysql mysql   389 Oct 20 09:57 mysql-bin.000011
-rw-rw---- 1 mysql mysql  1143 Oct 20 11:17 mysql-bin.000012
-rw-rw---- 1 mysql mysql 27411 Oct 20 11:18 mysql-bin.000013
-rw-rw---- 1 mysql mysql   342 Oct 20 11:18 mysql-bin.000014
-rw-rw---- 1 mysql mysql   420 Oct 20 11:18 mysql-bin.index
[root@Rocky9 ~]#
# myql-bin.xxx这个格式是在/etc/my.cnf.d/mariadb-server.cnf配置文件中定义好的
log-bin=/data/logbin/mysql-bin

# 查看备份文件记录的二进制日志位置
# 先解压缩
[root@Rocky9 logbin]# gzip -d /data/all.sql.gz
[root@Rocky9 logbin]# grep -i mysql-bin.0000 /data/all.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=385;
[root@Rocky9 logbin]#
# 这一行代表第一次完全备份到了二进制文件mysql-bin.000012中的385这个位置,385后续的是没有备份的,如果想还原的话,需要第一次备份的文件以及结合二进制文件mysql-bin.000012中的385后续的部分才可以恢复

# 导入二进制日志
[root@Rocky9 logbin]# mysqlbinlog --start-position=385 mysql-bin.000012 > /data/binlog.sql

# 启动数据库,相当于新安装数据库
[root@Rocky9 logbin]# systemctl restart mariadb.service
# 还原的时候是不需要二进制日志的,可以临时禁用
(root@localhost) [(none)]> set sql_log_bin=0;
Query OK, 0 rows affected (0.000 sec)

(root@localhost) [(none)]> select @@sql_log_bin;
+---------------+
| @@sql_log_bin |
+---------------+
|             0 |
+---------------+
1 row in set (0.001 sec)

(root@localhost) [(none)]> source /data/all.sql
(root@localhost) [(none)]> source /data/logbin.sql
(root@localhost) [(none)]> use hellodb
(root@localhost) [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
|  12 | xiaoming      |  22 | F      |
|  13 | xiaohong      |  23 | M      |
+-----+---------------+-----+--------+
6 rows in set (0.000 sec)

(root@localhost) [hellodb]>
# 恢复二进制
(root@localhost) [hellodb]> set sql_log_bin=1;
Query OK, 0 rows affected (0.000 sec)

# 还原成功

# 计划任务
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

# 数据库的隔离级别是隔离不住DDL语句的,也就是alter table,drop table,rename table,truncate table。并且这些操作rollback也是撤销不了的。

# SQL语句分类:
DDL:Data Definition Language 数据定义语言(create,drop,alter)
DML:Data Manipulation Language 数据操纵语言(insert,delete,update)
DQL:Data Query Language 数据查询语言(select)
DCL:Data Crontrol Language 数据控制语言(grank,revoke)
TCL:Transaction Crontrol Language 事务控制语言(commit,rollback,savepoint)

# 计划任务
crontab命令的几个常见用法:

crontab -e:编辑当前用户的crontab文件。
crontab -l:列出当前用户的crontab。
crontab -r:删除当前用户的crontab。

# 格式
cron环境跟shell环境是不一样的,最好将path变量都写在crontab -e里面,如果想确定目前crontab的环境变量可以看文件/etc/contab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin #和shell中的PATH变量是不同的
MAILTO=root
这里面定义了shell类型,path变量,以及邮件人

crontab -e
PATH=/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
* * * * * /path/to/command
这五个*分别代表:
分钟 (0 - 59)
小时 (0 - 23)
一个月中的某天 (1 - 31)
月份 (1 - 12)
一周中的某天 (0 - 7) (0 和 7 都代表星期日)

3. 利用xtrabackup完全、增量备份及还原

# 安装xtrabackup
https://www.percona.com/downloads
yum -y install percona-xtrabackup-80-8.0.34-29.1.el8.x86_64.rpm #Rocky 8、CentOS8
yum -y install percona-xtrabackup-80-8.0.34-29.1.el9.x86_64.rpm #Rocky 9
# 完全备份(不可以回滚)
mkdir /backup
xtrabackup -uroot --backup --target-dir=/backup/base

# 第一次增量备份(不可以回滚,保持事务的完整性,增量备份一定是建立在完全备份的基础上)
xtrabackup -uroot --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/base
# 第二次增量备份(可以回滚)
xtrabackup -uroot --backup --target-dir=/backup/inc2 --incremental-basedir=/backup/inc1

[root@Rocky8 backup]#ll  /backup/ -h
total 12K
drwxr-x--- 6 root root 4.0K Oct 23 22:07 base
drwxr-x--- 6 root root 4.0K Oct 23 22:56 inc1
drwxr-x--- 6 root root 4.0K Oct 23 22:58 inc2
[root@Rocky8 backup]#du -sh *
72M	base
2.0M	inc1
2.2M	inc2
[root@Rocky8 backup]#


# 还原
# 拷贝到远程机器
scp -r /backup/ 10.0.0.10:/
# 停止数据库
systemctl stop mysqld
rm -rf /var/lib/mysql/*
# 预准备,将所有备份整合到base目录下(--apply-log-only代表不回滚)
xtrabackup --prepare --apply-log-only --target-dir=/backup/base
xtrabackup --prepare --apply-log-only --target-dir=/backup/base --incremental-dir=/backup/inc1
xtrabackup --prepare  --target-dir=/backup/base --incremental-dir=/backup/inc2
# base目录下的数据拷贝到/var/lib/mysql/下
xtrabackup --copy-back --target-dir=/backup/base
# 修改属性
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld

4.主从复制

# 显示了当前MySQL服务器的活动进程
mysql> show processlist;
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
| Id | User            | Host      | db   | Command | Time  | State                  | Info             |
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 71058 | Waiting on empty queue | NULL             |
| 30 | root            | localhost | NULL | Query   |     0 | init                   | show processlist |
+----+-----------------+-----------+------+---------+-------+------------------------+------------------+
2 rows in set (0.02 sec)
# mysql8.0默认开启了event_scheduler,而mariadb10默认不开启
第一个进程(Id为5):
是由event_scheduler用户运行的。
它在localhost上运行。
这个进程不关联任何特定的数据库。
它是一个守护进程(Daemon)。
这个进程已经运行了71058秒。
它当前正在等待空队列上的任务。
这是事件调度器进程,它用于执行预定的事件。
第二个进程(Id为30):
是由root用户运行的。
它也在localhost上运行。
它不关联任何特定的数据库。
它是一个查询进程。
这个进程刚开始运行(运行了0秒)。
它目前正在初始化。
它正在执行的查询是show processlist,这就是你看到这个结果的原因。

server_id

# 查询当前MySQL服务器的server_id系统变量的值。
mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)

# server_id是一个整数,它用于唯一标识MySQL服务器实例,特别是在复制和二进制日志上下文中。在一个复制拓扑中(例如一个主-从结构),每个服务器必须有一个唯一的server_id。
具体作用:
1.复制: 在MySQL的复制结构中,server_id用于确保每个MySQL服务器节点(无论是主节点还是从节点)都有一个唯一标识。这样,当从节点读取主节点的二进制日志并应用更改时,它可以避免应用来自其自己的更改。它也确保了复制链中的其他从节点不会从另一个从节点接收更改。
eg:想象一下,我们有一个主MySQL服务器(我们称之为M)和两个从MySQL服务器(称为S1和S2)。
#复制的基础:
主服务器M在进行任何写操作(如INSERT, UPDATE等)时,会在其二进制日志(binary log)中记录这些更改。
从服务器(如S1和S2)将定期从主服务器M的二进制日志中读取这些更改,并在其本地应用这些更改。这就是它们如何与主服务器保持同步的。
#为什么需要server_id:
假设S1正在从M读取并应用更改。在这个过程中,S1也会记录这些更改到其自己的二进制日志中。
如果没有一种机制来识别这些更改的来源,那么S2可能会从S1读取这些更改,并再次应用它们,尽管它们已经直接从M应用过了。这会导致数据的不一致。
这就是server_id派上用场的地方。每次写入二进制日志的事件都会带有产生该事件的服务器的server_id。
当S1从M读取和应用更改时,它知道这些更改来自M,因为它们带有M的server_id。因此,当S1将这些更改写入其自己的日志时,S2在读取它们时会知道这些更改已经从M应用过了,因此不会再次应用它们。
#链式复制:
在更复杂的设置中,你可能有多级复制,例如M->S1->S2。在这种情况下,S2是S1的从服务器,而S1是M的从服务器。
在这种设置中,S2需要从S1读取和应用更改,但只有那些原始来自M的更改。它需要跳过那些已经从M到S1并从S1到S2应用过的更改。再次,server_id在此处是关键,因为它允许S2识别和跳过重复的更改。
2.二进制日志: 在二进制日志事件中,server_id用于标识生成该事件的MySQL服务器。这在处理复制时非常有用,因为从节点可以识别事件来源,确保它只处理来自主节点的事件。
3.避免冲突: 在多主复制环境中,确保每个主节点都有一个唯一的server_id是很重要的,以避免数据冲突和不一致。

# 在MySQL的配置文件my.cnf(或my.ini)中,你应该使用server_id,使用横线也是可以的。
[mysqld]
log-bin=/data/mysql/logbin/mysql-bin
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
server_id=135
关于这两者之间的区别:
server-d是正确的配置文件中的参数名称。
@@server_id是在SQL查询中使用的系统变量名称。例如,当你运行SELECT @@server_id;时。
这是MySQL的命名约定,系统变量使用下划线(_),而配置文件中的选项使用短横线(-)。在处理配置文件或编写SQL查询时,确保使用正确的格式是很重要的。

主从复制(主节点是新的)

# master
1.启用二进制,同时设置二进制的位置,文件命名格式
vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
log-bin=/data/mysql/logbin/mysql-bin
2.为当前节点设置一个全局唯一的ID
[mysqld]
server-id=x
log-basename=master #可选项,设置datadir中日志名称,确保不依赖主机名
3.查看从二进制日志的文件和位置开始进行复制
SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      157 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
4.创建有复制权限的用户账号(mysql8.0必须分开)
create user repluser@'10.0.0.%' identified by '123456';
grant replication slave on *.* to repluser@'10.0.0.%';
# GRANT: GRANT语句在MySQL中用于赋予权限。你可以使用它为特定的用户赋予特定的权限,以执行某些任务。
REPLICATION SLAVE: 这是你希望赋予的权限类型。REPLICATION SLAVE权限允许用户连接到主服务器(master)并请求二进制日志(binary log)的内容,这是MySQL复制所必需的。简而言之,具有这种权限的用户可以充当复制的从服务器(slave)。
ON *.*: 这表示权限的范围。在这里,*.*意味着权限适用于所有数据库和这些数据库中的所有表。尽管REPLICATION SLAVE权限实际上是全局的(因为它与特定数据库或表无关),但这种表示法通常是标准的。
TO repluser@'10.0.0.%': 这定义了权限的接收者。
repluser: 这是用户名。
10.0.0.%: 这是允许从中连接的主机地址模式。%是一个通配符,意味着这个用户可以从IP地址为10.0.0.x的任何主机连接,其中x可以是任何数字。
所以,总结一下,这个命令的意思是:“赋予repluser从任何10.0.0.x地址连接的用户权限,允许他们充当复制的从服务器,并从主服务器请求二进制日志的内容”。
# 8.0以前
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'HOST' IDENTIFIED BY 'replpass';

# salve
1.修改配置文件
[mysqld]
server_id=# #为当前节点设置一个全局惟的ID号
log-bin
read_only=ON #设置数据库只读,针对supper user无效
relay_log=relay-log #relay log的文件路径,默认值hostname-relay-bin
relay_log_index=relay-log.index #默认值hostname-relay-bin.index
2.使用有复制权限的用户账号连接至主服务器,并启动复制线程
CHANGE MASTER TO MASTER_HOST='10.0.0.135',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_PORT=3306,MASTER_LOG_FILE='mysql-bin.000010',MASTER_LOG_POS=157;
 
CHANGE MASTER TO是用于设置或更改MySQL从服务器的复制坐标和凭据的命令。
MASTER_HOST='10.0.0.135':
这是主服务器(master)的IP地址或主机名,从服务器将连接到这个地址以接收复制数据。
MASTER_USER='repluser':
用于连接到主服务器的MySQL用户名。这个用户需要有REPLICATION SLAVE权限。
MASTER_PASSWORD='123456':
上述用户的密码。
MASTER_PORT=3306:
主服务器上MySQL服务的端口号。
MASTER_LOG_FILE='mysql-bin.000010':
从服务器开始读取复制事件的二进制日志文件名。通常,当你设置新的从服务器或需要更改复制开始的位置时,你会设置这个值。
MASTER_LOG_POS=157:
在上述日志文件中,从服务器开始复制的位置(偏移量)。
将所有这些设置结合起来,这条命令实际上告诉从服务器:“连接到IP为10.0.0.135、端口为3306的主服务器,使用repluser用户名和123456密码,并从mysql-bin.000001日志文件的157位置开始接收复制事件。”

# 启动复制过程,slave会开启io、sql线程,master会开启dump线程
start slave

# 查看线程
show processlist;
# 查看从节点状态
show slave status\G
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 10.0.0.135
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000010
          Read_Master_Log_Pos: 157
               Relay_Log_File: rocky9-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000010
             Slave_IO_Running: yes
            Slave_SQL_Running: yes
	    Seconds_Behind_Master: NULL
	    
# IO线程(在从服务器上):
负责从主服务器读取二进制日志(binary log)事件。
IO线程连接到主服务器,然后读取主服务器的二进制日志,并将这些日志事件复制到从服务器的中继日志(relay log)。
中继日志本质上是从服务器上的二进制日志的临时副本。
当Slave_IO_Running状态显示为Yes时,这意味着IO线程正在运行并且与主服务器保持连接。

# SQL线程(在从服务器上):
负责读取中继日志并执行其中的事件,从而保持从服务器的数据与主服务器同步。
它在单线程模式下运行,这意味着它会一个接一个地执行日志事件,尽管在主服务器上这些事件可能是并行执行的。
当Slave_SQL_Running状态显示为Yes时,这意味着SQL线程正在运行。

# Dump线程(在主服务器上):
当从服务器连接到主服务器以请求二进制日志时,主服务器上的mysqld进程会为每个从服务器启动一个dump线程。
Dump线程的任务是读取二进制日志并发送它给请求的从服务器的IO线程。
如果你有多个从服务器连接到同一个主服务器,主服务器将为每个从服务器启动一个单独的dump线程。

# 当你启动从服务器上的复制进程时,这些线程是如何交互工作的:
IO线程首先连接到主服务器并请求从一个指定的二进制日志位置开始的日志事件。
主服务器的dump线程开始读取这些事件并发送给IO线程。
IO线程将这些事件写入其中继日志。
同时,SQL线程开始读取中继日志并执行日志事件,从而将从服务器上的数据与主服务器保持同步。

# 停止从服务器
stop slave

# 重置从服务器的复制设置
reset slave all;

主从复制(主节点运行已久)


# 实际生产环境中,主节点不会是一个新的数据库,而是一个用了好久的数据库,那么如果想主从复制,并且从节点要拿到主节点之前的数据,如下:
# master
首先需要对数据库进行完全备份
mysqldump -A -F --source-data=1 --single-transaction > /backup/all.sql
# --master-data在较新的版本当中已经弃用了,而是用--source-data来替代

1.启用二进制,同时设置二进制的位置,文件命名格式
vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
log-bin=/data/mysql/logbin/mysql-bin
2.为当前节点设置一个全局唯一的ID
[mysqld]
server-id=x
log-basename=master #可选项,设置datadir中日志名称,确保不依赖主机名
3.查看从二进制日志的文件和位置开始进行复制
SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      157 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
4.创建有复制权限的用户账号(mysql8.0必须分开)
create user repluser@'10.0.0.%' identified by '123456';
grant replication slave on *.* to repluser@'10.0.0.%';
# REPLICATION SLAVE:这是要授予的特定权限。当你为一个服务器设置复制,并且希望这个服务器作为从服务器(slave),这个权限就必须授予。这样,从服务器才能连接到主服务器(master)并请求二进制日志的事件。简单地说,它允许从服务器从主服务器拉取复制数据。
ON .:这指的是权限的作用范围。*.* 表示权限适用于所有数据库的所有表。在这种情况下,这是有意义的,因为复制涉及到所有数据库。

TO 'repl'@'%':这指定了将获得权限的用户及其来源。


# salve
1.修改配置文件
[mysqld]
server_id=# #为当前节点设置一个全局惟的ID号
log-bin
read_only=ON #设置数据库只读,针对supper user无效
relay_log=relay-log #relay log的文件路径,默认值hostname-relay-bin
relay_log_index=relay-log.index #默认值hostname-relay-bin.index
2.将在主节点的完全备份文件拷贝到从节点
vim  /backup/all.sql
找到下面的语句
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=157;
修改成
CHANGE MASTER TO MASTER_HOST='10.0.0.131',MASTER_USER='repluser',MASTER_PASSWORD='123456',MASTER_PORT=3306,  MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=157;
# 进入到mysql中
# 临时关闭二进制
mysql> set sql_log_bin=0;
# 导入完全备份的sql文件
mysql> source /backup/all.sql
# 查看从节点的状态
mysql> show slave status\G
# 启动从节点线程
mysql> start slave
# 开启二进制
mysql> set sql_log_bin=1;

查看从节点状态:
Last_IO_Error: error connecting to master 'repluser@10.0.0.131:3306' - retry-time: 60 retries: 1 message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
此错误表示从服务器在尝试连接到主服务器时遇到了鉴权问题。具体地,它是关于caching_sha2_password鉴权插件的,该插件在MySQL 8.0及更高版本中是默认的鉴权插件。此插件要求在客户端和服务器之间使用安全连接,通常是通过SSL/TLS。
# 更改主服务器上复制用户的鉴权方法():
ALTER USER 'repluser'@'10.0.0.%' IDENTIFIED WITH 'mysql_native_password' BY '123456';
#也可以在创建的时候更该
CREATE USER 'repluser'@'10.0.0.%' IDENTIFIED WITH 'mysql_native_password' BY '123456';
flush privileges;
# IDENTIFIED WITH 'mysql_native_password' - 这告诉MySQL,当这个用户尝试登录时,应该使用mysql_native_password鉴权插件。mysql_native_password 是MySQL的一个身份验证插件。在MySQL 8.0及更高版本中,身份验证插件的默认值是 caching_sha2_password。然而,不是所有的客户端库或连接器都支持新的 caching_sha2_password 插件。因此,在某些情况下,可能需要创建使用旧的 mysql_native_password 插件的用户。
caching_sha2_password:
这是MySQL 8.0及更高版本中的默认鉴权插件。
它使用SHA-256哈希算法。
这个插件为了提高性能和安全性,提供了一个密码缓存机制。
通常,它需要一个安全的连接(如SSL/TLS),但也可以配置为允许非安全连接。
mysql_native_password:
这是在MySQL 8.0之前的版本中的默认鉴权插件。
它使用SHA-1哈希算法。
它不需要安全的连接,但使用SSL/TLS总是一个好的实践。

# 如果是在从节点上修改导致最后数据不同步,那么需要再从节点跳过错误
stop slave;
set global sql_slave_skip_counter=1
start slave;

使用GTID进行主从复制

# 利用 GTID复制不像传统的复制方式(异步复制、半同步复制)需要找到binlog文件名和POS点,只需知道master的IP、端口、账号、密码即可。开启GTID后,执行change master to
master_auto_postion=1即可,它会自动寻找到相应的位置开始同步
# 其余的都一样,只需要在主配置文件以及从配置文件加入下面服务器选项
vim /etc/my.cnf
[mysqld]
gtid_mode=ON	# gtid模式
enforce_gtid_consistency	# 保证GTID安全的参数

# 在mysql8.0.23以及更高的版本,已经逐渐弃用了change master这种写法使用下面:
# 旧版本写法:
CHANGE MASTER TO
MASTER_HOST='10.0.0.131',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1;

# 新版本写法:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.131',
SOURCE_USER='repluser',
SOURCE_PASSWORD='123456',
SOURCE_PORT=3306,
SOURCE_AUTO_POSITION=1;
SOURCE_LOG_FILE 和 SOURCE_LOG_POS(从 MySQL 8.0.23 开始)

# 清空slave的新版本写法:
 RESET REPLICA ALL;
 从 MySQL 8.0.22 开始,使用 START REPLICA 代替 START SLAVE,
 STOP REPLICA=stop slave
 START REPLIC=start slave
 SHOW REPLICA STATUS\G=show slave status\G

5. 级联复制

级联复制是指从服务器不仅从主服务器接收更新,还将这些更新传递给其他的从服务器。也就是说,你可以有如下的链式结构:主 -> 从1 -> 从2。

配置方法

  1. 首先,确保主服务器启用了二进制日志(binlog)。
  2. 在从1服务器上,像普通的主从复制那样配置复制,使其从主服务器接收更新。
  3. 在从1上设置 log_slave_updates=1,这样从1可以将从主服务器接收到的更新写入自己的二进制日志。
  4. 在从2服务器上,将从1配置为其主服务器,使从2从从1接收更新。
# 准备主服务器:
1.开启二进制,以及设置server_id
vim /etc/my.cnf
[mysqld]
server-id=135
log-bin=/data/mysql/logbin/mysql-bin
2.重启mysql服务
systemctl restart mysqld
3.创建用于复制的用户并赋予权限:
CREATE USER 'repluser'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'%';
4.记录二进制日志的位置:
show master status;

# 准备第一个从服务器(从1):
1.在 my.cnf 或 my.ini 配置文件中设置:
[mysqld]
log-bin=/data/mysql/logbin/mysql-bin
server-id=131
relay-log=relay-bin
log_slave_updates=1  # 让从服务器记录复制的二进制日志
2.重启MySQL服务。
3.使用以下命令配置从1以从主服务器接收复制:
CHANGE MASTER TO
  MASTER_HOST='master_host_ip',
  MASTER_USER='repluser',
  MASTER_PASSWORD='123456',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=157;
4.启动从1的复制线程:
start slave;

# 准备第二个从服务器(从2):
1.在 my.cnf 或 my.ini 配置文件中设置:
[mysqld]
log-bin=/data/mysql/logbin/mysql-bin
server-id=134
relay-log=relay-bin
2.重启MySQL服务。
3.使用以下命令配置从2以从从1服务器接收复制:
CHANGE MASTER TO
  MASTER_HOST='slave1_host_ip',
  MASTER_USER='repluser',
  MASTER_PASSWORD='123456',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=157;
4.启动从2的复制线程:
start slave;

6. 主主复制

主主复制指的是两个服务器都可以接受写操作,并将这些操作复制到另一个服务器。这实际上是两个主从复制的组合

配置方法

  1. 配置服务器A和服务器B的server-id,确保它们是唯一的。
  2. 启用两个服务器上的二进制日志。
  3. 在服务器A上,配置从服务器,使其从服务器B接收更新。
  4. 在服务器B上,配置从服务器,使其从服务器A接收更新。
  5. 为了避免主键冲突,有些场景可能需要为每个服务器设置不同的自增间隔(auto_increment_increment)和起始值(auto_increment_offset)。

注意

  • 主主复制并不意味着你可以在两个服务器上同时写入相同的数据。这可能会导致数据冲突和不一致。它通常用于确保冗余,并允许在一个服务器故障时,另一个服务器可以立即接管。
  • 主主复制通常更复杂,并需要更多的管理。例如,需要确保避免主键或唯一约束冲突。
1.准备两台MySQL服务器:确保你有两台运行MySQL的服务器,我们将它们称为ServerA和ServerB。
修改配置文件:

在ServerA上:
[mysqld]
server-id=1
log-bin=/data/mysql/logbin/mysql-bin
在ServerB上:
[mysqld]
server-id=2
log-bin=/data/mysql/logbin/mysql-bin
这里的关键是为每个服务器指定一个唯一的 server-id。重启两个MySQL实例以应用更改。
2. 重启MYSQL数据库
3.创建复制用户:
在ServerA上:
CREATE USER 'repluser'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'%';
在ServerB上:(可以省略这一步,因为创建一个另一个会复制过去)
CREATE USER 'repl'@'ServerA_IP' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'ServerA_IP';

4.获取二进制日志的位置:
在ServerA上:
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
记录日志文件名和位置。随后在ServerB上执行相同的命令。
5.配置另一台服务器作为从服务器:
在ServerA上:
CHANGE MASTER TO
  MASTER_HOST='ServerB_IP',
  MASTER_USER='repluser',
  MASTER_PASSWORD='123456',
  MASTER_LOG_FILE='log_file_name_from_ServerB',
  MASTER_LOG_POS=log_position_from_ServerB;
START SLAVE;
UNLOCK TABLES;
在ServerB上:
CHANGE MASTER TO
  MASTER_HOST='ServerA_IP',
  MASTER_USER='repluser',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='log_file_name_from_ServerA',
  MASTER_LOG_POS=log_position_from_ServerA;
START SLAVE;
UNLOCK TABLES;
6.验证复制状态:
SHOW SLAVE STATUS\G;

注意事项

  • 确保避免在两台服务器上同时修改同一数据,这可以通过使用自动递增的主键和为每个服务器设置不同的递增偏移量和步长来实现。
  • 主主复制更容易出现数据冲突和不一致,因此应该小心使用,并确保有冲突解决机制。
  • 建议使用半同步复制或GTID(全局事务标识符)来增强主主复制的健壮性。

7.半同步复制(mariadb与此不同)

MySQL 8.0引入了许多新功能和改进,其中包括对半同步复制的增强。半同步复制是一种确保数据在主服务器和至少一个从服务器之间安全复制的机制。在这种复制模式下,主服务器在提交事务前,会等待至少一个从服务器确认它已经收到并准备好提交事务的数据。

这种复制方式的好处是,它提供了比异步复制更高的数据一致性保证,但又不像同步复制那样对性能有极大影响。

半同步复制是MySQL提供的一种数据复制方式,它在标准的异步复制(主数据库写入操作后立即返回,不等从数据库确认)和同步复制(主数据库必须等从数据库确认写入成功后才能继续操作)之间提供了一种折中的解决方案。

在半同步复制模式下,主数据库在写入操作后会等待至少一个从数据库确认收到了写入的数据,然后再继续后续操作。这样可以确保数据的一致性和可靠性,防止在主数据库宕机的情况下数据丢失。

半同步复制的工作机制

  1. 事务提交:当一个事务在主服务器上提交时,主服务器将事务的变更写入到它的二进制日志(binlog)中。
  2. 等待从服务器确认:主服务器然后会等待至少一个配置的从服务器确认它已经收到了这些变更,并准备好将它们应用到自己的数据集上。
  3. 完成或超时:一旦主服务器收到了从服务器的确认,或者等待确认的时间超过了配置的超时时间(rpl_semi_sync_master_timeout),事务就会被认为是提交了。

1.主服务器安装半同步复制插件

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

# rpl_semi_sync_master 插件(主服务器插件)
这个命令安装了半同步复制的主服务器插件。这意味着它会让主服务器在提交事务时等待至少一个从服务器的确认。
rpl_semi_sync_master: 这是插件的名称,代表半同步复制的主服务器部分。
SONAME 'semisync_master.so': 这里的 SONAME 指定了插件库的名称。对于 Linux 系统,库的扩展名通常是 .so。对于 Windows 系统,库的扩展名会是 .dll。所以,如果你在 Windows 系统上执行这个命令,你需要将其修改为 semisync_master.dll。
这个插件会控制事务的提交过程,确保数据在返回给客户端之前已经被复制到了从服务器。

2.从服务器安装半同步复制插件

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

#  rpl_semi_sync_slave 插件(从服务器插件)
这个命令安装了半同步复制的从服务器插件。这意味着它会让从服务器在接收到主服务器的变更后立即发送确认
rpl_semi_sync_slave: 这是插件的名称,代表半同步复制的从服务器部分。
SONAME 'semisync_slave.so': 与主服务器插件相同,这里的 SONAME 指定了插件库的名称。
这个插件确保从服务器能够快速地确认接收到主服务器的变更,从而让主服务器能够继续处理其他事务。

这两个插件一起工作,提供了一个半同步的复制机制。主服务器插件负责在事务提交时等待从服务器的确认,而从服务器插件负责在接收到变更时快速发送确认。

3.配置主服务器

vim /etc/my.cnf
[mysqld]
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 3000  # 可根据需要调整,单位是毫秒
# 重启mysql服务
systemctl restart mysqld

4.配置从服务器

vim /etc/my.cnf
[mysqld]
rpl_semi_sync_slave_enabled = 1
# 重启mysql服务
systemctl restart mysqld

5.设置复制

在主服务器上创建一个用于复制的用户并授权:

CREATE USER 'replica'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'replica'@'%';
FLUSH PRIVILEGES;

6.在多个从服务器上配置复制:

CHANGE MASTER TO
  MASTER_HOST='主服务器IP地址',
  MASTER_USER='replica',
  MASTER_PASSWORD='password',
  MASTER_AUTO_POSITION=1;
START SLAVE;

MASTER_AUTO_POSITION = 1 是在 MySQL 复制配置中用来启用自动位置复制(GTID-based replication)的一个选项。
MASTER_AUTO_POSITION = 1
当你在从服务器上执行 CHANGE MASTER TO 命令来设置复制时,MASTER_AUTO_POSITION = 1 告诉 MySQL 使用 GTID 来管理复制的进度,而不是传统的文件位置方法。
这意味着 MySQL 会自动跟踪复制的进度,并确保从服务器始终能获取并应用主服务器上的所有变更。这也减少了人为错误的机会,因为你不需要手动管理复制进度。
使用 GTID 的复制方式更加现代、灵活,是推荐的配置方式,尤其是在复杂或高可用性要求的环境中。

设置 MASTER_AUTO_POSITION
为了使用 GTID 复制,主服务器和从服务器的 gtid_mode 配置选项必须被设置为 ON,并且所有的事务都必须被分配 GTID。当这些条件满足时,你可以在从服务器上执行类似以下命令来启用 GTID 复制:
CHANGE MASTER TO
  MASTER_HOST='主服务器地址',
  MASTER_USER='复制用户',
  MASTER_PASSWORD='复制密码',
  MASTER_AUTO_POSITION = 1;


GTID(全局事务标识符)
GTID,全称是全局事务标识符(Global Transaction Identifier),是 MySQL 在 5.6 版本中引入的一种机制,用于更简单、更可靠地管理复制。每个事务都会被分配一个唯一的标识符,不管它是在主服务器上执行还是被复制到从服务器上。这使得跟踪和管理复制变得更加简单,尤其是在复杂的复制配置和故障恢复情况下。

使用 GTID 的好处
简化故障恢复:在使用 GTID 的环境中,你不需要关心二进制日志文件和位置,这使得故障恢复变得更加直接和可靠。
事务一致性:GTID 保证了即使在主服务器发生切换的情况下,复制也能保持事务的一致性。
简化复制管理:GTID 让复制的配置和管理变得更加直观。


7.检查半同步状态

在主服务器上,可以通过以下命令检查半同步复制是否已经启动:
show global variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 1000       |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+

查看客户端个数的状态变量:
show global status like '%semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 2    |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| 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     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+


在从服务器上,可以通过以下命令检查半同步复制是否已经启动:
show variables like '%semi%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+---------------------------------+-------+

注意事项

  • 性能影响:半同步复制可能会对性能有一些影响,因为它增加了事务提交的延迟。主服务器需要等待从服务器确认它已经收到了变更,这可能会增加事务的提交时间。
  • 网络延迟:如果主服务器和从服务器之间的网络延迟较大,那么半同步复制的性能影响可能会更加明显。
  • 超时和回退:如果从服务器没有在rpl_semi_sync_master_timeout指定的时间内确认,主服务器将回退到异步复制模式,以避免事务提交被无限延迟。这个超时时间需要根据具体情况仔细配置。

8.复制过滤器

复制过滤器(Replication Filters)是 MySQL 中一组配置选项,允许你定义在复制过程中应该忽略或修改哪些数据库或表的变更。这可以帮助优化复制过程,防止不需要的数据被复制到从服务器。

复制过滤器主要有两种类型:

1. 用于从服务器的复制过滤器:

  • replicate-do-db: 指定要复制的数据库。只有当前默认数据库的事务会被复制。
  • replicate-ignore-db: 指定不要复制的数据库。
  • replicate-do-table: 指定要复制的表。格式为 db_name.table_name
  • replicate-ignore-table: 指定不要复制的表。格式为 db_name.table_name
  • replicate-wild-do-table: 使用通配符指定要复制的表。
  • replicate-wild-ignore-table: 使用通配符指定不要复制的表。

使用复制过滤器的注意事项:

  1. 复制过滤器应慎用:过滤器可能会导致主从服务器的数据不一致。只有在你完全理解其影响并确信这是你想要的行为时,才应使用复制过滤器。
  2. 与 GTID 的兼容性:当使用 GTID(全局事务标识符)进行复制时,一些复制过滤器可能无法使用。因为 GTID 要求主从服务器的所有事务都严格一致。
  3. 动态设置:某些复制过滤器可以在运行时动态设置,但有些需要在服务器启动时通过配置文件设置。
  4. 设置复制过滤器:使用 CHANGE REPLICATION FILTER 命令在运行时设置复制过滤器。
  5. 监控和审计:在使用复制过滤器时,应定期监控和审计系统,确保复制过程按预期运行,并且没有不一致发生。

2. 用于二进制日志和主服务器的复制过滤器:

  • binlog-do-db: 指定要写入二进制日志的数据库,这会影响所有的从服务器。
  • binlog-ignore-db: 指定不要写入二进制日志的数据库,这会影响所有的从服务器。
# 在从服务器上设置复制过滤器
#用 CHANGE REPLICATION FILTER 设置复制过滤器
#MySQL 5.7.6 及更高版本支持 CHANGE REPLICATION FILTER 命令,用于在运行时设置复制过滤器。
# 例如,如果你想要从服务器忽略 db1 数据库的所有变更,你可以运行:
CHANGE REPLICATION FILTER REPLICATE_IGNORE_DB = (‘db1’);
如果你只想复制 db2.table1,你可以运行:
CHANGE REPLICATION FILTER REPLICATE_DO_TABLE = (‘db2.table1’);

# 2.2 在配置文件中设置复制过滤器
你也可以在从服务器的 MySQL 配置文件(通常是 my.cnf 或 my.ini)中设置复制过滤器。
[mysqld]
replicate-ignore-db = db1
replicate-do-table = db2.table1
然后,你需要重启 MySQL 服务以使更改生效。

# 在主服务器上设置复制过滤器(可选)
如果你需要在主服务器上设置复制过滤器,例如,决定哪些数据库或表的变更应该写入二进制日志,你可以在 MySQL 配置文件中使用 binlog-do-db 和 binlog-ignore-db 选项。
例如,如果你只想将 db2 数据库的变更写入二进制日志,你可以在主服务器的配置文件中添加:
[mysqld]
binlog-do-db = db2

CHANGE MASTER TO用法

CHANGE MASTER TO 命令在 MySQL 中用于改变从服务器复制配置的参数。这是设置或更改从服务器与主服务器之间复制关系的核心命令。以下是该命令的一些选项的解释:

连接信息
MASTER_HOST: 主服务器的主机名或 IP 地址。
MASTER_PORT: 主服务器的端口号。
MASTER_USER: 用于连接到主服务器的 MySQL 用户名。
MASTER_PASSWORD: 用于连接到主服务器的密码。
MASTER_CONNECT_RETRY: 如果连接失败,从服务器重试连接的时间间隔(秒)。
MASTER_RETRY_COUNT: 从服务器尝试重新连接主服务器的次数。
NETWORK_NAMESPACE: 网络命名空间。
SSL 配置
MASTER_SSL: 是否使用 SSL 进行复制。
MASTER_SSL_CA: CA 证书的路径。
MASTER_SSL_CAPATH: CA 证书目录的路径。
MASTER_SSL_CERT: 从服务器的 SSL 证书路径。
MASTER_SSL_KEY: 从服务器的 SSL 私钥路径。
MASTER_SSL_CIPHER: 用于 SSL 的加密算法列表。
MASTER_SSL_VERIFY_SERVER_CERT: 是否验证主服务器的 SSL 证书。
MASTER_TLS_VERSION: 用于复制连接的 TLS 协议版本。
MASTER_TLS_CIPHERSUITES: TLSv1.3 密码套件。
复制位置
MASTER_LOG_FILE 和 MASTER_LOG_POS: 设置从主服务器的哪个二进制日志文件和位置开始复制。
RELAY_LOG_FILE 和 RELAY_LOG_POS: 设置从中继日志的哪个文件和位置开始执行。
MASTER_AUTO_POSITION: 是否使用全局事务标识符(GTID)来自动确定复制的位置。
复制行为
MASTER_HEARTBEAT_PERIOD: 主服务器和从服务器之间心跳的间隔时间。
MASTER_DELAY: 设置从服务器执行复制事件的延迟时间。
IGNORE_SERVER_IDS: 设置从服务器应该忽略的服务器 ID 列表。
高级配置
SOURCE_CONNECTION_AUTO_FAILOVER: 启用或禁用源自动故障转移。
ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS: 为匿名事务分配 GTID。
REQUIRE_ROW_FORMAT: 是否要求行格式。
REQUIRE_TABLE_PRIMARY_KEY_CHECK: 是否要求表有主键。
MASTER_COMPRESSION_ALGORITHMS: 设置复制压缩算法。
MASTER_ZSTD_COMPRESSION_LEVEL: 设置 Zstandard 压缩算法的压缩级别。
MASTER_BIND: 指定复制连接应绑定到的网络接口。
GET_MASTER_PUBLIC_KEY: 是否从主服务器获取公钥。
MASTER_PUBLIC_KEY_PATH: 主服务器公钥的路径。
GTID_ONLY: 是否仅使用 GTID

CHANGE REPLICATION SOURCE

CHANGE REPLICATION SOURCE TO option [, option] ... [ channel_option ]

option: {
    SOURCE_BIND = 'interface_name'
  | SOURCE_HOST = 'host_name'
  | SOURCE_USER = 'user_name'
  | SOURCE_PASSWORD = 'password'
  | SOURCE_PORT = port_num
  | PRIVILEGE_CHECKS_USER = {NULL | 'account'}
  | REQUIRE_ROW_FORMAT = {0|1}
  | REQUIRE_TABLE_PRIMARY_KEY_CHECK = {STREAM | ON | OFF | GENERATE}
  | ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS = {OFF | LOCAL | uuid}
  | SOURCE_LOG_FILE = 'source_log_name'
  | SOURCE_LOG_POS = source_log_pos
  | SOURCE_AUTO_POSITION = {0|1}
  | RELAY_LOG_FILE = 'relay_log_name'
  | RELAY_LOG_POS = relay_log_pos
  | SOURCE_HEARTBEAT_PERIOD = interval
  | SOURCE_CONNECT_RETRY = interval
  | SOURCE_RETRY_COUNT = count
  | SOURCE_CONNECTION_AUTO_FAILOVER = {0|1}
  | SOURCE_DELAY = interval
  | SOURCE_COMPRESSION_ALGORITHMS = 'algorithm[,algorithm][,algorithm]'
  | SOURCE_ZSTD_COMPRESSION_LEVEL = level
  | SOURCE_SSL = {0|1}
  | SOURCE_SSL_CA = 'ca_file_name'
  | SOURCE_SSL_CAPATH = 'ca_directory_name'
  | SOURCE_SSL_CERT = 'cert_file_name'
  | SOURCE_SSL_CRL = 'crl_file_name'
  | SOURCE_SSL_CRLPATH = 'crl_directory_name'
  | SOURCE_SSL_KEY = 'key_file_name'
  | SOURCE_SSL_CIPHER = 'cipher_list'
  | SOURCE_SSL_VERIFY_SERVER_CERT = {0|1}
  | SOURCE_TLS_VERSION = 'protocol_list'
  | SOURCE_TLS_CIPHERSUITES = 'ciphersuite_list'
  | SOURCE_PUBLIC_KEY_PATH = 'key_file_name'
  | GET_SOURCE_PUBLIC_KEY = {0|1}
  | NETWORK_NAMESPACE = 'namespace'
  | IGNORE_SERVER_IDS = (server_id_list),
  | GTID_ONLY = {0|1}
}

channel_option:
    FOR CHANNEL channel

server_id_list:
    [server_id [, server_id] ... ]

从服务器状态含义

SHOW SLAVE STATUS\G
连接信息
Slave_IO_State: 显示复制 I/O 线程的状态,这里是 “Waiting for source to send event”,意味着从服务器正等待主服务器发送更多的二进制日志事件。
Master_Host: 主服务器的主机名或IP地址,这里是 10.0.0.135。
Master_User: 用于复制的 MySQL 用户名,这里是 repluser。
Master_Port: 主服务器的端口号,这里是 3306。
Connect_Retry: 如果连接失败,从服务器将等待这么多秒后重试,这里是 60。
二进制日志信息
Master_Log_File: 从服务器正在读的主服务器的二进制日志文件名,这里是 mysql-bin.000001。
Read_Master_Log_Pos: 从服务器在主服务器的二进制日志文件中的读取位置,这里是 1228。
Relay_Log_File: 从服务器正在使用的中继日志文件名,这里是 Rocky9-relay-bin.000003。
Relay_Log_Pos: 从服务器在中继日志中的读取位置,这里是 690。
Relay_Master_Log_File: 中继日志事件来自的主服务器的二进制日志文件名,这里是 mysql-bin.000001。
Exec_Master_Log_Pos: 从服务器在主服务器的二进制日志中执行到的位置,这里也是 1228。
复制状态
Slave_IO_Running: 是否 I/O 线程正在运行,这里是 Yes。
Slave_SQL_Running: 是否 SQL 线程正在运行,这里是 Yes。
复制延迟
Seconds_Behind_Master: 从服务器落后于主服务器的时间(秒),这里是 0,表示没有延迟。
错误信息
Last_Errno: 上一个错误的错误码,这里是 0,表示没有错误。
Last_Error: 上一个错误的错误描述,这里为空,表示没有错误。
GTID 信息
Auto_Position: 是否使用 GTID 自动定位复制,这里是 0,表示没有启用。
其他
Slave_SQL_Running_State: 从服务器 SQL 线程的状态,这里是 “Replica has read all relay log; waiting for more updates”,表示从服务器已经读取了所有中继日志,并等待更多更新。
复制过滤设置
Replicate_Do_DB: 设置数据库级别的复制规则,复制指定的数据库。这里为空,意味着没有设置。
Replicate_Ignore_DB: 设置数据库级别的复制规则,忽略指定的数据库。这里为空,意味着没有设置。
Replicate_Do_Table: 设置表级别的复制规则,复制指定的表。这里为空,意味着没有设置。
Replicate_Ignore_Table: 设置表级别的复制规则,忽略指定的表。这里为空,意味着没有设置。
Replicate_Wild_Do_Table: 使用通配符设置表级别的复制规则,复制匹配模式的表。这里为空,意味着没有设置。
Replicate_Wild_Ignore_Table: 使用通配符设置表级别的复制规则,忽略匹配模式的表。这里为空,意味着没有设置。
复制进程的状态
Skip_Counter: 跳过复制的事件数量。这里为 0,意味着没有跳过事件。
Relay_Log_Space: 中继日志使用的磁盘空间总量(字节)。这里为 1777。
Until_Condition: 设置复制执行的终止条件。这里为 None,意味着没有设置终止条件。
Until_Log_File: 当设置了 Until 条件时,这个字段表示复制应停止的二进制日志文件名。这里为空。
Until_Log_Pos: 当设置了 Until 条件时,这个字段表示复制应停止的二进制日志位置。这里为 0。
SSL 设置
Master_SSL_Allowed: 是否允许通过 SSL 连接到主服务器。这里为 No。
以及其他一系列 SSL 相关的配置,例如 Master_SSL_CA_File,Master_SSL_CA_Path,Master_SSL_Cert 等,这里都为空或为 No,表示没有启用 SSL。
复制错误信息
Last_IO_Errno: 最后一次 IO 线程错误的错误码。这里为 0。
Last_IO_Error: 最后一次 IO 线程错误的描述。这里为空。
Last_SQL_Errno: 最后一次 SQL 线程错误的错误码。这里为 0。
Last_SQL_Error: 最后一次 SQL 线程错误的描述。这里为空。
GTID 和其他信息
Master_Server_Id: 主服务器的服务器 ID。这里为 135。
Master_UUID: 主服务器的唯一标识符。这里为 544070ec-73a1-11ee-b5ee-000c29bf6bda。
Master_Info_File: 保存复制配置信息的文件名。这里为 mysql.slave_master_info。
SQL_Delay: 从服务器延迟执行复制事件的时间。这里为 0,意味着没有延迟。
SQL_Remaining_Delay: 当使用 SQL_DELAY 时,这个字段显示剩余的延迟时间。这里为 NULL。
Slave_SQL_Running_State: 从服务器 SQL 线程的状态。这里为 Replica has read all relay log; waiting for more updates。
Master_Retry_Count: 当从服务器无法连接到主服务器时,将重试的次数。这里为 86400。
Auto_Position: 是否使用 GTID 模式进行自动定位。这里为 0,表示没有启用。
Replicate_Rewrite_DB: 用于重写复制的数据库名。这里为空。
Channel_Name: 多源复制的复制通道名称。这里为空,表示使用默认通道。
Master_TLS_Version: 用于复制连接的 TLS 版本。这里为空。

Percona-Toolkit

pt-query-digest: 分析 MySQL 查询日志并生成报告,帮助识别和优化慢查询。
pt-table-checksum: 检查 MySQL 数据库中表的数据一致性,可以用来找到主从复制中的不一致。
pt-table-sync: 同步 MySQL 数据库表之间的数据,常用于修复复制不一致。
pt-archiver: 用于高效归档老旧数据,而不影响数据库的性能。
pt-stalk: 收集 MySQL 服务器的诊断数据,用于性能分析和故障排除。
pt-show-grants: 显示 MySQL 用户的权限,用于备份和复制权限。
pt-online-schema-change: 在线修改大表的结构,而不阻塞对这些表的读写访问。
pt-deadlock-logger: 监控和记录 MySQL 死锁事件。
pt-mysql-summary: 提供 MySQL 服务器配置和状态的摘要信息。
pt-find: 在一组 MySQL 服务器上查找数据库、表或行。
pt-slave-delay:
pt-slave-find:
pt-slave-restart:

安装toolkit工具
https://www.percona.com/software/database-tools/percona-toolkit
yum -y install percona-toolkit-3.5.5-1.el8.x86_64.rpm
yum -y install percona-toolkit-3.5.5-1.el9.x86_64.rpm

pt-query-digest

pt-query-digest 是 Percona Toolkit 中用来分析 MySQL 查询的一个工具。它可以处理多种类型的输入,包括慢查询日志、常规查询日志、二进制日志、SHOW PROCESSLIST 输出以及从 tcpdump 捕获的 MySQL 协议数据。

这个工具的默认行为是按照查询的指纹将查询分组,并按照查询时间降序报告结果(即先报告最慢的查询)。

基本用法:
pt-query-digest [OPTIONS] [FILES] [DSN]
OPTIONS:一组用来定制工具行为的选项。
FILES:要分析的日志文件。如果省略,工具将从标准输入读取。
DSN:数据源名称,用于连接到 MySQL 数据库。它是可选的,但对于某些选项(如 --since 和 --until)是必需的。
重要选项说明:
--ask-pass:在连接到 MySQL 时提示输入密码。
--charset:设置默认字符集。
--config:指定要读取的配置文件列表。
--continue-on-error:即使遇到错误也继续解析。
--create-history-table:如果历史表不存在,则创建它。
--daemonize:转到后台运行并从 shell 分离。
--database:连接到指定数据库。
--defaults-file:只从给定文件读取 MySQL 选项。
--filter:丢弃不符合指定 Perl 代码条件的事件。
--group-by:指定用于分组事件的属性。
--history:在给定表中保存每个查询类的指标。
--host:连接到指定主机。
--limit:限制输出到指定的百分比或计数。
--output:设置查询分析结果的格式和打印方式。
--password:用于连接的密码。
--port:用于连接的端口号。
--progress:向标准错误输出进度报告。
--user:连接的 MySQL 用户名。
# 案例
1.分析慢查询日志
pt-query-digest /path/to/slow.log
这条命令会读取慢查询日志文件,并输出一个包含最慢查询的报告。报告中会显示每个查询的执行时间、锁定时间、返回的行数等信息。
2.分析在线运行的查询
pt-query-digest --processlist h=host,u=user,p=password
这个命令会连接到 MySQL 服务器,然后定期检查正在运行的查询。你可以通过 --interval 选项来设置检查的频率。
3. 分析 TCPDUMP 数据
如果你有通过 tcpdump 捕获的 MySQL 协议数据,你也可以使用 pt-query-digest 进行分析:
pt-query-digest --type tcpdump /path/to/tcpdump.log
4. 分析特定时间范围的查询
你可以使用 --since--until 选项来指定一个时间范围,只分析这个时间范围内的查询:
pt-query-digest --since '2023-10-01 00:00:00' --until '2023-10-01 23:59:59' /path/to/slow.log
5. 限制输出结果
如果你只对最慢的查询感兴趣,可以使用 --limit 选项来限制输出的结果数量:
pt-query-digest --limit 10 /path/to/slow.log
这个命令会输出执行时间最长的10个查询。
6. 分析查询并生成JSON格式的输出
如果你希望将分析结果用于其他工具处理,你可以使用 --output 选项生成JSON格式的输出:
pt-query-digest --output json /path/to/slow.log
7. 忽略某些类型的查询
你可以使用 --filter 选项来忽略某些类型的查询:
pt-query-digest --filter '$event->{arg} !~ m/^SELECT/' /path/to/slow.log
这个命令会忽略所有 SELECT 查询。

pt-table-checksum

pt-table-checksum 用于检查 MySQL 数据库表的数据一致性,可以用来找到主从复制中的不一致。pt-table-checksum 是 Percona Toolkit 的一部分,用于执行在线复制一致性检查。它通过在主库执行校验和查询,并将结果与从库进行比较,来发现复制数据是否不一致。如果检测到差异、警告或错误,工具的退出状态将非零。下面详细讲解这个命令的用法和一些常用选项。

pt-table-checksum [OPTIONS] [DSN]
[OPTIONS]: 一系列选项来定制检查的行为。
[DSN]: 一个可选的数据源名称,用来指定主库的连接信息。
常用选项
--binary-index: 该选项会修改 --create-replicate-table 的行为,使得复制表的上限和下限边界列被创建为 BLOB 数据类型。
--channel: 用于在连接到使用复制通道的服务器时指定通道名称。
--check-binlog-format: 检查所有服务器上的 binlog_format 是否相同(默认为是)。
--check-plan: 检查查询执行计划是否安全(默认为是)。
--chunk-index: 优先使用这个索引来分块表。
--chunk-index-columns: 只使用 --chunk-index 中前N个列。
--chunk-size: 每个校验和查询选择的行数(默认为1000)。
--chunk-time: 动态调整块大小,以便每个校验和查询的执行时间接近这个值(默认为0.5秒)。
--create-replicate-table: 如果复制数据库和表不存在,则创建它们(默认为是)。
--disable-qrt-plugin: 如果 QRT (Query Response Time) 插件启用,则禁用它
# 案例
# 检查所有数据库和表的一致性:
pt-table-checksum h=localhost,u=user,p=password

# pt-table-checksum --user=check --password=123456 --host=10.0.0.135 --no-check-binlog-format
前提必须有这个用户
create user 'check'@'10.0.0.%' identified with 'mysql_native_password' by '123456';
grant all on *.* to 'check'@'10.0.0.%';

pt-table-sync

pt-table-sync 用于同步 MySQL 数据库表之间的数据。这个工具可以用来解决主从复制中的数据不一致问题,或者将两个独立运行的 MySQL 服务器上的数据同步。pt-table-sync 使用了各种复杂的算法来检测和解决数据不一致的问题。

pt-table-sync [OPTIONS] [DSN]
OPTIONS:用来配置工具行为的选项。
DSN:数据源名称,指定要连接到的 MySQL 服务器。
重要选项:
--sync-to-master:将从服务器上的数据同步到主服务器。需要在从服务器上运行。
--databases 或 -d:指定要同步的数据库。
--tables 或 -t:指定要同步的表。
--execute:实际执行同步操作。如果不指定,pt-table-sync 将运行在打印模式,显示将要执行的 SQL 语句,但不实际执行它们。
--print:打印将要执行的 SQL 语句,而不是实际执行它们。
--verbose:增加输出的详细性。
--dry-run:模拟同步操作,但不执行任何数据库更改。
#案例 
1.同步从服务器的表数据到主服务器:
pt-table-sync --sync-to-master h=主服务器地址,u=用户名,p=密码,D=数据库,t=表 --dry-run h=从服务器地址
2.实际执行同步操作:
pt-table-sync --sync-to-master h=主服务器地址,u=用户名,p=密码,D=数据库,t=表 --execute h=从服务器地址
3.打印出将要执行的 SQL 语句:
pt-table-sync --sync-to-master h=主服务器地址,u=用户名,p=密码,D=数据库,t=表 --print h=从服务器地址

pt-table-sync --sync-to-master h=slave_host,u=root,p=your_password --print

pt-stalk

pt-stalk 用于收集 MySQL 服务器的诊断数据。

pt-stalk [OPTIONS]
# 当 CPU 使用率超过 90% 时收集数据:
pt-stalk --function=cpu --threshold=90

pt-online-schema-change

pt-online-schema-change 用于在线修改大表的结构。

pt-online-schema-change [OPTIONS] DSN
# 在线添加一个列:
pt-online-schema-change h=localhost,u=user,p=password,D=database,t=table --alter "ADD COLUMN newcol INT" --execute

pt-deadlock-logger

pt-deadlock-logger 用于监控和记录 MySQL 死锁事件。

监控本地数据库并记录死锁:
pt-deadlock-logger h=localhost,u=user,p=password

pt-mysql-summary

pt-mysql-summary 提供了 MySQL 服务器配置和状态的摘要信息,帮助理解服务器的当前状态。

pt-mysql-summary [OPTIONS]
# 获取本地 MySQL 服务器的摘要信息:
pt-mysql-summary --user=user --password=password

pt-show-grants

pt-show-grants 用于显示 MySQL 用户的权限,可以用于备份和复制权限。

pt-show-grants [OPTIONS]
# 显示所有用户的权限:
pt-show-grants --user=admin --password=password

pt-duplicate-key-checker

pt-duplicate-key-checker 找出和报告 MySQL 表中可能的重复索引。

pt-duplicate-key-checker [OPTIONS]
# 检查本地数据库的重复索引:
pt-duplicate-key-checker --user=user --password=password

pt-kill

pt-kill 用于监控 MySQL 查询并杀死执行时间过长的查询

pt-kill [OPTIONS]
# 杀死运行时间超过60秒的查询:
pt-kill --user=user --password=password --busy-time=60 --kill

pt-archiver

pt-archiver 用于高效归档老旧数据,而不影响数据库的性能。

pt-archiver [OPTIONS]
# 归档旧数据:
pt-archiver --source u=user,p=password,D=database,t=table --where "created_at < NOW() - INTERVAL 1 YEAR" --limit 1000 --commit-each

pt-find

pt-find 是 Percona Toolkit 的一部分,用于搜索和查找MySQL服务器上的数据库对象,如数据库、表、视图、存储过程等。这个工具非常灵活,允许你根据各种条件来查找对象,例如根据表的大小、行数、创建时间等。

pt-find [OPTIONS] [DSN]
OPTIONS:可选参数,用于定义搜索的条件和输出的格式。
DSN:数据源名称,用于指定要连接的MySQL服务器的详细信息。

pt-find 是 Percona Toolkit 的一部分,用于搜索和查找MySQL服务器上的数据库对象,如数据库、表、视图、存储过程等。这个工具非常灵活,允许你根据各种条件来查找对象,例如根据表的大小、行数、创建时间等。

以下是一些常用的 pt-find 的选项和用法的详细说明:

语法
sh
Copy code
pt-find [OPTIONS] [DSN]
OPTIONS:可选参数,用于定义搜索的条件和输出的格式。
DSN:数据源名称,用于指定要连接的MySQL服务器的详细信息。
常用选项
--database 或 -d: 指定要搜索的数据库。
--table 或 -t: 指定要搜索的表。
--engine: 指定要搜索的存储引擎。
--size: 根据表的大小来搜索。
--rows: 根据表的行数来搜索。
--print: 打印找到的对象。
--exec: 执行给定的SQL语句。

pt-slave-delay

pt-slave-delay 是 Percona Toolkit 中的一个工具,用于设置一个MySQL复制从服务器的复制延迟。这意味着你可以配置从服务器以延迟一定时间来应用从主服务器复制过来的二进制日志事件。这对于在从服务器上创建备份或进行其它需要数据一致性但不需要实时更新的操作非常有用。

pt-slave-delay [OPTIONS] [DSN]
--delay: 设置复制延迟的时间,单位是秒。
--start: 启动延迟复制。
--stop: 停止延迟复制。
# 将从服务器的复制延迟设置为3600秒(1小时)。
pt-slave-delay --delay 3600 h=your_host,u=your_user,p=your_password

pt-slave-find

pt-slave-find 是一个用来找到并显示所有连接到指定 MySQL 服务器的复制从服务器的工具。

pt-slave-find [OPTIONS] [DSN]
选项:
--recursion-method: 设置查找从服务器的方法。
--max-depth: 设置查找从服务器的最大深度。
pt-slave-find h=your_host,u=your_user,p=your_password
这个命令将显示连接到指定服务器的所有从服务器。
[root@Rocky8 ~]#pt-slave-find h=10.0.0.135,u=check,p=123456
10.0.0.135
Version         8.0.32
Server ID       135
Uptime          05:56:56 (started 2023-10-26T10:22:47)
Replication     Is not a slave, has 2 slaves connected, is not read_only
Filters
Binary logging  ROW
Slave status
Slave mode      STRICT
Auto-increment  increment 1, offset 1
InnoDB version  8.0.32
+- 10.0.0.131
   Version         8.0.32
   Server ID       131
   Uptime          05:51:36 (started 2023-10-26T10:28:07)
   Replication     Is a slave, has 0 slaves connected, is not read_only
   Filters
   Binary logging  ROW
   Slave status     seconds behind, not running, error 1007
   Slave mode      STRICT
   Auto-increment  increment 1, offset 1
   InnoDB version  8.0.32
+- 10.0.0.134
   Version         8.0.32
   Server ID       134
   Uptime          05:52:31 (started 2023-10-26T10:27:12)
   Replication     Is a slave, has 0 slaves connected, is not read_only
   Filters
   Binary logging  ROW
   Slave status    0 seconds behind, running, no errors
   Slave mode      STRICT
   Auto-increment  increment 1, offset 1
   InnoDB version  8.0.32
[root@Rocky8 ~]#


pt-slave-restart

pt-slave-restart 是用来安全重启 MySQL 从服务器复制的工具,它确保在停止和开始复制之间的时间尽可能短,减少复制延迟。

pt-slave-restart [OPTIONS] [DSN]
选项:
--wait: 设置在尝试重新启动复制之前等待的时间,单位是秒。
--tries: 设置尝试重新启动复制的最大次数。
#这个命令将尝试在从服务器上重新启动复制,最多尝试3次,每次等待60秒。
pt-slave-restart --wait 60 --tries 3 h=your_host,u=your_user,p=your_password

9.服务器选项、系统变量等

服务器选项、系统变量和状态变量的区别

在MySQL中,服务器选项、系统变量和状态变量都是配置和监视数据库服务器行为的重要工具。然而,它们的目的和用途是不同的。以下是这三者之间的区别及其详细说明:

服务器选项:

  • 定义: 服务器选项是在启动MySQL服务器时设置的参数。它们通常在命令行或my.cnf(在Unix/Linux上)或my.ini(在Windows上)的配置文件中定义。
  • 作用: 服务器选项用于初始化MySQL服务器的设置,如数据目录的位置、错误日志文件的位置等。
  • 修改方式: 要更改服务器选项,通常需要编辑配置文件并重新启动MySQL服务器。
  • 示例: --datadir=/path/to/data--port=3306

系统变量:

  • 定义: 系统变量是MySQL服务器运行时的配置参数。这些变量控制许多方面的操作,如查询缓存大小、最大连接数等。
  • 作用: 系统变量可以用于优化服务器性能、资源使用和许多其他方面的行为。
  • 修改方式: 许多系统变量可以在运行时使用SET命令进行更改,而不需要重启服务器。但某些系统变量,如innodb_buffer_pool_size,需要重启服务器才能更改。
  • 查询方式: 可以使用SHOW VARIABLESSELECT @@var_name来查询。
  • 示例: max_connections, query_cache_size

状态变量:

  • 定义: 状态变量为数值,提供关于MySQL服务器操作的信息。它们不是用于配置服务器,而是用于监控其性能和行为。
  • 作用: 状态变量可以帮助数据库管理员了解服务器的健康状况,如查询的数量、打开的表的数量、缓存命中率等。这些信息可以用于故障排查和性能优化。
  • 修改方式: 你不能修改状态变量的值,因为它们是由服务器基于其操作动态生成的。
  • 查询方式: 可以使用SHOW STATUS命令查询。
  • 示例: Com_select, Threads_connected

总结:

  • 服务器选项是启动服务器时设置的,并通常在配置文件中定义。
  • 系统变量是控制服务器运行时行为的参数,可以在运行时进行更改。
  • 状态变量是表示服务器操作统计信息的数值,用于监控和诊断。

如何区分他们:

查看MySQL官方文档
MySQL的官方文档详细列出了所有的启动选项和系统变量。你可以在文档中查找特定的选项或变量来确定它的类型。

https://dev.mysql.com/doc/refman/8.0/en/server-option-variable-reference.html

使用SHOW命令

  • 使用SHOW VARIABLES;命令可以列出所有的系统变量。
  • 使用SHOW GLOBAL VARIABLES;可以列出所有的全局系统变量。 如果你可以在这些命令的输出中看到特定的名称,那么它是一个系统变量。

使用mysqld命令
你可以在命令行中运行mysqld --help --verbose。这将列出mysqld服务器的所有启动选项和系统变量。启动选项通常以--前缀开始,并直接给出,例如--datadir。而系统变量在这里也会被列出,但是它们可以在运行时使用SET命令进行修改。

注意事项

  • 有些MySQL选项既是启动选项也是系统变量。这意味着它们可以在启动时通过命令行或配置文件设置,也可以在运行时通过SET命令进行修改(前提是这些变量是动态的)。
  • 不是所有的系统变量都是动态的。有些变量只能在启动时设置,并在整个服务器会话中保持不变。

log_bin和sql_log_bin的区别

在 MySQL 中,log_binsql_log_bin 是与二进制日志(Binary Logging)相关的参数和变量,但它们的用途和影响是不同的。

log_bin:

  • 类型:配置参数

  • 描述:这是一个服务器启动参数,用于指定是否启用二进制日志功能,以及二进制日志文件的名称前缀。

  • 用途:当你打开 log_bin,MySQL 会记录所有更改数据库内容的 SQL 语句的日志。这对于数据复制和增量备份都是必要的。

  • 设置方法:你需要在 MySQL 的 my.cnfmy.ini 配置文件中设置,或在启动服务器时通过命令行参数设置。

    示例:

    log_bin=/data/mysql/logbin/mysql-bin
    # 默认情况
    log_bin=/var/log/mysql/mysql-bin.log
    

    注意事项:一旦你启动了二进制日志功能,日志文件可能会迅速增长。你需要定期备份并清理这些日志文件,或使用 expire_logs_days 参数来自动清理旧的日志文件。

sql_log_bin:

  • 类型:会话级变量

  • 描述:这是一个动态的会话级变量,可以为当前会话启用或禁用二进制日志记录。

  • 用途:假如你临时不希望某个操作被记录到二进制日志中(例如,不希望该操作被复制到从服务器),你可以为那个会话临时禁用 sql_log_bin

  • 设置方法:你可以在 SQL 语句中为特定的会话设置此变量。

    示例:

    SET sql_log_bin = 0;
    

    注意事项:禁用 sql_log_bin 仅影响当前会话,不影响其他会话或服务器级别的二进制日志功能。

read_only

在MySQL中,read_only是一个系统变量,也是一个服务器启动选项,这意味着它可以在MySQL服务器启动时通过命令行或配置文件设置,也可以在服务器运行时动态地修改它(前提是你有足够的权限)。它可以用来限制服务器上的写操作。下面是关于read_only的详细说明:

作为服务器启动选项

  • 在MySQL的配置文件 my.cnfmy.ini 中设置:
[mysqld]
read_only = ON|TRUE
  • 或者在启动 mysqld 时通过命令行设置:
mysqld --read-only

作为系统变量

  • 在运行时,你可以查询它的值:
SHOW GLOBAL VARIABLES LIKE 'read_only';
  • 也可以动态地设置它的值:
设置为只读:
SET GLOBAL read_only = ON|TRUE;
设置为可写:
SET GLOBAL read_only = FALSE;

用途

  • 复制设置:在主从复制的环境中,通常会将从服务器设置为 read_only,以防止数据被修改。这确保所有的数据更改都发生在主服务器上,然后被复制到从服务器。但是如果是从服务器要变成主服务器,要把read_only关闭,并且要确保二进制开启。
  • 维护窗口:在进行数据库维护或升级时,可以暂时设置 read_only,以确保数据不被修改。
  • 只读实例:在某些应用场景中,你可能需要一个只读的数据库实例来处理大量的查询负载而不进行任何写入。

注意事项

  • 尽管设置了 read_only,具有SUPER权限的用户仍然可以进行写入操作。
  • read_only 设置为 TRUE 时,并不会终止正在进行的写入操作,但它会阻止新的写入操作。
  • 使用 read_only 时要小心,确保应用程序和用户能够适当地处理这种只读状态,以防止出现意外错误或问题。

log_slave_updates

log_slave_updates 是MySQL中的一个重要配置选项,尤其在复制的上下文中。它决定了一个从服务器是否将其从主服务器接收到的二进制日志事件记录到自己的二进制日志中。

定义: 当 log_slave_updates 被设置为 TRUE1 时,从服务器会将从主服务器接收并执行的更新事件写入其自己的二进制日志。如果设置为 FALSE0(默认),则从服务器不会在其二进制日志中记录这些事件。

用途

  • 链式复制:如果你有一个多级复制架构(例如:主 -> 从1 -> 从2),那么从1必须开启 log_slave_updates,这样从2才能从从1中获取更新,这个用于级联复制的架构中。
  • 备份和点时间恢复:开启 log_slave_updates 使得你可以从一个从服务器备份二进制日志,并能使用这些日志进行点时间恢复。
  • 延迟复制:对于设置了复制延迟的从服务器,开启 log_slave_updates 可以确保其它从服务器从它那里复制时,复制的内容是完整的。

如何设置

  • 在MySQL的配置文件 (my.cnfmy.ini) 中设置:
[mysqld]
log_slave_updates = 1
  • 或者在启动 mysqld 时通过命令行设置:
mysqld --log-slave-updates

如果你的MySQL版本支持在线更改这个设置(例如,MySQL 5.7.6或更高版本),你也可以动态地修改它:

SET GLOBAL log_slave_updates = ON;

注意事项

  • 开启 log_slave_updates 会增加从服务器的磁盘I/O,因为它需要写更多的二进制日志数据。在开启此选项之前,需要考虑其对性能的影响。
  • 如果你使用GTID(全局事务标识符)复制,那么 log_slave_updates 必须在所有从服务器上启用。

sql_slave_skip_counter

在MySQL复制环境中,偶尔可能会遇到主从、主主服务器之间的数据不一致或其他错误。这时,为了继续复制过程,MySQL提供了一些机制来跳过某些错误。sql_slave_skip_counterslave_skip_errors 就是这些机制中的两个。

  • 定义:这是一个会话级别的系统变量,允许你指定从服务器应该跳过的事件数。
  • 用途:当从服务器在应用二进制日志事件时遇到错误,你可以设置此变量以跳过指定数量的事件并继续复制过程。
  • 如何使用
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter = N; -- N是你想跳过的事件数。
START SLAVE;

意事项

  • 使用此变量可能会导致主从数据不一致,所以在使用之前,确保你了解跳过这些事件的后果。
  • 通常,它应该作为临时解决方案来使用,长期依赖它可能会导致问题。

slave_skip_errors

  • 定义:这是一个全局静态系统变量,允许你定义从服务器在复制过程中可以安全忽略的错误类型。在MySQL 8.0版本中,slave_skip_errors 是一个全局系统变量,但它是静态的,这意味着它只能在MySQL服务器启动时通过命令行或配置文件设置,而不能在运行时动态修改。
  • 用途:它使你可以持续地忽略特定类型的错误,而不必每次都手动设置sql_slave_skip_counter
  • 如何使用:你可以指定错误代码、错误名称或“All”(表示所有错误)。
[mysqld]
slave_skip_errors = '1062,1053'
  • 或者在启动mysqld时通过命令行进行设置:
mysqld --slave-skip-errors='1062,1053'

注意:该变量的默认值是空字符串,这意味着默认情况下不会跳过任何错误。

由于不能在运行时动态更改 slave_skip_errors,所以如果你需要修改它的值,你必须先停止MySQL服务器,然后再重新启动它。

skip-slave-start

skip-slave-start 是MySQL中的一个启动选项。当你使用这个启动选项,从服务器会在启动时不自动启动复制线程。这意味着即使你在之前启动的时候正在进行复制,当MySQL服务器再次启动并带有 skip-slave-start 选项时,复制不会自动开始。

用途

  • 有时,为了维护或其他目的,你可能不希望MySQL从服务器在启动时立即开始复制。使用 skip-slave-start 可以帮助实现这一目的。
  • 这也可以给管理员提供时间来手动检查或修改复制设置,而不必担心复制在此期间自动启动

如何使用

  • 通过命令行启动 mysqld 时:
mysqld --skip-slave-start
  • 或者在MySQL的配置文件中设置:
[mysqld]
skip-slave-start

启动后的操作

尽管使用了 skip-slave-start,你仍然可以在服务器启动后手动开始复制:

START SLAVE;

注意skip-slave-start 只是一个启动选项,并不是一个持久的设置。这意味着,如果你在下次启动MySQL服务器时没有指定它,复制会像往常一样自动开始(前提是之前已经配置了复制并且是活动的)。

relay-log

relay-log:这是MySQL配置中的一个选项,用于指定从服务器上用于保存从主服务器接收的二进制日志事件名或路径,也叫中继日志。

relay-bin:这是中继日志文件的基础名称。当MySQL开始写入这些文件时,它会添加一个扩展名(例如 Rocky9-relay-bin.000001)。随着时间的推移,这些文件会继续增加(例如 Rocky9-relay-bin.000002, Rocky9-**relay**-bin.000003 等等)。

为什么中继日志很重要?

当从服务器从主服务器请求二进制日志事件时,这些事件首先被写入从服务器的中继日志。然后,从服务器的SQL线程读取中继日志,并在从服务器上执行这些事件,从而保持从服务器的数据与主服务器同步。

为什么要配置它?

尽管有默认的中继日志名称,但在某些情况下,你可能希望更改它,例如:

  • 如果你希望将中继日志文件放在不同的磁盘或文件系统上,以分隔其他MySQL数据文件。
  • 如果你运行多个MySQL实例,并希望每个实例都有明确的日志文件命名约定。

注意事项

确保你为中继日志配置了适当的磁盘空间,因为在复制过程中,这些日志可能会增长,尤其是当从服务器与主服务器断开连接并在稍后重新连接时。虽然这些日志文件在事件被SQL线程执行后会被自动删除,但在高写入负载的情况下,它们可能会占用大量的磁盘空间。

总的来说,relay-log=relay-bin 配置是告诉从服务器将接收到的二进制日志事件写入以 relay-bin 为基础名称的文件中。

FLUSH TABLES WITH READ LOCK

当涉及到MySQL复制或备份时,FLUSH TABLES WITH READ LOCK; 命令是一个非常重要的命令。它的作用和重要性可以从其命令名称中分解:

  1. FLUSH TABLES:这部分的命令实际上会刷新MySQL的表,确保所有挂起的更改都已写入磁盘。这对于确保数据的完整性尤为重要,尤其是在备份或开始复制过程之前。
  2. WITH READ LOCK:这部分是命令的关键。当执行此命令时,它会为所有表立即获取一个全局的读锁。这意味着,当锁定有效时,可以从任何表中读取数据,但不能向任何表中写入数据。

以下是FLUSH TABLES WITH READ LOCK;的主要应用场景:

  • 创建物理备份:如果你正在使用如mysqldump这样的工具创建一个物理备份,你可能希望在备份开始之前确保数据库处于一致的状态。执行此命令可以确保在备份过程中不会有新的写入。
  • 配置复制:在设置MySQL的主-从复制时,为了获得二进制日志的当前位置(使用SHOW MASTER STATUS;),通常会先锁定主服务器,确保没有进一步的数据变更。

然而,需要注意的是,在执行FLUSH TABLES WITH READ LOCK;后,你应该尽快完成接下来的任务(如备份或检查二进制日志位置),然后立即释放锁,以免阻塞其他写入操作。你可以使用UNLOCK TABLES;命令来释放锁。

此外,还应考虑到在高并发的生产环境中,长时间锁定可能会导致显著的性能下降和应用程序延迟,因此应谨慎使用此命令。在一些情况下,如使用Percona XtraBackup或其他热备份工具,你可能不需要执行这个命令,因为这些工具通常有自己的机制来确保数据的一致性。

rpl_semi_sync_master_enabled

sqlCopy code
SET GLOBAL rpl_semi_sync_master_enabled = 1;

这个命令用来启用半同步复制在主服务器上的功能。当设置为 1(或 ON)时,它会告诉主服务器在事务提交时等待从服务器的确认。

  • rpl_semi_sync_master_enabled = 1: 启用半同步复制。
  • rpl_semi_sync_master_enabled = 0: 禁用半同步复制,复制将回退到异步模式。

rpl_semi_sync_master_timeout

sqlCopy code
SET GLOBAL rpl_semi_sync_master_timeout = 3000;

这个变量设置了主服务器等待从服务器确认的最大时间(以毫秒为单位)。在上面的例子中,它被设置为 3000 毫秒,即 3 秒。

  • 如果在这个时间内,主服务器收到了从服务器的确认,事务就会被提交。
  • 如果在这个时间内,主服务器没有收到从服务器的确认,主服务器将停止等待,事务也会被提交,但复制将回退到异步模式,直到从服务器再次能够及时确认接收到的变更。

调整这个超时时间是一个权衡性能和数据一致性的决策。设置较低的超时时间可以减少在从服务器延迟或不可用时主服务器上的事务提交延迟,但也可能导致半同步复制更频繁地回退到异步模式。设置较高的超时时间可以增加数据一致性保证,但也可能在从服务器有问题时导致主服务器上的事务提交延迟。

使用 SET GLOBAL 使这些变量的更改在运行时立即生效,但要使更改在服务器重启后依然有效,你还需要在 MySQL 的配置文件(通常是 my.cnfmy.ini)中设置这些变量。

rpl_semi_sync_slave_enabled

rpl_semi_sync_slave_enabled 是一个 MySQL 系统变量,用于控制从服务器上半同步复制的行为。当这个变量被设置为 1(或 ON)时,它启用半同步复制在从服务器端的功能。

设置 rpl_semi_sync_slave_enabled

SET GLOBAL rpl_semi_sync_slave_enabled = 1;
# 使用 SET GLOBAL 修改 MySQL 配置变量将立即生效,但这些更改在数据库重启后将不会保留。为了确保在重启后设置仍然有效,你需要在 MySQL 的配置文件中进行更改。
或者
[mysqld]
rpl_semi_sync_slave_enabled = 1

这个命令会启用半同步复制在从服务器端的功能,这意味着从服务器会在接收到事务变更后立即发送确认给主服务器。这样,主服务器在提交事务前可以等待从服务器的确认,确保数据的一致性。

  • rpl_semi_sync_slave_enabled = 1: 启用半同步复制在从服务器端。
  • rpl_semi_sync_slave_enabled = 0: 禁用半同步复制在从服务器端,从服务器将不会发送确认给主服务器,复制将回退到异步模式。

为什么要启用半同步复制

半同步复制确保了在主服务器上提交的事务已经被至少一个从服务器接收并记录到它的 relay log(中继日志)中。这提供了比异步复制更强的数据一致性保证,有助于防止数据丢失的情况发生,特别是在主从切换或其他复制拓扑变更的情况下。

启用半同步复制通常会增加事务的提交延迟,因为主服务器需要等待从服务器的确认,但它提供了更强的数据安全性。

Seconds_Behind_Master

Seconds_Behind_Master 显示从服务器落后于主服务器的时间(以秒为单位)。一个值为 0 表示从服务器已经赶上了主服务器,正在实时复制变更。

Slave_IO_Running

Slave_IO_Running 显示从服务器上的 I/O 线程是否正在运行。I/O 线程负责从主服务器拉取二进制日志事件。

  • Slave_IO_Running: Yes 表示 I/O 线程正在运行。
  • Slave_IO_Running: No 表示 I/O 线程没有运行,可能是因为遇到了错误,或者复制没有被启动。

Slave_SQL_Running

Slave_SQL_Running 显示从服务器上的 SQL 线程是否正在运行。SQL 线程负责执行二进制日志中的事件来应用变更。

  • Slave_SQL_Running: Yes 表示 SQL 线程正在运行。
  • Slave_SQL_Running: No 表示 SQL 线程没有运行,可能是因为遇到了错误,或者复制没有被启动。

如何检查这些状态

你可以使用 SHOW SLAVE STATUS\G 命令来查看从服务器的复制状态,包括上面提到的这些指标。

10. mycat2

Mycat 是一个数据库中间件,它的主要目的是提供数据库分布式解决方案和数据库集群解决方案。Mycat背后的原理是基于著名的开源数据库中间件Cobar,由阿里巴巴开发并且开源。Mycat在Cobar的基础上进行了增强,并添加了更多功能。

以下是Mycat的几个核心原理:

  1. SQL解析:Mycat 接收到客户端发来的SQL语句后,首先进行SQL解析,了解这个SQL语句的含义,包括查询哪些列,哪些条件等。
  2. SQL路由:Mycat 会根据配置文件中定义的数据节点和分片规则,决定这个SQL语句应该路由到哪个数据库服务器执行。
  3. SQL改写:在某些情况下,Mycat 会对SQL语句进行改写,以适应后端数据库的特定要求或者优化查询性能。
  4. 结果集合并:如果SQL语句被路由到多个数据库服务器,Mycat 会收集所有服务器返回的结果集,然后进行合并、排序等操作,以保证最终返回给客户端的结果是正确的。
  5. 读写分离:Mycat 支持读写分离配置,可以将读操作和写操作分别路由到不同的数据库服务器。
  6. 分库分表:Mycat 可以实现数据库的水平拆分,将数据分散到多个数据库实例中,这样做可以提升系统的可扩展性和负载能力。
  7. 高可用性:Mycat 通过心跳检测后端数据库的状态,可以在后端数据库出现问题时,将请求转发到其他健康的数据库服务器,从而提供服务的高可用性。
  8. 缓存:Mycat 还可以对查询结果进行缓存,提高数据库的读取性能。

Mycat 通过这些原理和机制,使得应用能够以较低的成本实现数据库的高可用性、高性能和高扩展性。它对应用程序透明,应用程序无需修改代码就可以使用Mycat来分布式处理数据库请求。

mycat配置文件夹
		+ clusters
		    - prototype.cluster.json //无集群的时候自动创建
			- c0.cluster.json
                        - c1.cluster.json
        + datasources
        	- prototypeDs.datasource.json //无数据源的时候自动创建
        	- dr0.datasource.json
        	- dw0.datasource.json
        + schemas
        	- db1.schema.json
        	- mysql.schema.json
        + sequences
        	- db1_schema.sequence.json
 -server.json //服务器配置
 -state.json //mycat运行状态,包含集群选举的主节点信息,配置时间戳

10.1 安装mycat2

1.MyCat2是基于Java开发的,所以他的运行环境是比较简单的,只需要安装JDK即可。接下来准备一台Linux机器,搭建JDK8版本。初始搭建时,建议在这台服务器上也搭建一个MySQL服务。
yum -y install java-1.8.0-openjdk
然后,为了上手使用MyCat2,需要搭建后端测试的MySQL服务。接下来会准备两个MySQL8.0服务实例,并搭建完成MySQL的主从同步集群。
2.下载mycat
mycat2运行环境框架:http://dl.mycat.org.cn/2.0/install-template/mycat2-install-template-1.20.zip
mycat2 jar包:http://dl.mycat.org.cn/2.0/1.21-release/mycat2-1.21-release-jar-with-dependencies.jar # 必须是1.21,1.22影响后面的工具使用
下载好的运行框架解压,把mycat2 jar包放在运行环境框架目录下的lib里
unzip mycat2-install-template-1.20.zip -d /apps/
chmod +x /apps/mycat/bin/
# 配置环境变量
echo PATH=/apps/mycat/bin:$PATH > /etc/profile.d/mycat.sh
source /etc/profile.d/mycat.sh

10.2 datasources

3.数据源(datasource):配置Mycat连接的数据源信息
修改以下三项,指向自己真实的物理数据库地址
vim /apps/mycat/conf/datasources/prototypeDs.datasource.json
{
    "dbType":"mysql",
    "idleTimeout":60000,
    "initSqls":[],
    "initSqlsGetConnection":true,
    "instanceType":"READ_WRITE",
    "maxCon":1000,
    "maxConnectTimeout":3000,
    "maxRetryCount":5,
    "minCon":1,
    "name":"prototypeDs",
    "password":"123456",
    "type":"JDBC",
    "url":"jdbc:mysql://10.0.0.131:3306/hellodb?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
    "user":"root",
    "weight":0
}
这三项
"password":"123456",
 "url":"jdbc:mysql://10.0.0.131:3306/hellodb?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
 "user":"root",
#字段含义
# dbType:数据库类型,mysql
# name:在MyCat2中定义的数据源名字
# user, password,url: 实际数据库的JDBC属性,url访问数据库地址
# type:数据源类型,默认 JDBC
# idleTimeout:空闲连接超时时间
# initSqls:初始化sql
# initSqlsGetConnection:对于 jdbc 每次获取连接是否都执行 initSqls
# instanceType:配置实例只读还是读写
    可选值:READ_WRITE,READ,WRITE
#weight :负载均衡权重
# 连接相关配置
    "maxCon": 1000,
    "maxConnectTimeout": 3000,
    "maxRetryCount": 5,
    "minCon": 1,

10.3 users

4.用户(user): 配置MyCat客户端用户相关信息
 vim /apps/mycat/conf/users/root.user.json
 修改mycat登录的用户名和地址,注意用户名与文件名一直,如username改成yinlt,文件名就是yinlt.user.json
 {
    "dialect":"mysql",
    "ip":null,
    "password":"xyy123456",
    "transactionType":"xa",
    "username":"root"
}
字段含义:
#ip:客户端访问ip,建议为空,填写后会对客户端的ip进行限制
# username:用户名
# password:密码
# isolation:设置初始化的事务隔离级别
    READ_UNCOMMITTED:1
    READ_COMMITTED:2
    REPEATED_READ:3,默认
    SERIALIZABLE:4
# transactionType:事务类型
    可选值:
    proxy 本地事务,在涉及大于 1 个数据库的事务,commit 阶段失败会导致不一致,但是兼容性最好
    xa 事务,需要确认存储节点集群类型是否支持 XA可以通过语句实现切换
    可以通过语句实现切换set transaction_policy = 'xa' , set transaction_policy = 'proxy' 
    可以通过语句查询SELECT @@transaction_policy

10.4 clusters

4.集群(cluster):配置集群信息
所在目录 mycat/conf/clusters
vim /apps/mycat/conf/clusters/prototype.cluster.json
{
    "clusterType":"MASTER_SLAVE",
    "heartbeat":{
        "heartbeatTimeout":1000,
        "maxRetry":3,
        "minSwitchTimeInterval":300,
        "slaveThreshold":0
    },
    "masters":[
        "prototypeDs"
    ],
    "maxCon":200,
    "name":"prototype",
    "readBalanceType":"BALANCE_ALL",
    "switchType":"SWITCH"
}
#字段含义
# clusterType:集群类型。主要用得多的是 SINGLE_NODE
    可选值:
    SINGLE_NODE:单一节点
    MASTER_SLAVE:普通主从
    GARELA_CLUSTER:garela cluster/PXC 集群
    MHA:MHA 集群
    MGR:MGR 集群
# readBalanceType:查询负载均衡策略
    可选值:
    BALANCE_ALL(默认值): 获取集群中所有数据源
    BALANCE_ALL_READ: 获取集群中允许读的数据源
    BALANCE_READ_WRITE:获取集群中允许读写的数据源,但允许读的数据源优先
    BALANCE_NONE: 获取集群中允许写数据源,即主节点中选择
# switchType:切换类型
    可选值:
    NOT_SWITCH:不进行主从切换
    SWITCH:进行主从切换

10.5 schemas

5.逻辑库表(schema):配置逻辑库表,实现分库分表
schema配置
{库名}.schema.json保存在schemas文件夹
所在目录 mycat/conf/schemas
vim /apps/mycat/conf/schemas/hellodb.schema.json
{
    "schemaName": "hellodb",
    "targetName": "prototypeDs"
}
vim mycat/conf/schemas/mydb1.schema.json
#库配置
{
    "schemaName": "mydb",
    "targetName": "prototype"
}
# schemaName:逻辑库名
# targetName:目的真实数据源或集群
# normalTables:常规表。如果物理表已经存在或者在每次启动服务时需要加载表定义,就可以写在这里。
targetName自动从prototype目标加载test库下的物理表或者视图作为单表,prototype必须是mysql服务器

#单表配置
{
    "schemaName": "mysql-test",
    "normalTables": {
    "role_edges": {
    "createTableSQL":null,//可选
    "locality": {
    "schemaName": "mysql",//物理库,可选
    "tableName": "role_edges",//物理表,可选
    "targetName": "prototype"//指向集群,或者数据源
    }
}

10.6 启动mycat2

# 配置逻辑
启动mycat
mycat start
[root@mycat ~]#tail /apps/mycat/logs/wrapper.log
INFO   | jvm 1    | 2023/10/28 23:40:41 | 2023-10-28 23:40:41,215[INFO]com.alibaba.druid.pool.DruidDataSource.init:990{dataSource-1} inited
INFO   | jvm 1    | 2023/10/28 23:40:46 | 2023-10-28 23:40:46,787[INFO]io.mycat.config.MycatRouterConfigOps.recoveryXA:735readXARecoveryLog start
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,967[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 488b61e0-698d-4568-8844-c9aea2e492f5 started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,968[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 10347482-f113-4d6b-b4ac-036699789f7c started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,968[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 8a322925-5877-408b-8870-825b43123a4b started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,968[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 91c5045c-dcff-4d6d-92cc-cb005a04691e started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,970[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 2ebbe0d8-592c-48b6-adbd-9001a72fd143 started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,970[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server b0d3fce3-4f83-4c3a-a74f-7fca70e00620 started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,973[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 6d3469ef-8f14-4c1b-8363-ecb92401611f started up.
INFO   | jvm 1    | 2023/10/28 23:40:47 | 2023-10-28 23:40:46,974[INFO]io.mycat.vertx.VertxMycatServer.lambda$start$1:166Mycat Vertx server 30aed181-027b-464c-b2d0-70aa03e79f63 started up.
[root@mycat ~]#
# 连接
[root@mycat conf]#mysql -umycat -p123456 -P 8066 -h 10.0.0.135
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.33-mycat-2.0 Source distribution

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| `Database`         |
+--------------------+
| hellodb            |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)

10.6 使用注解添加数据源,集群等

# 使用注解的方式进行修改配置文件
# 首先,确保主从复制已经搭建完成,并且里面有需要的物理数据库
# 1.连接mycat,可以使用第三方工具,包括sqlyog,navicat,dbeaver
mysql -umycat -p123456 -P 8066 -h 10.0.0.135
# 修改mycat的用户名密码
[root@mycat conf]#vim users/mycat.user.json
{
    "dialect":"mysql",
    "ip":null,
    "password":"123456",
    "transactionType":"xa",
    "username":"mycat"
}
# 修改mycat的端口号
[root@mycat conf]#vim server.json
    "ip":"0.0.0.0",
    "mycatId":1,
    "port":3306,
    "reactorNumber":8,
    "tempDirectory":null,
    "timeWorkerPool":{
      "corePoolSize":0,
      "keepAliveTime":1,
      "maxPendingLimit":65535,
      "maxPoolSize":2,
      "taskTimeout":5,
      "timeUnit":"MINUTES"
    }
根据需求修改port


# 2.创建逻辑库
CREATE DATABASE hellodb; #此时,会自动生成在schemas下面生成一个hellodb.schema.json的文件
# 3.使用注解添加读的写据源(datasources/rwSepw.datasource.json)
/*+ mycat:createDataSource{ "name":"rwSepw","url":"jdbc:mysql://10.0.0.131:3306/hellodb?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456" } */;
# 4.使用注解添加读的数据源(datasources/rwSepr.datasource.json)
/*+ mycat:createDataSource{"name":"rwSepr","url":"jdbc:mysql://10.0.0.134:3306/hellodb?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456"} */;
# 5. 查看现有的数据源
/*+ mycat:showDataSources{} */;
# 6.将上面创建的数据源放在集群中cluster
/*! mycat:createCluster{"name":"prototype1","masters":["rwSepw"],"replicas":["rwSepr"]} */;
# 7.查看集群
/*+ mycat:showClusters{} */
# 8.在逻辑库中加上对应的集群
{
    "customTables":{},
    "globalTables":{},
    "normalProcedures":{},
    "normalTables":{},
    "schemaName":"hellodb",
    "targetName":"prototype1",
    "shardingTables":{},
    "views":{}
}
添加 "targetName":"prototype1",然后重启mycat
1.搭建主从复制架构
2.首先在实际的mysql中创建database,然后再mycat2中创建一模一样的数据库名(顺序不能颠倒)
targetName可以是单一的数据源,也可以是集群字

10.7 双主双从的读写分离

# 1.先搭两对主从复制架构
# 2.然后,两个主节点再进行互为主从搭建的模式,但是这两个配置文件都必须加入
server-id=1
log_slave_updates=1
binlog-format=STATEMENT #这里使用statement(语句)是因为下面要轮询确定是那个机器的数据库,如果是row所有的数据都一样没办法区分
# 3.创建需要的数据库(在任意一个主机上执行下面命令,剩下的三台机器都会同步)
create database mydb2;
use mydb2;
CREATE TABLE mytb1(
    id INT,
    NAME VARCHAR(50)
);
INSERT INTO mytb1 VALUES(1,"xingyuyu");
INSERT INTO mytb1 VALUES(2,"zhangsan");
INSERT INTO mytb1 VALUES(3,"lisi");
INSERT INTO mytb1 VALUES(4,@@hostname);
SELECT * FROM mytb1;

# 配置mycat2(使用语句创建,本质也是修改对应的配置文件 /apps/mycat/conf下面的目录)
# 注意点:逻辑库的库名必须和物理库的名字一样才可以看到数据
# 创建逻辑数据库
create database mydb2;
# 使用注解添加写的数据源
/*+ mycat:createDataSource{ "name":"rwSepw","url":"jdbc:mysql://10.0.0.131:3306/mydb2?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456" } */;
/*+ mycat:createDataSource{"name":"rwSepr","url":"jdbc:mysql://10.0.0.134:3306/mydb2?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456"} */;
/*+ mycat:createDataSource{"name":"rwSepw2","url":"jdbc:mysql://10.0.0.107:3306/mydb2?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456"} */;
/*+ mycat:createDataSource{"name":"rwSepr2","url":"jdbc:mysql://10.0.0.106:3306/mydb2?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true","user":"root","password":"123456"} */;

#查看现有的数据源
/*+ mycat:showDataSources{} */;
# 删除数据源
/*+ mycat:dropDataSource{"name":"rwSepr"} */;

image-20231106132516647

# 将数据源放到集群里面
/*! mycat:createCluster{"name":"mydb2_cluster","masters":["rwSepw","rwSepw2"],"replicas":["rwSepr","rwSepr2"]} */;
# 删除cluster
/*+ mycat:dropCluster{"name":"prototype1"} */;
# 查看集群cluster
/*+ mycat:showClusters{} */

image-20231106134252867

# 重启mycat(我这里配置了环境变量)
mycat restart

# 连接mycat,发现此时的逻辑库mydb1下面自动生成了一张表mytb1
id  NAME
1   xingyuyu
2   zhangsan
3   lisi
4   master.xyy.org

id  NAME
1   xingyuyu
2   zhangsan
3   lisi
4   slave.xyy.org

id  NAME
1   xingyuyu
2   zhangsan
3   lisi
4   master2

id  NAME
1   xingyuyu
2   zhangsan
3   lisi
4   slave2
# 查询的结果如上面,发现在几个数据库之间进行轮询

10.8 实现分库分表

# 建立在上面的基础上,使用两个机器进行测试
# 注释掉不用的两个数据源,否则启动失败
mv datasources/rwSepw2.datasource.json datasources/rwSepw2.datasource.json_bak
mv datasources/rwSepr2.datasource.json datasources/rwSepr2.datasource.json_bak
# 重启mycat

# 两个主机创建四个数据源
/*+ mycat:createDataSource{
"name":"dw0",
"url":"jdbc:mysql://10.0.0.131:3306",
"user":"root",
"password":"123456"
} */;
/*+ mycat:createDataSource{
"name":"dr0",
"url":"jdbc:mysql://10.0.0.131:3306",
"user":"root",
"password":"123456"
} */;
/*+ mycat:createDataSource{
"name":"dw1",
"url":"jdbc:mysql://10.0.0.134:3306",
"user":"root",
"password":"123456"
} */;
/*+ mycat:createDataSource{
"name":"dr1",
"url":"jdbc:mysql://10.0.0.134:3306",
"user":"root",
"password":"123456"
} */;

# 添加新的数据源的集群(一定要叫c1,c0等)
/*!
mycat:createCluster{"name":"c0","masters":["dw0"],"replicas":["dr0"]}
*/;
/*!
mycat:createCluster{"name":"c1","masters":["dw1"],"replicas":["dr1"]}
*/;

# 全局表/广播表 逻辑库
CREATE DATABASE db1;
# 固定写法,创建广播表会自动关联数据源
CREATE TABLE db1.`travelrecord` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` VARCHAR(100) DEFAULT NULL,
`traveldate` DATE DEFAULT NULL,
`fee` DECIMAL(10,0) DEFAULT NULL,
`days` INT DEFAULT NULL,
`blob` LONGBLOB,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 BROADCAST;
广播表 (Broadcast Table)
概念:广播表是一种特殊的表,它在所有分库中都有一个完全相同的副本。
作用:
数据同步:当有数据修改时,这些更改会同步到所有分库的广播表中,确保数据的一致性。
跨库联查:广播表通常用于存储小而不经常变化的数据,如配置信息、字典数据等,它们可以方便地用于跨库联查,不需要担心数据分布的问题

# 创建orders表
CREATE TABLE orders (
  id BIGINT NOT NULL AUTO_INCREMENT,
  order_type INT,
  customer_id INT,
  amount DECIMAL(10,2),
  PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8
dbpartition BY mod_hash(customer_id) 
tbpartition BY mod_hash(customer_id) 
tbpartitions 1 
dbpartitions 2;
# 解释:CREATE TABLE orders (...): 这个命令用于创建一个名为 orders 的新表。
表的列定义:
id BIGINT NOT NULL AUTO_INCREMENT: 定义了一个名为 id 的列,数据类型是 BIGINT,不允许空值,且设置为自动增长,通常作为主键使用。
order_type INT: 定义了一个名为 order_type 的列,数据类型是 INT。
customer_id INT: 定义了一个名为 customer_id 的列,数据类型是 INT,在分片策略中用作分片键。
amount DECIMAL(10,2): 定义了一个名为 amount 的列,数据类型是 DECIMAL,这里 10,2 表示总共最多10位数字,其中小数点后最多2位。
PRIMARY KEY (id): 指定 id 列作为表的主键。
ENGINE=INNODB: 指定使用 InnoDB 存储引擎,它支持事务处理等高级数据库功能。
DEFAULT CHARSET=utf8: 设置表的默认字符集为 utf8,这对于支持多语言文本是重要的。
分库分表策略:
dbpartition BY mod_hash(customer_id): 指定使用 customer_id 列的哈希值来进行数据库级别的分区。这意味着基于 customer_id 的哈希值将数据分散到不同的数据库(分库)中。
tbpartition BY mod_hash(customer_id): 指定使用 customer_id 列的哈希值来进行表级别的分区。这意味着数据将根据 customer_id 的哈希值分布到不同的表(分表)中。
tbpartitions 1: 表示每个数据库分区下只有一个表分区。
dbpartitions 2: 表示总共有两个数据库分区。

INSERT INTO orders(id,order_type,customer_id,amount) VALUES(1,101,100,100100);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);
SELECT * FROM orders;
id  order_type  customer_id amount
1   101 100 100100.00
2   101 100 100300.00
6   102 100 100020.00
3   101 101 120000.00
4   101 101 103000.00
5   102 101 100400.00

#上面的id为什么和插入时的序号不一样呢,是因为此时是用了customer_id进行分片了。master那台机器会生成一个db_0的数据库,下面有一个orders_0的表;而slave机器有一个db_1的数据库,下面有一个order_1的表
image-20231106214130650 image-20231106213811356 image-20231106214035896

10.9 mycat2自动识别ER关系

CREATE TABLE orders_detail(
`id` BIGINT NOT NULL AUTO_INCREMENT,
detail VARCHAR(2000),
order_id INT,
PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8
dbpartition BY mod_hash(order_id) tbpartition BY mod_hash(order_id)
tbpartitions 1 dbpartitions 2;

INSERT INTO orders_detail(id,detail,order_id) VALUES(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

SELECT * FROM orders o INNER JOIN orders_detail od ON od.order_id=o.id;

image-20231106221818618

# mycat2上面执行
select * from order_detail;

image-20231106222010083

# 在master机器中查看

image-20231106222158027

# 在slave中查看

image-20231106222237563

# 查看配置的表是否具有ER关系,如果groupid相关,那么就代表该组中的表具有相同的存储分布
/*+ mycat:showErGroup{}*/

image-20231106221748576

10.10 工具使用

# 下载对应的jar包
http://dl.mycat.org.cn/2.0/ui/
wget http://dl.mycat.org.cn/2.0/ui/assistant-1.22-release-jar-with-dependencies-2022-5-26.jar
# 下载以后双击运行(前提电脑上装了jdk)
# 如果双击打不开,进入对应的目录使用java  -jar

java -jar .\assistant-1.22-release-jar-with-dependencies-2022-5-26.jar

image-20231106222832260

image-20231106222919186

11.mysql修改命令提示符

# 当我们安装好mysql服务器的时候,需要使用“mysql”这个客户端命令来查看相应的设置,但是提示符显示不是很友好。
eg:
mysql >

# 进入mysql的配置目录
cd /etc/my.cnf.d

# 在该目录下创建任何文件mysql都会识别并且加载
touch mysql.cnf

[mysql]
prompt=(\\u@\\h mysql\\v) [\\d]>\\_

# 解释:
在MySQL的配置文件或者交互式提示符中,这些是用于设置MySQL命令行客户端提示符的转义序列。

\\u: 当前MySQL用户。
\\h: 连接的MySQL服务器的主机名。
\\d: 当前选择的数据库。
\\_: 显示一个'>'字符。
\\c: 显示MySQL命令计数器。
\\l: 显示当前delimiter字符。
\\p: 显示当前端口。
\\P: 显示当前mysqlnd库端口。
\\r: 显示当前协议版本。
\\s: 显示当前服务器版本。
\\v: 显示当前版本信息。
\\n: 新行。
\\t: 制表符

#再次进入发现提示符已经变化了
root@localhost mysql8.0.32) [(none)]>

12.my.cnf

# vim /etc/my.cnf
[mysqld]
server-id=1
datadir=/data/mysql
socket=/data/mysql/mysql.socket
[mysqld_safe]
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.socket

# 在MySQL的配置文件中加入了上面参数,但是生成的临时密码会打印到屏幕中,而不是我指定好的mysql.log中,这在写脚本的时候很不方便。
原因:MySQL的mysqld_safe是一个用于启动mysqld的脚本,它有一些额外的功能,例如自动重启mysqld如果它崩溃了。mysqld_safe 和 mysqld 是两个不同的程序,它们有各自的日志。
mysqld_safe 将其日志输出到标准输出/标准错误,也就是屏幕,除非你通过命令行参数或环境变量重定向它。你不能在 my.cnf 文件中配置 mysqld_safe 的日志路径。
mysqld 的日志是配置在 my.cnf 文件中的,例如你的 /data/mysql/mysql.log。你看到的日志输出到屏幕可能是 mysqld_safe 的日志,而不是 mysqld 的日志。如果你想要将 mysqld_safe 的日志输出到文件,你可以在启动 mysqld_safe 时重定向它的输出。例如:
mysqld --initialize --user=mysql --datadir=/data/mysql --log-error=/data/mysql/mysql.log

#配置参数
[client]: 这个分组包含了客户端程序的设置。
port: 客户端用来连接的端口。
socket: 客户端用来连接的套接字。

[mysqld]: 这个分组包含了 MySQL 服务器的设置。
port: 服务器监听的端口。
bind-address: 服务器绑定的 IP 地址。
datadir: 数据目录的位置。
socket: 服务器套接字的位置。
user: 服务器运行的用户。
log-error: 错误日志文件的位置。
pid-file: PID 文件的位置。
max_connections: 允许的最大连接数。
key_buffer_size: 用于索引块的缓冲区大小。
table_open_cache: 打开的表的缓存数量。
sort_buffer_size: 用于排序的缓冲区大小。
read_buffer_size: 用于顺序读取的缓冲区大小。

[mysqldump]: 这个分组包含了 mysqldump 程序的设置。
quick: 加速导出操作。
max_allowed_packet: 允许的最大数据包大小。

[mysql]: 这个分组包含了 mysql 客户端的设置。
no-auto-rehash: 禁用自动补全。

13.mysql5.7二进制安装脚本

#!/bin/bash
# MySQL5.7.43 Download URL: https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz
# MySQL8.0.34 Download URL: https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.34-linux-glibc2.28-x86_64.tar.gz

. /etc/init.d/functions
SRC_DIR=$(pwd)
MYSQL='mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz'
#MYSQL='mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz'
#MYSQL='MySQL-8.0/mysql-8.0.34-linux-glibc2.28-x86_64.tar.gz'
COLOR='echo -e \E[01;33m'
END='\E[0m'
MYSQL_ROOT_PASSWORD=root

check() {
  if [ ! -e $MYSQL ]; then
    $COLOR"缺少${MYSQL}文件,即将通过wget进行安装"$END
    yum -y install wget &> /dev/null
    #wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.43-linux-glibc2.12-x86_64.tar.gz
    #wget https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz
    if [[ ! -e  $MYSQL ]]; then
      $COLOR"yum安装失败,请将相关软件放在${SRC_DIR}目录下"$END
      exit
    fi
    install_mysql
  elif [ -e /usr/local/mysql ]; then
    action "数据库已存在,安装失败" false
    exit
  elif [ -e $MYSQL ]; then
    $COLOR"已检测到$MYSQL"$END
    install_mysql
  else
    return
  fi
}

install_mysql() {
  $COLOR "开始安装MySQL数据库..."$END
  yum -y -q install libaio numactl-libs
  cd $SRC_DIR
  tar xf $MYSQL -C /usr/local
  MYSQL_DIR=$(echo $MYSQL | sed -nr 's/^(.*[0-9]).*/\1/p')
  ln -s /usr/local/$MYSQL_DIR /usr/local/mysql
  chown -R root:root /usr/local/mysql/
  id mysql &>/dev/null || {
    useradd -s /sbin/nologin -r mysql
    action "创建mysql用户"
  }
  echo 'PATH=/usr/local/mysql/bin/:$PATH' >/etc/profile.d/mysql.sh
  . /etc/profile.d/mysql.sh
  ln -s /usr/local/mysql/bin/* /usr/bin/
  cp /etc/my.cnf{,.bak}
  cat >/etc/my.cnf <<EOF
[mysqld]
server-id=1
datadir=/data/mysql
socket=/data/mysql/mysql.socket
#[mysqld_safe]
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.socket
EOF
  [ -d /data ] || mkdir /data
  #my.cnf加入了[mysqld_safe]的写法
  #mysqld --initialize --user=mysql --datadir=/data/mysql --log-error=/data/mysql/mysql.log
  #my.cnf没有加入[mysqld_safe]的写法
  mysqld --initialize --user=mysql --datadir=/data/mysql
  cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
  chkconfig --add mysqld
  chkconfig mysqld on
  service mysqld start
  [ $? -ne 0 ] && {
    $COLOR"数据库启动失败,退出!"$END
    exit
  }
  sleep 3
  MYSQL_Temporary_Password=$(awk '/A temporary password/{print $NF}' /data/mysql/mysql.log)
  echo $MYSQL_Temporary_Password
  mysqladmin -uroot -p$MYSQL_Temporary_Password password $MYSQL_ROOT_PASSWORD &>/dev/null
  action "数据库安装完成"
}
check

MySQL5.7编译源码脚本


15.MySQL操作命令

# 查看字符集
# SHOW VARIABLES 是 MySQL 中用于查看服务器系统变量的命令
mysql> SHOW VARIABLES LIKE 'char%'; # 将返回所有以 "char" 开头的系统变量。
% 表示任意数量的字符,_ 表示任意单个字符。
character_set_client: 这是客户端使用的字符集。当你发送一个查询给服务器时,它假设查询是使用这个字符集编写的。
character_set_connection: 这是服务器用来解释客户端发送给它的文本的字符集。
character_set_database: 当创建一个新的数据库或表时,这是默认的字符集。
character_set_results: 这是服务器将查询结果发送回客户端时使用的字符集。
character_set_server: 这是服务器的默认字符集。
character_set_system: 这是服务器使用的系统字符集。
character_sets_dir: 这是服务器上字符集文件的目录
# 要设置这些变量,可以使用 SET 命令。例如:
mysql> SET character_set_client = utf8;
注意:为了永久更改这些设置,需要在 MySQL 配置文件(通常是 my.cnf 或 my.ini)中设置它们,并重启服务器。

# SHOW CREATE SCHEMA 或 SHOW CREATE DATABASE 命令用于查看创建指定数据库的 SQL 语句。
SHOW CREATE SCHEMA database_name;
SHOW CREATE DATABASE database_name;

# 查看字符集的默认排序规则
show collation;

# 查看排序变量
show variables like 'collection%';

# 字符集
show character set;

# 永久修改服务器的字符集
vim /etc/my.cnf或者根据自定义的路径
[mysqld]
character_set_server=utf8mb4

# 永久修改客户端的字符集
vim /etc/my.cnf.d/client.cnf
[client]
default-character=utf8mb4

exit
fi
install_mysql
elif [ -e /usr/local/mysql ]; then
action “数据库已存在,安装失败” false
exit
elif [ -e $MYSQL ]; then
C O L O R " 已检测到 COLOR"已检测到 COLOR"已检测到MYSQL"$END
install_mysql
else
return
fi
}

install_mysql() {
C O L O R " 开始安装 M y S Q L 数据库 . . . " COLOR "开始安装MySQL数据库..." COLOR"开始安装MySQL数据库..."END
yum -y -q install libaio numactl-libs
cd $SRC_DIR
tar xf M Y S Q L − C / u s r / l o c a l M Y S Q L D I R = MYSQL -C /usr/local MYSQL_DIR= MYSQLC/usr/localMYSQLDIR=(echo KaTeX parse error: Undefined control sequence: \1 at position 33: …s/^(.*[0-9]).*/\̲1̲/p') ln -s /u…MYSQL_DIR /usr/local/mysql
chown -R root:root /usr/local/mysql/
id mysql &>/dev/null || {
useradd -s /sbin/nologin -r mysql
action “创建mysql用户”
}
echo ‘PATH=/usr/local/mysql/bin/:$PATH’ >/etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
ln -s /usr/local/mysql/bin/* /usr/bin/
cp /etc/my.cnf{,.bak}
cat >/etc/my.cnf <<EOF
[mysqld]
server-id=1
datadir=/data/mysql
socket=/data/mysql/mysql.socket
#[mysqld_safe]
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.socket
EOF
[ -d /data ] || mkdir /data
#my.cnf加入了[mysqld_safe]的写法
#mysqld --initialize --user=mysql --datadir=/data/mysql --log-error=/data/mysql/mysql.log
#my.cnf没有加入[mysqld_safe]的写法
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
[ $? -ne 0 ] && {
C O L O R " 数据库启动失败,退出! " COLOR"数据库启动失败,退出!" COLOR"数据库启动失败,退出!"END
exit
}
sleep 3
MYSQL_Temporary_Password=$(awk ‘/A temporary password/{print $NF}’ /data/mysql/mysql.log)
echo M Y S Q L T e m p o r a r y P a s s w o r d m y s q l a d m i n − u r o o t − p MYSQL_Temporary_Password mysqladmin -uroot -p MYSQLTemporaryPasswordmysqladminurootpMYSQL_Temporary_Password password $MYSQL_ROOT_PASSWORD &>/dev/null
action “数据库安装完成”
}
check


## MySQL5.7编译源码脚本

```bash

15.MySQL操作命令

# 查看字符集
# SHOW VARIABLES 是 MySQL 中用于查看服务器系统变量的命令
mysql> SHOW VARIABLES LIKE 'char%'; # 将返回所有以 "char" 开头的系统变量。
% 表示任意数量的字符,_ 表示任意单个字符。
character_set_client: 这是客户端使用的字符集。当你发送一个查询给服务器时,它假设查询是使用这个字符集编写的。
character_set_connection: 这是服务器用来解释客户端发送给它的文本的字符集。
character_set_database: 当创建一个新的数据库或表时,这是默认的字符集。
character_set_results: 这是服务器将查询结果发送回客户端时使用的字符集。
character_set_server: 这是服务器的默认字符集。
character_set_system: 这是服务器使用的系统字符集。
character_sets_dir: 这是服务器上字符集文件的目录
# 要设置这些变量,可以使用 SET 命令。例如:
mysql> SET character_set_client = utf8;
注意:为了永久更改这些设置,需要在 MySQL 配置文件(通常是 my.cnf 或 my.ini)中设置它们,并重启服务器。

# SHOW CREATE SCHEMA 或 SHOW CREATE DATABASE 命令用于查看创建指定数据库的 SQL 语句。
SHOW CREATE SCHEMA database_name;
SHOW CREATE DATABASE database_name;

# 查看字符集的默认排序规则
show collation;

# 查看排序变量
show variables like 'collection%';

# 字符集
show character set;

# 永久修改服务器的字符集
vim /etc/my.cnf或者根据自定义的路径
[mysqld]
character_set_server=utf8mb4

# 永久修改客户端的字符集
vim /etc/my.cnf.d/client.cnf
[client]
default-character=utf8mb4

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XingYuyu_Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值