二进制安装 MySQL 5.7 和 MySQL8.0 1、安装相关包
1 yum -y install libaio numactl-libs libncurses*
2、创建用户和组及目录
1 2 3 4 5 6 7 8 groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql mkdir -p /data/mysql/chown -R mysql:mysql /data/mysql/mkdir -p /mysql/binlogchown -R mysql:mysql /mysql/binlog
3、准备程序文件
1 2 3 4 5 6 7 [root@Rocky8-mini3 ~] mysql-5.7.40-linux-glibc2.12-x86_64.tar.gz [root@Rocky8-mini3 ~] [root@Rocky8-mini3 ~] [root@Rocky8-mini3 src] [root@Rocky8-mini3 src]
4、准备环境变量
1 2 [root@Rocky8-mini3 bin] [root@Rocky8-mini3 bin]
5、准备配置文件和相关目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@Rocky8-mini3 bin] [client] socket=/data/mysql/mysql.sock [mysql] prompt="\\r:\\m:\\s(\\u@\\h) [\\d]>\\_" [mysqld] port=3306 log-bin=/mysql/binlog/mysql-bin server-id=1001 datadir=/data/mysql socket=/data/mysql/mysql.sock user=mysql bind-address = 0.0.0.0 symbolic-links=0 log-error=/data/mysql/mysql.log pid-file=/data/mysql/mysql.pid
6、初始化数据库文件
(1)生成随机密码
1 2 3 4 5 6 7 8 ll -d /data/mysql/ drwxr-xr-x 2 mysql mysql 6 Feb 7 23:47 /data/mysql/ [root@Rocky8-mini4 local ] 2023-02-07T15:47:43.136469Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). ··· ··· 2023-02-07T15:47:43.395989Z 1 [Note] A temporary password is generated for root@localhost: jUFcLah?a6K:
(2)生成空密码
1 mysqld --initialize-insecure --user=mysql --datadir=/data/mysql
7、准备服务脚本启动
1 2 3 4 5 6 7 8 9 10 11 12 [root@Rocky8-mini3 bin] [root@Rocky8-mini3 bin] [root@Rocky8-mini3 bin] [root@Rocky8-mini3 bin] 64 if test -z "$basedir " 65 then 66 basedir=/usr/local/src/mysql 67 bindir=/usr/local/src/mysql/bin [root@Rocky8-mini3 bin] Starting MySQL.Logging to '/data/mysql/mysqld.log' . SUCCESS!
8、修改口令
1 2 3 4 mysqladmin -uroot -p'jUFcLah?a6K:' password wuhaolam mysqladmin -uroot password wuhaolam
9、测试登录
源码编译安装MySQL5.7 源码下载地址:https://downloads.mysql.com/archives/community/
实验环境
1 2 3 4 5 6 Rocky Linux release 8.5 (Green Obsidian) boost_1_59_0.tar.gz mysql-5.7.40.tar.gz rpcsvc-proto-1.4.tar.gz 防火墙和selinux关闭
1、安装相关依赖包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 yum -y install gcc gcc-c++ cmake bison zlib-devel libcurl-devel libarchive ncurses-devel gnutls-devel libxml2-devel openssl-devel libevent-devel libaio-devel perl-Data-Dumper libtirpc-devel [root@Centos8-mini ~] [root@Centos8-mini ~] boost_1_59_0.tar.gz [root@Centos8-mini ~] [root@Centos8-mini ~] [root@Centos8-mini boost_1_59_0] [root@Centos8-mini boost_1_59_0] [root@Centos8-mini boost_1_59_0] [root@Centos8-mini ~] rpcsvc-proto-1.4.tar.gz [root@Centos8-mini ~] [root@Centos8-mini ~] [root@Centos8-mini rpcsvc-proto-1.4] ./boost/mpl/assert.hpp:193:21: warning: unnecessary parentheses in declaration of ‘assert_not_arg’ [-Wparentheses] failed ************ (boost::mpl::not_<Pred>::************ 在当前文件boost/mpl/assert.hpp 最上面一行添加: // 禁止boost 断言宏
2、创建用户和数据库目录
1 2 3 4 5 groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql mkdir -p /data/mysql/chown -R mysql:mysql /data/mysql/
3、源码编译安装
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@Centos8-mini ~] mysql-5.7.40.tar.gz [root@Centos8-mini ~] [root@Centos8-mini ~] [root@Centos8-mini mysql-5.7.40] [root@Rocky8-mini2 mysql-5.7.40] [root@Rocky8-mini2 mysql-5.7.40]
4、生成环境变量
1 2 [root@Rocky8-mini2 mysql-5.7.40] [root@Rocky8-mini2 mysql-5.7.40]
5、准备配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@Rocky8-mini mysql-5.7.40] [client] port=3306 socket=/data/mysql/mysql.sock [mysql] prompt="\\r:\\m:\\s(\\u@\\h) [\\d]>\\_" [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock user=mysql symbolic-links=0 log-error=/data/mysql/mysqld.log pid-file=/data/mysql/mysql.pid
6、初始化数据库
1 [root@Rocky8-mini2 mysql-5.7.40]
7、准备自启动脚本
1 2 3 4 5 6 7 8 [root@Rocky8-mini2 mysql-5.7.40] [root@Rocky8-mini mysql-5.7.40] [root@Rocky8-mini mysql-5.7.40] [root@Rocky8-mini mysql-5.7.40] [root@Rocky8-mini2 mysql-5.7.40] Starting MySQL.Logging to '/data/mysql/Rocky8-mini2.err' . SUCCESS!
8、修改默认密码并登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@Rocky8-mini mysql] 2023-03-01T13:42:36.266976Z 1 [Note] A temporary password is generated for root@localhost: frPDygTwQ7/> [root@Rocky8-mini mysql] mysqladmin: [Warning] Using a password on the command line interface can be insecure. Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety. [root@Rocky8-mini mysql] 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 3 Server version: 5.7.40 Source distribution Copyright (c) 2000, 2022, 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. 08:49:19(root@localhost) [(none)]>
数据库相关练习 【前提准备】
1 2 3 4 1、下载好数据文件 http://file.wuhaolam.top/hellodb_innodb.sql 2、导入数据库中 10:14:57(root@localhost) [(none)]> source hellodb_innodb.sql;
【相关练习】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 1. 在students表中,查询年龄大于25岁,且为男性的同学的名字和年龄 select name,gender,age from students where age>25 and gender='M'; 2. 以ClassID为分组依据,显示每组的平均年龄 SELECT ClassID,AVG(age) FROM students GROUP BY ClassID; 3. 显示第2题中平均年龄大于30的分组及平均年龄 SELECT ClassID,AVG(age) FROM students GROUP BY ClassID HAVING AVG(age)>30; 4. 显示以L开头的名字的同学的信息 SELECT * FROM students WHERE NAME LIKE 'L%'; 5. 显示TeacherID非空的同学的相关信息 SELECT * FROM students WHERE TeacherID IS NOT NULL; 6. 以年龄排序后,显示年龄最大的前10位同学的信息 SELECT * FROM students ORDER BY age DESC LIMIT 10; 7. 查询年龄大于等于20岁,小于等于25岁的同学的信息 SELECT * FROM students WHERE age BETWEEN 20 AND 25; 8. 以ClassID分组,显示每班的同学的人数 SELECT ClassID,COUNT(stuid) 班级人数 FROM students GROUP BY ClassID; 9. 以Gender分组,显示其年龄之和 SELECT gender,SUM(age) FROM students GROUP BY Gender; 10. 以ClassID分组,显示其平均年龄大于25的班级 SELECT ClassID,AVG(age) FROM students GROUP BY ClassID HAVING AVG(age)>25; 11. 以Gender分组,显示各组中年龄大于25的学员的年龄之和 SELECT gender,SUM(age) FROM students WHERE age > 25 GROUP BY Gender; 12. 显示前5位同学的姓名、课程及成绩 SELECT stu.`Name`,cou.`Course`,sco.`Score` FROM students AS stu,courses AS cou,scores AS sco WHERE stu.`StuID`=sco.`StuID` AND cou.`CourseID`=sco.`CourseID` LIMIT 10; 13. 显示其成绩高于80的同学的名称及课程 SELECT stu.`Name`,cou.`Course`,sco.`Score` FROM students AS stu,courses AS cou,scores AS sco WHERE stu.`StuID`=sco.`StuID` AND cou.`CourseID`=sco.`CourseID` AND sco.`Score`>80; 14. 取每位同学各门课的平均成绩,显示成绩前三名的同学的姓名和平均成绩 SELECT stu.`Name`,AVG(score) FROM students AS stu,scores AS sco WHERE stu.`StuID`=sco.`StuID` GROUP BY stu.`Name` ORDER BY AVG(score) DESC LIMIT 3; 15. 显示每门课程课程名称及学习了这门课的同学的个数 SELECT courses.`Course` 课程名称,COUNT(scores.`CourseID`) FROM courses,scores WHERE courses.`CourseID`=scores.`CourseID` GROUP BY courses.`Course`; 16. 显示其年龄大于平均年龄的同学的名字 SELECT NAME,age FROM students WHERE age > (SELECT AVG(age) FROM students); 17. 显示其学习的课程为第1、2,4或第7门课的同学的名字 SELECT NAME,CourseID FROM students,scores WHERE students.`StuID`=scores.`StuID` AND scores.`CourseID` IN (1,2,4,7); 18. 显示其成员数大于为3个的班级的同学中年龄大于同班同学平均年龄的同学 SELECT NAME,classid,age FROM students AS A WHERE classid IN (SELECT classid FROM students GROUP BY classid HAVING COUNT(stuid) > 3 ) AND age > (SELECT AVG(age) FROM students WHERE students.`ClassID`=A.`ClassID`); 19. 统计各班级中年龄大于全校同学平均年龄的同学 SELECT NAME,classid,age FROM students WHERE age > (SELECT AVG(age) FROM students);
mysqldump 和二进制日志结合实现数据的恢复 案例描述:每天2点做数据库的完全备份,在早上8点误删除了表students,8点10分发现故障,需要将数据库还原到8点10分的状态,并且恢复被删除的表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 [root@Rocky8-mini ~] [root@Rocky8-mini ~] -rw-r--r-- 1 root root 868K Mar 4 02:07 /backup/allbackupsql_2023-03-04_02:07:01.sql 02:09:12(root@localhost) [hellodb]> insert students values(26,'Tom' ,22,'M' ,2,2); Query OK, 1 row affected (0.00 sec) 02:10:25(root@localhost) [hellodb]> insert students values(27,'Jerry' ,22,'F' ,2,1); Query OK, 1 row affected (0.01 sec) 02:14:55(root@localhost) [hellodb]> show tables; 02:16:08(root@localhost) [hellodb]> insert teachers values(5,'ZERO' ,36,'M' ); Query OK, 1 row affected (0.00 sec) [root@Rocky8-mini ~] -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003' , MASTER_LOG_POS=154; [root@Rocky8-mini ~] [root@Rocky8-mini ~] DROP TABLE `students` /* generated by server */ [root@Rocky8-mini ~] 02:29:56(root@localhost) [(none)]> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) 02:30:11(root@localhost) [(none)]> source /backup/allbackupsql_2023-03-04_02:07:01.sql; 02:30:35(root@localhost) [hellodb]> source /backup/binlog.sql; 02:30:52(root@localhost) [hellodb]> set sql_log_bin=1; Query OK, 0 rows affected (0.00 sec)
利用xtrabackup完全,增量备份及还原 【工具下载】
https://www.percona.com/downloads(MySQL8.0的数据库需要使用 Percona XtraBackup 8.0的rpm包,MySQL5.X的版本使用 2.4的rpm包)
利用xtrabackup备份生成的相关文件
xtrabackup_info:文本文件,innobackupex工具执行时的相关信息,包括版本,备份选项,备份时长,备份LSN(log sequence number日志序列号),BINLOG的位置
xtrabackup_checkpoints:文本文件,备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN范围信息,每个InnoDB页(通常为16k大小)都会包含一个日志序列号LSN。 LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的
xtrabackup_binlog_info:文本文件,MySQL服务器当前正在使用的二进制日志文件及至备份这一刻为止二进制日志事件的位置,可利用实现基于binlog的恢复
backup-my.cnf:文本文件,备份命令用到的配置选项信息
xtrabackup_logfile:备份生成的二进制日志文件
实例:利用 Percona XtraBackup 2.4 完全,增量备份及还原 MySQL 5.7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 两台Rocky8 Linux机器,安装了xtrabackup和mysql 5.7 192.168.119.128 备份主机 192.168.119.138 还原主机 [root@Rocky8-mini ~] percona-xtrabackup-24-2.4.27-1.el8.x86_64.rpm [root@Rocky8-mini ~] [root@Rocky8-mini ~] [root@Rocky8-mini ~] 07:39:18(root@localhost) [hellodb]> insert teachers values(6,'LuFei' ,32,'M' ); [root@Rocky8-mini ~] 07:45:00(root@localhost) [hellodb]> insert teachers values(7,'LaMei' ,22,'F' ); [root@Rocky8-mini ~] [root@Rocky8-mini ~] [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~]
实现主从复制 【实验环境】
【实验步骤】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 Master 设备 [root@Rocky8-mini ~] [mysqld] log-bin=/mysql/binlog/mysql-bin server-id=128 [root@Rocky8-mini ~] [root@Rocky8-mini ~] 04:46:18(root@localhost) [(none)]> create user replyuser@"192.168.119.%" identified by "wuhaolam" ; 04:46:24(root@localhost) [(none)]> grant replication slave on *.* to replyuser@"192.168.119.%" ; [root@Rocky8-mini ~] Slave 设备 [root@Rocky8-mini2 ~] server-id=138 read-only [root@Rocky8-mini2 ~] CHANGE MASTER TO MASTER_HOST='192.168.119.128' , MASTER_USER='replyuser' , MASTER_PASSWORD='wuhaolam' , MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000007' , MASTER_LOG_POS=154; 05:56:44(root@localhost) [(none)]> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) 05:56:54(root@localhost) [(none)]> source /all.sql; 05:57:12(root@localhost) [hellodb]> set sql_log_bin=1; Query OK, 0 rows affected (0.00 sec) 06:10:51(root@localhost) [hellodb]> start slave; Query OK, 0 rows affected (0.00 sec) 06:11:03(root@localhost) [hellodb]> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.119.128 Master_User: replyuser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000007 Read_Master_Log_Pos: 629 Relay_Log_File: Rocky8-mini2-relay-bin.000002 Relay_Log_Pos: 795 Relay_Master_Log_File: mysql-bin.000007 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 629 Relay_Log_Space: 1009 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 128 Master_UUID: fa5a0767-ba39-11ed-b05a-000c294da889 Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log ; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec)
Note:在MySQL8.0中可能会报如下错误
error connecting to master ‘slave@192.168.0.104 :3306’ - retry-time: 60 retries: 6 message: Authentication plugin ‘caching_sha2_password’ reported error: Authentication requires secure connection.
解决办法
如果是 MySQL8.0 的环境中进行主从复制,需要在从节点配置主节点信息时添加 “GET_MASTER_PUBLIC_KEY=1”
例如:CHANGE MASTER TO MASTER_HOST=’192.168.119.128’, MASTER_USER=’replyuser’, MASTER_PASSWORD=’wuhaolam’, MASTER_PORT=3306, MASTER_LOG_FILE=’mysql-bin.000007’, MASTER_LOG_POS=154;
实现级联复制 【实验环境】
【实验步骤】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Master 设备 [root@Rocky8-mini ~] [mysqld] log-bin=/mysql/binlog/mysql-bin server-id=128 [root@Rocky8-mini ~] [root@Rocky8-mini ~] 04:46:18(root@localhost) [(none)]> create user replyuser@"192.168.119.%" identified by "wuhaolam" ; 04:46:24(root@localhost) [(none)]> grant replication slave on *.* to replyuser@"192.168.119.%" ; [root@Rocky8-mini ~] [root@Rocky8-mini ~] 中间级联 Slave1 配置 [root@Rocky8-mini2 ~] log-bin=/mysql/binlog/mysql-bin server-id=138 read-only log_slave_updates [root@Rocky8-mini2 ~] [root@Rocky8-mini2 ~] CHANGE MASTER TO MASTER_HOST='192.168.119.128' , MASTER_USER='replyuser' , MASTER_PASSWORD='wuhaolam' , MASTER_PORT=3306, MASTER_LOG_ FILE='mysql-bin.000008' , MASTER_LOG_POS=154; 07:25:18(root@localhost) [(none)]> set sql_log_bin=0; Query OK, 0 rows affected (0.00 sec) 07:25:29(root@localhost) [(none)]> source /all.sql; 07:25:57(root@localhost) [hellodb]> show master logs; 07:26:21(root@localhost) [hellodb]> set sql_log_bin=1; Query OK, 0 rows affected (0.00 sec) 07:27:44(root@localhost) [hellodb]> start slave; Query OK, 0 rows affected, 1 warning (0.00 sec) Slave2 节点配置 [root@Rocky8-mini3 ~] server-id=129 read-only [root@Rocky8-mini3 ~] Shutting down MySQL.. SUCCESS! Starting MySQL. SUCCESS! CHANGE MASTER TO MASTER_HOST='192.168.119.138' , MASTER_USER='replyuser' , MASTER_PASSWORD='wuhaolam' , MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000006' , MASTER_LOG_POS=154; [root@Rocky8-mini3 ~] [root@Rocky8-mini3 ~]
主主复制 一般用于主主复制的架构
【实验环境】
【实验步骤】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 07:43:05(root@localhost) [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 201 | | mysql-bin.000002 | 177 | | mysql-bin.000003 | 343 | | mysql-bin.000004 | 177 | | mysql-bin.000005 | 871301 | | mysql-bin.000006 | 177 | | mysql-bin.000007 | 310 | +------------------+-----------+ 7 rows in set (0.00 sec) 06:42:52(root@localhost) [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.119.138' , MASTER_USER='replyuser' , MASTER_PASSWORD='wuhaolam' , MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000007' , MASTER_LOG_POS=310; Query OK, 0 rows affected, 2 warnings (0.01 sec) 06:57:40(root@localhost) [(none)]> start slave; Query OK, 0 rows affected (0.00 sec)
半同步复制 默认情况下,MySQL的赋值功能是异步的,异步复制可以提供最佳的性能,主库把binlog日志发送给从库就结束,不验证从库是否接收完毕。当主服务器或从服务器发生故障时,有可能从服务器没有接收到主服务器发送过来的binlog日志,造成主服务器和从服务器的数据不一致,甚至在恢复时造成数据的丢失。
官方文档
1 2 3 https://dev.mysql.com/doc/refman/8.0/en/replication-semisync.html https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html https://mariadb.com/kb/en/library/semisynchronous-replication/
【实验步骤】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 [root@Rocky8-mini2 ~] [root@Rocky8-mini ~] /usr/local/src/mysql-5.7.40-linux-glibc2.12-x86_64/lib/plugin/debug/semisync_master.so /usr/local/src/mysql-5.7.40-linux-glibc2.12-x86_64/lib/plugin/debug/semisync_slave.so /usr/local/src/mysql-5.7.40-linux-glibc2.12-x86_64/lib/plugin/semisync_master.so /usr/local/src/mysql-5.7.40-linux-glibc2.12-x86_64/lib/plugin/semisync_slave.so [root@Rocky8-mini ~] rpl_semi_sync_master_enabled=ON rpl_semi_sync_master_timeout=3000 [root@Rocky8-mini2 ~] rpl_semi_sync_slave_enabled=ON 08:00:37(root@localhost) [(none)]> install plugin rpl_semi_sync_master soname 'semisync_master.so' ; 08:01:34(root@localhost) [(none)]> show plugins; 08:01:55(root@localhost) [(none)]> set global rpl_semi_sync_master_enabled=1; Query OK, 0 rows affected (0.01 sec) 08:02:20(root@localhost) [(none)]> set global rpl_semi_sync_master_timeout=3000; Query OK, 0 rows affected (0.00 sec) 08:02:34(root@localhost) [(none)]> show global variables like '%semi%' ; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 3000 | | 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 | +-------------------------------------------+------------+ 6 rows in set (0.01 sec) 08:02:57(root@localhost) [(none)]> SHOW GLOBAL STATUS LIKE '%semi%' ; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | 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 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec) 09:04:40(root@localhost) [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so' ; Query OK, 0 rows affected (0.01 sec) 09:05:19(root@localhost) [(none)]> set global rpl_semi_sync_slave_enabled=1; Query OK, 0 rows affected (0.00 sec) 09:05:41(root@localhost) [(none)]> show global variables like '%semi%' ; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.01 sec) 09:06:13(root@localhost) [(none)]> start slave; Query OK, 0 rows affected (0.00 sec) 09:06:20(root@localhost) [(none)]> SHOW GLOBAL STATUS LIKE '%semi%' ; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
【测试】
1 2 3 4 5 6 7 8 9 10 11 # 在master上创建数据库 08:03:54(root@localhost) [(none)]> create database db2; Query OK, 1 row affected (0.01 sec) # 停止从服务器复制线程 09:06:22(root@localhost) [(none)]> stop slave; Query OK, 0 rows affected (0.00 sec) # 重新在master上测试,需要等待3s(如果有多个从,只有所有从服务器都停止复制线程,主服务器才会等待) 08:09:13(root@localhost) [(none)]> create database db4; Query OK, 1 row affected (3.01 sec)
复制过滤器 让从节点只复制指定的数据库或者是指定的数据库中的表
复制过滤器的两种实现方式
(1)服务器选项:主服务器仅向二进制日志中记录与指定数据库相关的事件
优点:只需要在主节点配置一次即可
缺点:基于二进制日志的还原将无法实现,因为本机的二进制日志也会受限于此配置,将不会记录
1 2 3 4 5 6 vim /etc/my.cnf binlog-do-db=db1 binlog-do-db=db2 binlog-ignore-db=
(2)从服务器 SQL_THREAD 在读取 Relay log 中的事件时,仅读取与特定数据库(特定表)相关的事件并更新自己的数据库信息
优点:不影响二进制备份还原
缺点:会造成网络及磁盘I/O浪费,在所有从节点都要配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 vim /etc/my.cnf replicate-do-db=db1_name replicate-do-db=db2_name replicate-do-table=db_name.tbl_name replicate-ignore-db= replicate-ignore-table= replicate-wild-do-table=foo%.bar% replicate-wild-ignore-table=
MyCat MyCat 介绍 MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的Server,前端用户可以把它看做是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生(Native)协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分库分表,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。
MyCat后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。
MyCat 简单概括
开源,面向企业应用开发的大数据库集群
支持事务、ACID、可替代MySQL的加强版数据库
可以视为MySQL集群的企业级数据库,用来替代Oracle集群
一个融合内存缓存技术、NoSQL技术、HDFS大数据的新型SQL server
结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品
一个新颖的数据库中间件产品
MyCat 工作原理
MyCat最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终返回给用户
MyCat高可用性
在生产环境中,MyCat节点最后使用双节点,可以使用的高可用的集群方式有
Keepalived + MyCat + MySQL
Keepalived + LVS + MyCat + MySQL
Keepalived + HAproxy + MyCat + MySQL
MyCat 安装 1、安装JDK
1 2 3 4 5 yum -y install java [root@Rocky8-mini ~] openjdk version "1.8.0_312" OpenJDK Runtime Environment (build 1.8.0_312-b07) OpenJDK 64-Bit Server VM (build 25.312-b07, mixed mode)
2、下载安装MyCat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 wget http://dl.mycat.org.cn/1.6.7.6/20220524101549/Mycat-server-1.6.7.6-release-20220524173810-linux.tar.gz mkdir /appstar xf Mycat-server-1.6.7.6-release-20220524173810-linux.tar.gz -C /apps ls /apps/mycat/bin catlet conf lib logs version.txt echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh. /etc/profile.d/mycat.sh [root@Rocky8-mini4 ~] Starting Mycat-server... [root@Rocky8-mini4 ~] STATUS | wrapper | 2023/03/12 04:38:27 | --> Wrapper Started as Daemon STATUS | wrapper | 2023/03/12 04:38:28 | Launching a JVM... INFO | jvm 1 | 2023/03/12 04:38:28 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org INFO | jvm 1 | 2023/03/12 04:38:28 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved. INFO | jvm 1 | 2023/03/12 04:38:28 | INFO | jvm 1 | 2023/03/12 04:38:29 | Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver' . The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary. INFO | jvm 1 | 2023/03/12 04:38:30 | MyCAT Server startup successfully. see logs in logs/mycat.log
MyCat 主要配置文件说明 server.xml
server.xml几乎保存了所有mycat需要的系统配置信息。如连接MyCat的用户,密码,数据库名称等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <user name ="root" defaultAccount ="true" > <property name ="password" > 123456</property > <property name ="schemas" > TESTDB</property > <property name ="defaultSchema" > TESTDB</property > </user > <user name ="user" > <property name ="password" > user</property > <property name ="schemas" > TESTDB</property > <property name ="readOnly" > true</property > <property name ="defaultSchema" > TESTDB</property > </user >
参数 说明 user 用户配置节点 name 客户端登录MyCat的用户名,也就是客户端用来连接MyCat的用户名 password 客户端登录MyCat的密码 schemas 数据库名,此处和schema.xml文件中的配置关联,多个数据库名用逗号分开 privileges 配置用户针对表的增删改查的权限 readOnly MyCat逻辑库所具有的权限。true为只读,false为读写都有。
注意:
server.xml 文件里面登录MyCat的用户名和密码可以任意定义,这个账户和密码是为客户机登录MyCat时使用的账号
逻辑库名(如上中的TESTDB,是登录MyCat后显示的库名,切换这个库后,显示的就是代理的真实的MySQL数据库中的表)也要在schema.xml文件中被定义,否则会导致MyCat服务启动失败
此处只定义了一个标签,如果定义多个标签,设置了多个连接MyCat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库
schema.xml
该文件是最主要的配置项,关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置。MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0" ?> <!DOCTYPE mycat :schema SYSTEM "schema.dtd" > <mycat:schema xmlns:mycat ="http://org.opencloudb/" > <schema name ="TESTDB" checkSQLschema ="false" sqlMaxLimit ="100" > <table name ="user" dataNode ="dn1,dn2" rule ="auto-sharding-long" /> <table name ="stat_tcp_stream" dataNode ="dn2,dn3" rule ="auto-sharding-long" /> </schema > <dataNode name ="dn1" dataHost ="localhost1" database ="mpos_tshark_miner_2014" /> <dataNode name ="dn2" dataHost ="localhost2" database ="mpos_tshark_miner2014" /> <dataNode name ="dn3" dataHost ="localhost3" database ="mpos_tshark_hrtel" /> <dataHost name ="localhost1" maxCon ="1000" minCon ="10" balance ="0" dbType ="mysql" dbDriver ="jdbc" writeType ="0" switchType ="1" slaveThreshold ="100" > <heartbeat > select user()</heartbeat > <writeHost host ="hostM1" url ="jdbc:mysql://192.168.1.150:5029" user ="root" password ="root" > </writeHost > </dataHost > <dataHost name ="localhost2" maxCon ="1000" minCon ="1" balance ="0" dbType ="mysql" dbDriver ="jdbc" > <heartbeat > </heartbeat > <writeHost host ="hostM2" url ="jdbc:mysql://192.168.1.150:5029" user ="root" password ="root" > </writeHost > </dataHost > <dataHost name ="localhost3" maxCon ="1000" minCon ="1" balance ="0" dbType ="mysql" dbDriver ="jdbc" > <heartbeat > </heartbeat > <writeHost host ="hostM3" url ="jdbc:mysql://192.168.1.150:5029" user ="root" password ="root" > </writeHost > </dataHost > </mycat:schema >
【配置参数解释说明】
参数 说明 schema 数据库设置,此数据库为逻辑数据库,name与server.xml文件中的schema对应 dataNode 分片信息,也就是分库相关配置 dataHost 物理数据库,真正存储数据的数据库
【配置说明】
name 属性唯一标识dataHost标签,供上层的标签使用 maxCon 属性指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标签都会使用这个属性的值来实例化出连接池的最大连接数 minCon 属性指定每个读写实例连接池的最小连接,初始化连接池的大小
实战案例:利用MyCat实现MySQL读写分离 【实验架构】
【实验环境】
1 2 3 mycat-server 192.168.119.150 mysql-master 192.168.119.128 mysql-slave 192.168.119.138
【实验步骤】
1、创建主从复制架构,基于之前的实验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [root@mysql-slave ~] mysql: [Warning] Using a password on the command line interface can be insecure. *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.119.128 Master_User: replyuser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000013 Read_Master_Log_Pos: 877 Relay_Log_File: Rocky8-mini2-relay-bin.000033 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000013 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 877 Relay_Log_Space: 848 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 128 Master_UUID: fa5a0767-ba39-11ed-b05a-000c294da889 Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log ; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version:
2、在代理服务器 192.168.119.150 上安装 mycat 服务
1 2 3 [root@mycat-server ~] LISTEN 0 128 *:8066 *:*
3、在MyCat服务器上修改server.xml文件来配置MyCat的连接信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@mycat-server ~]# vim /apps/mycat/conf/server.xml <property name ="serverPort" > 3306</property > <property name ="managerPort" > 9066</property > <property name ="idleTimeout" > 300000</property > <property name ="authTimeout" > 15000</property > <property name ="bindIp" > 0.0.0.0</property > <property name ="dataNodeIdleCheckPeriod" > 300000</property > <property name ="frontWriteQueueSize" > 4096</property > <property name ="processors" > 32</property > <user name ="root" defaultAccount ="true" > <property name ="password" > wuhaolam</property > <property name ="schemas" > hellodb,db1</property > </user > 注意: 这里使用的用户名为root,密码为wuhaolam,逻辑数据库名为hellodb和db1,这些信息可以随意定义,读写权限都有,没有对表做任何特殊的权限。其它默认。
4、修改schema.xml实现读写分离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@mycat-server ~]# vim /apps/mycat/conf/schema.xml <?xml version="1.0" ?> <!DOCTYPE mycat :schema SYSTEM "schema.dtd" > <mycat:schema xmlns:mycat ="http://io.mycat/" > <schema name ="hellodb" checkSQLschema ="false" sqlMaxLimit ="100" dataNode ="dn1" > </schema > <schema name ="db1" checkSQLschema ="false" sqlMaxLimit ="100" dataNode ="dn2" > </schema > <dataNode name ="dn1" dataHost ="localhost1" database ="hellodb" /> <dataNode name ="dn2" dataHost ="localhost1" database ="db1" /> <dataHost name ="localhost1" maxCon ="1000" minCon ="10" balance ="1" writeType ="0" dbType ="mysql" dbDriver ="native" switchType ="1" slaveThreshold ="100" > <heartbeat > select user()</heartbeat > <writeHost host ="hostM1" url ="192.168.119.128:3306" user ="mycat" password ="wuhaolam" > <readHost host ="hostS1" url ="192.168.119.138:3306" user ="mycat" password ="wuhaolam" > </readHost > </writeHost > </dataHost > </mycat:schema > 注意: 要保证能使用mycat用户登录进入后面的真实的数据库。
5、在后端服务器创建用户并对MyCat授权
1 2 3 4 5 09:25:24(root@localhost) [(none)]> grant all on *.* to 'mycat'@'192.168.119.%' identified by 'wuhaolam'; Query OK, 0 rows affected, 1 warning (0.00 sec) 10:39:17(root@localhost) [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec)
6、连接MyCat服务器上连接并测试
1 2 3 4 5 6 7 8 :41: (root@192.168.119.150) [(none)]> show databases; +----------+ | DATABASE | +----------+ | db1 | | hellodb | +----------+ 2 rows in set (0.01 sec)
7、开启通用日志确认实现读写分离
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 # 在主从服务器上临时开启通用日志 10 :39 :24 (root@localhost ) [(none )]> set global general_log= 1 ;# 插入的数据在 mysql- master 主机上显示日志信息 [root@mysql - master ~ ]# tail - f / data/ mysql/ Rocky8- mini.log 2023 -03 -12 T14:51 :41.162054 Z 114 Query select user ()2023 -03 -12 T14:51 :51.161289 Z 114 Query select user ()2023 -03 -12 T14:52 :01.161901 Z 114 Query select user ()2023 -03 -12 T14:52 :11.161869 Z 114 Query select user ()2023 -03 -12 T14:52 :14.012241 Z 114 Init DB hellodb2023 -03 -12 T14:52 :14.012377 Z 114 Query SET names utf8;2023 -03 -12 T14:52 :14.012991 Z 114 Query insert teachers values (7 ,'ShanZhi' ,'35' ,'M' )2023 -03 -12 T14:52 :21.162882 Z 114 Init DB db12023 -03 -12 T14:52 :21.163033 Z 114 Query select user ()2023 -03 -12 T14:52 :31.164418 Z 114 Query select user ()2023 -03 -12 T14:52 :41.161604 Z 114 Query select user ()# 查询的信息在 mysql- slave 上显示信息 [root@mysql - slave ~ ]# tail - f / data/ mysql/ Rocky8- mini2.log 2023 -03 -12 T14:49 :43.965851 Z 50 Connect mycat@192 .168 .119 .150 on db1 using TCP/ IP2023 -03 -12 T14:49 :43.966087 Z 51 Connect mycat@192 .168 .119 .150 on hellodb using TCP/ IP2023 -03 -12 T14:49 :53.962295 Z 44 Query select user ()2023 -03 -12 T14:50 :03.963241 Z 48 Query select user ()2023 -03 -12 T14:50 :12.369474 Z 51 Query SET names utf8;2023 -03 -12 T14:50 :12.369682 Z 51 Query show tables2023 -03 -12 T14:50 :13.964787 Z 43 Query select user ()2023 -03 -12 T14:50 :23.965344 Z 46 Query select user ()2023 -03 -12 T14:50 :24.792032 Z 51 Query select * from teachers2023 -03 -12 T14:50 :33.962562 Z 50 Query select user ()# select user () 为MyCat对后端服务器进行健康性检查 # 停止从节点,MyCat会将请求调度至主节点; 但停止主节点,不会将请求调度至从节点
MySQL 高可用性 MHA Master High Availability MHA 工作原理和架构 MHA 集群架构
MHA 工作原理
1、MHA 利用 select 1 as value 指令判断 Master 服务器的健康性,一旦 Master 宕机,MHA 从宕机崩溃的 Master 保存 binlog events
2、识别含有最新的 slave,即从 Master 同步数据最全的 slave
3、应用差异的 Relay log 到其它的 slave
4、应用从 Master 保存的二进制日志事件 (binlog events)
5、提升一个 slave 为新的Master
6、使其它的 slave 连接新的 Master 进行复制
注意 :为了尽可能减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL的半同步复制
MHA 软件
MHA 软件由两部分组成,Manager 工具包和 Node 工具包
Manager 工具包主要包含的工具如下:
1 2 3 4 5 6 7 8 9 masterha_check_ssh 检查MHA的SSH配置状况 masterha_check_repl 检查MySQL复制状况 masterha_manager 启动MHA masterha_check_status 检测当前MHA运行状态 masterha_master_monitor 检测master是否宕机 masterha_master_switch 故障转移(手动或自动) masterha_conf_host 添加或删除配置的server信息 masterha_stop --conf=app1.cnf 停止MHA masterha_secondary_check 两个或多个网络线路检查MySQL主服务器的可用
Node 工具包: 这些工具通常由MHA Manager的脚本触发,无需人为操作
1 2 3 4 save_binary_logs 保存和赋值master的二进制日志 apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的slave filter_mysqlbinlog 去除不必要的ROLLBACK事件(MHA已经不在使用此工具) purge_relay_logs 清楚中继日志(不会阻塞SQL线程)
MHA 自定义扩展
1 2 3 4 5 6 secondary_check_script 通过多条网络路由检测master的可用性 master_ip_ailover_script 更新Application使用的masterip shutdown_script 强制关闭master节点 report_script 发送报告 init_conf_load_script 加载初始配置参数 master_ip_online_change_script 更新master节点的IP地址
MHA 配置文件
1 2 global 配置,为各application提供默认配置,默认文件路径 /etc/masterha_default.cnf application 配置: 为每一个主从复制集群提供配置
MHA 实战案例 【实验架构图和环境】
1 2 3 4 5 【实验环境】 192.168.119.142 centos7 MHA管理端 192.168.119.138 Rocky8 mysql-master 192.168.119.129 Rocky8 mysql-slave1 192.168.119.150 Rocky8 mysql-slave2
1、在 MHA 管理节点安装 Manager 和 Node 包 下载地址:
https://github.com/yoshinorim/mha4mysql-manager/releases
https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58
1 2 3 4 [root@MHA ~] anaconda-ks.cfg mha4mysql-manager-0.58-0.el7.centos.noarch.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@MHA ~] [root@MHA ~]
2、在所有MySQL服务器上安装 mha4mysql-node 包 1 2 3 [root@mysql-master ~] [root@mysql-slave1 ~] [root@mysql-slave2 ~]
3、在所有节点之间实现key验证 使用脚本实现key验证 ,注意根据自己的环境修改脚本中需要互相实现key验证的主机
4、在管理节点建立配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 [root@MHA ~] [root@MHA ~] [server default] user=mhauser password=wuhaolam manager_workdir=/data/mastermha/app1/ manager_log=/data/mastermha/app1/manager.log remote_workdir=/data/mastermha/app1/ ssh_user=root repl_user=repluser repl_password=wuhaolam ping_interval=1 master_ip_failover_script=/usr/local/bin/master_ip_failover report_script=/usr/local/bin/sendmail.sh check_repl_delay=0 master_binlog_dir=/data/mysql/ [server1] hostname=192.168.119.138 candidate_master=1 [server2] hostname=192.168.119.129 candidate_master=1 [server3] hostname=192.168.119.150
说明:当主库宕机谁来接管新的master
1 2 3 1、所有节点日志都是一致的,默认会以配置文件的顺序去选择一个新主 2、从节点日志不一致,自动选择最接近于主库的从库充当新主 3、如果对于某个节点设置了权重(candidate_master=1),权重节点会优先选择。但是此节点日志量落后于主库超过100M也不会被选择。可以配合check_repl_delay=0,关闭日志量的检查,强制选择候选节点
5、相关脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 [root@MHA ~] echo "MySQL is down" | mail -s 'MHA warning' wuhaolam@163.com [root@MHA ~] [root@MHA ~] use strict;use warnings FATAL => 'all' ;use Getopt::Long;my ($command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_port, $new_master_host, $new_master_ip, $new_master_port ); my $vip = '192.168.119.100/24' ;my $brdc = '192.168.119.255' ;my $gateway = '192.168.119.2' ;my $interface = 'eth0' ;my $key = "1" ;my $ssh_start_vip = "/sbin/ifconfig $interface:$key $vip;/sbin/arping -I $interface -c 3 -s $vip $gateway >/dev/null 2>&1" ;my $ssh_stop_vip = "/sbin/ifconfig $interface:$key down" ;GetOptions( 'command=s' => \$command,'ssh_user=s' => \$ssh_user,'orig_master_host=s' => \$orig_master_host,'orig_master_ip=s' => \$orig_master_ip,'orig_master_port=i' => \$orig_master_port,'new_master_host=s' => \$new_master_host,'new_master_ip=s' => \$new_master_ip,'new_master_port=i' => \$new_master_port,); exit &main();sub main {print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n" ;if ( $command eq "stop" || $command eq "stopssh" ) {my $exit_code = 1 ;eval {print "Disabling the VIP on old master: $orig_master_host \n" ;&stop_vip(); $exit_code = 0 ; }; if ($@) {warn "Got Error: $@\n" ;exit $exit_code;} exit $exit_code;} elsif ( $command eq "start" ) {my $exit_code = 10 ;eval {print "Enabling the VIP - $vip on the new master - $new_master_host \n" ;&start_vip(); $exit_code = 0 ; }; if ($@) {warn $@;exit $exit_code;} exit $exit_code;} elsif ( $command eq "status" ) {print "Checking the Status of the script.. OK \n" ;`ssh $ssh_user\@$orig_master_host \" $ssh_start_vip \"` ;exit 0 ;} else {&usage(); exit 1 ;} } sub start_vip () {`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"` ;} sub stop_vip () {`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"` ;} sub usage {print "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n" ;} [root@MHA ~]
6、实现数据库Master节点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 [root@mysql-master ~] . /etc/init.d/functions PackageDir="/root" PackageName="mysql-5.7.40-linux-glibc2.12-x86_64" MysqlRootPassword="wuhaolam" ID=`ip a show eth0 | awk -F'[./]' '/\<inet\>/ {print $4}' ` yum -y install libaio numactl-libs libncurses* &> /dev/null || { echo -e "\033[1;31minstall package fail\033[0m" ;exit 1; } if ! id mysql &> /dev/null;then groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql fi if [ -d /data/mysql ];then action "数据库存在,退出安装" /bin/false exit 1 else mkdir -p /data/mysql/ && chown -R mysql:mysql /data/mysql/ fi [ -e ${PackageDir} /${PackageName} .tar.gz ] || { echo -e "\033[1;31mPackage file is not exits\033[0m" ;exit 1; } tar xf ${PackageDir} /${PackageName} .tar.gz -C /usr/local/ cd /usr/local/ln -s ${PackageName} / mysqlchown -R root:root /usr/local/mysql/echo 'PATH=/usr/local/mysql/bin:$PATH' > /etc/profile.d/mysql.sh. /etc/profile.d/mysql.sh cat > /etc/my.cnf << EOF [client] port=3306 socket=/data/mysql/mysql.sock [mysql] prompt="\\r:\\m:\\s(\\u@\\h) [\\d]>\\_" [mysqld] log-bin=/data/mysql/mysql-bin server-id=${ID} datadir=/data/mysql socket=/data/mysql/mysql.sock user=mysql symbolic-links=0 skip_name_resolve=1 log-error=/data/mysql/mysql.log pid-file=/data/mysql/mysql.pid EOF mysqld --initialize --user=mysql --datadir=/data/mysql &> /dev/null cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqldchkconfig --add mysqld chkconfig mysqld on service mysqld start &> /dev/null && echo -e "\033[1;32mMySQL startup success\033[0m" || { echo -e "\033[1;31mMySQL startup failed\033[0m" ;exit 1; } Password=`awk '/A temporary password/ {print $11}' /data/mysql/mysql.log` mysqladmin -uroot -p${Password} password ${MysqlRootPassword} &> /dev/null && action "数据库安装完成" /bin/true || action "密码修改失败" /bin/false -------------------------------------------------------------------- :08: (root@localhost) [(none)]> show master logs; +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 177 | | mysql-bin.000002 | 414 | +------------------+-----------+ 2 rows in set (0.00 sec) :08: (root@localhost) [(none)]> create user repluser@'192.168.119.%' identified by 'wuhaolam' ; Query OK, 0 rows affected (0.00 sec) :11: (root@localhost) [(none)]> grant replication slave on *.* to repluser@'192.168.119.%' ; Query OK, 0 rows affected (0.00 sec) :12: (root@localhost) [(none)]> create user mhauser@'192.168.119.%' identified by 'wuhaolam' ; Query OK, 0 rows affected (0.00 sec) :12: (root@localhost) [(none)]> grant all on *.* to mhauser@'192.168.119.%' ; Query OK, 0 rows affected (0.00 sec) :16: (root@localhost) [(none)]> flush privileges; Query OK, 0 rows affected (0.00 sec) [root@mysql-master ~]
7、实现slave 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@mysql-slave1 ~] [client] port=3306 socket=/data/mysql/mysql.sock [mysql] prompt="\r:\m:\s(\u@\h) [\d]>\_" [mysqld] log-bin=/data/mysql/mysql-bin server-id=129 datadir=/data/mysql socket=/data/mysql/mysql.sock user=mysql symbolic-links=0 skip_name_resolve=1 relay_log_purge=0 log-error=/data/mysql/mysql.log pid-file=/data/mysql/mysql.pid :59: (root@localhost) [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.119.138' , MASTER_USER='repluser' , MASTER_PASSWORD='wuhaolam' , MASTER_LOG_FILE='mysql-bin.000002' , MASTER_LOG_POS=414; Query OK, 0 rows affected, 2 warnings (0.01 sec) :01: (root@localhost) [(none)]> start slave; Query OK, 0 rows affected (0.00 sec)
8、检查MHA环境 1 2 3 4 5 [root@MHA ~] [root@MHA ~] [root@MHA ~] app1 is stopped(2:NOT_RUNNING).
9、启动MHA 1 2 3 4 5 6 7 8 9 10 11 12 [root@MHA ~] [root@MHA ~] app1 (pid:4523) is running(0:PING_OK), master:192.168.119.138 [root@mha ~] Thu Mar 23 22:45:26 2023 - [info] Checking SSH publickey authentication settings on the current master.. 192.168.119.138(192.168.119.138:3306) (current master)
10、模拟故障 1 2 3 4 5 6 [root@mysql-master ~] [root@MHA ~] app1 is stopped(2:NOT_RUNNING).
使用 tail -f /data/mastermha/app1/manager.log
查看具体的主从节点切换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 [root@mysql-slave1 ~] 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link /ether 00:0c:29:8b:d7:3c brd ff:ff:ff:ff:ff:ff inet 192.168.119.129/24 brd 192.168.119.255 scope global noprefixroute eth0 valid_lft forever preferred_lft forever inet 192.168.119.100/24 brd 192.168.119.255 scope global secondary eth0:1 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe8b:d73c/64 scope link valid_lft forever preferred_lft forever :39: (root@localhost) [(none)]> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.119.129 Master_User: repluser Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000004 Read_Master_Log_Pos: 154 Relay_Log_File: mysql-slave2-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000004 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 154 Relay_Log_Space: 534 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 129 Master_UUID: a3e552fe-ca22-11ed-9336-000c298bd73c Master_Info_File: /data/mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log ; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) ERROR: No query specified
11、故障修复 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@mysql-master ~] [root@mysql-slave1 ~] mysql: [Warning] Using a password on the command line interface can be insecure. +------------------+-----------+ | Log_name | File_size | +------------------+-----------+ | mysql-bin.000001 | 177 | | mysql-bin.000002 | 461 | | mysql-bin.000003 | 177 | | mysql-bin.000004 | 154 | +------------------+-----------+ [root@mysql-master ~] [root@mysql-master ~] [root@MHA ~] [root@MHA ~] [root@MHA ~] [root@MHA ~] app1 is stopped(2:NOT_RUNNING). [root@mha ~] [1] 2990 [root@mha ~] app1 (pid:2990) is running(0:PING_OK), master:192.168.119.129