MySQL多实例
多实例概念
在mysql3.25.15版本之后推出复制功能,复制意味着将一台服务器中的数据转移到另外一台或者多台服务器的过程
单机部署多个mysql,因为mysql占用资源少,体积小,所以如果一台服务器只安装一个mysql服务,会出现资源过剩的情况,可以将不同的mysql安装到不同的硬盘
MySQL复制流程
(1)主服务器将对于mysql更改的语句记录到二进制日志文件中(DDL,DML)也有一些DCL会被记录
(2)主服务器在确定授权用户之后,从服务器将主服务器的二进制日志复制到自己的中继日志中(relay-log)
(3)从服务器通过sql线程执行拉取到中继日志中的sql语句,将日志中的内容在从服务器重新执行一遍得到和主服务器一样的数据(事务)
多实例的用途
MYSQL在生产环境中,90%以上属于一主多从的架构模式,并且实现读写分离,将主服务器的压力分散到多台从服务器上,可以解决数据库压力瓶颈
多实例MySQL的管理工具
mysqld_multi工具实现mysql服务器的统一化管理,可以管理所有或者指定服务器的运行或者停止
mysqld_safe实现mysql服务器的单台运行的命令工具
mysqld_multi来同一管理各个mysql服务器的mysqld_safe
安装多实例
实验环境
一台Linux主机:192.168.1.1(已安装MySQL)
实验目的
在一台Linux安装启动多个MySQL服务进行使用
实验步骤
可以参考之前的文章安装一个MySQL服务,并且在部署其他MySQL时,不能有任何MySQL服务已经启动
创建其他实例的存放数据目录
# 创建目录mysql1,mysql2,mysql3
mkdir -p /usr/local/var/mysql{1,2,3}
初始化实例目录
多实例也不用重新安装,使用编译过的MySQL,重新初始化数据库到实例目录即可
cd /usr/local/mysql/
/usr/local/mysql/scripts/mysql_install_db --user=mysql --datadir=/usr/local/var/mysql1/data
/usr/local/mysql/scripts/mysql_install_db --user=mysql --datadir=/usr/local/var/mysql2/data
/usr/local/mysql/scripts/mysql_install_db --user=mysql --datadir=/usr/local/var/mysql3/data
如果在这报错FATAL ERROR: Could not find ./bin/my_print_defaults
,可能是缺少这个脚本文件,进入原来的mysql安装目录检查,如果没有问题,则查看是否进入到mysql安装目录,没有进入也会影响调用脚本问题,根据以上步骤做不会出问题
可以看到以上命令没有指定--basedir
是因为只需要使用原来安装的即可,,默认的就是当前目录,如果非要指定就输入--basedir=/usr/local/mysql
每一个目录的初始化结束后,在输出信息中可以看到如图所示的两个OK即成功
修改MySQL主配置文件
使MySQL可以识别新初始化成功的三个MySQL服务
vim /etc/my.cnf
# 添加mysqld_multi工具模块来管理mysql多实例服务
[mysqld_multi]
mysqld=/usr/local/mysql/bin/mysqld_safe # 管理开启mysql进程的工具
mysqladmin=/usr/local/mysql/bin/mysqladmin # 关闭mysql服务
user=root # 通过服务器root用户使用上述两条命令
[mysqld1]
port=3306 # 指定mysqld1服务的端口号
[mysqld2]
port=3307 # 指定mysqld2服务的端口号
socket=/usr/local/mysql/mysql2.sock # 此路径要和第一个mysql服务的socket路径一致,只有文件名不一样
datadir=/usr/local/var/mysql2/data # 指定mysqld2服务的数据存放目录
[mysqld3]
port=3308 # 指定mysqld3服务的端口号
socket=/usr/local/mysql/mysql3.sock
datadir=/usr/local/var/mysql3/data
mysqld1
服务没有指定socket文件和数据存放目录是因为它会沿用最开始mysql服务的文件和目录,后面会说到
启动MySQL多实例
查看多实例状态
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看多实例状态
Reporting MySQL servers
MySQL server from group: mysqld1 is not running
MySQL server from group: mysqld2 is not running
MySQL server from group: mysqld3 is not running
启动多实例
mysqld_multi --defaults-extra-file=/etc/my.cnf start # 启动
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看
Reporting MySQL servers
MySQL server from group: mysqld1 is running
MySQL server from group: mysqld2 is running
MySQL server from group: mysqld3 is running
停止多实例
mysqld_multi --defaults-extra-file=/etc/my.cnf stop
验证多实例
登录不同端口的MySQL服务
如果最开始的MySQL有密码则需要-p
指定密码
mysql -uroot -P3306 # 登录3306端口的mysql服务
mysql> SHOW VARIABLES LIKE 'port'; # 查看服务端口号
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3306 |
+---------------+-------+
mysql -uroot -P3307 # 登录3307端口的mysql服务
mysql> SHOW VARIABLES LIKE 'port'; # 查看服务端口号
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3306 |
+---------------+-------+
mysql -uroot -P3308 # 登录3308端口的mysql服务
mysql> SHOW VARIABLES LIKE 'port'; # 查看服务端口号
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3306 |
+---------------+-------+
从以上登录来看,发现不管登录哪个端口号的服务,查看到的端口号都是一样的。这是因为如果多实例MySQL服务登录客户端不指定socket文件的路径的话,会使用默认的socket文件,也就是3306的文件
- 网络上两个程序通过双向的通信实现数据交换,连接的每一个端称为一个socket,在mysql中使用socket添加在[mysqld]模块下,用于快速实现定义登录不同端口的mysqld,
-S
或者--socket=
锁定socket文件
重新使用对应的socket文件来登录不同端口号的mysqld服务
mysql -uroot -P3307 -S /usr/local/mysql/mysql2.sock
mysql> SHOW VARIABLES LIKE 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3307 |
+---------------+-------+
mysql -uroot -P3308 -S /usr/local/mysql/mysql3.sock
mysql> SHOW VARIABLES LIKE 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3308 |
+---------------+-------+
原服务与多实例服务数据冲突
还记得在之前修改配置文件时,没有给mysqld1服务指定数据目录和socket文件,也就是3306端口的服务,最开始的mysql使用的也是3306端口,因为端口的冲突,可能会导入停止服务时,mysqld1一直显示is running
的运行状态,查看进程号,强行关闭即可
先将服务停止
mysqld_multi --defaults-extra-file=/etc/my.cnf stop # 停止多实例服务
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看多实例状态
Reporting MySQL servers
MySQL server from group: mysqld1 is not running
MySQL server from group: mysqld2 is not running
MySQL server from group: mysqld3 is not running
更改配置文件中3306的数据目录
将mysqld1和mysql的3306的数据分割开
vim /etc/my.cnf
# 添加
[mysqld1]
port=3306
socket=/usr/local/mysql/mysql.sock # 可以继续使用旧的sock文件
datadir=/usr/local/var/mysql1/data # 数据目录使用多实例数据目录
如果不修改以上配置的话,登录到3306端口的服务,总是会看到最开始的3306的服务端口中存储过的数据
重新启动服务
mysqld_multi --defaults-extra-file=/etc/my.cnf start # 启动多实例
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看多实例状态
Reporting MySQL servers
MySQL server from group: mysqld1 is running
MySQL server from group: mysqld2 is running
MySQL server from group: mysqld3 is running
如果最开始使用3306端口的服务有密码的话,现在重新登录多实例的3306是没有密码的;或者如果最开始的有数据,现在重新登录就是一个全新的数据库
使用mysqld_multi工具管理多实例
选择性的对指定某个端口号服务的停止/启动
mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1 # 停止mysqld1的服务
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看状态
Reporting MySQL servers
MySQL server from group: mysqld1 is not running
MySQL server from group: mysqld2 is running
MySQL server from group: mysqld3 is running
mysqld_multi --defaults-extra-file=/etc/my.cnf stop 2,3 # 停止mysqld1/mysqld2的服务
mysqld_multi --defaults-extra-file=/etc/my.cnf report # 查看状态
Reporting MySQL servers
MySQL server from group: mysqld1 is not running
MySQL server from group: mysqld2 is not running
MySQL server from group: mysqld3 is not running
mysqld_multi --defaults-extra-file=/etc/my.cnf start 1-3 # 启动mysqld1/mysqld2/mysqld3的服务
mysqld_multi --defaults-extra-file=/etc/my.cnf report
Reporting MySQL servers
MySQL server from group: mysqld1 is running
MySQL server from group: mysqld2 is running
MySQL server from group: mysqld3 is running
这样的操作是对配置文件中新加的模块是有规定的,多实例必须是以[mysqld]
开头
多实例间主从复制
修改配置文件
vim /etc/my.cnf
# 每个服务模块添加server-id和二进制日志的位置指定
[mysqld1]
port=3306
socket=/usr/local/mysql/mysql.sock
datadir=/usr/local/var/mysql1/data
server-id=1 # 每个端口号必须不同,否则会失败
log-bin=/usr/local/var/mysql1/data/mysql-bin # 开启并指定二进制日志的路径
[mysqld2]
port=3307
socket=/usr/local/mysql/mysql2.sock
datadir=/usr/local/var/mysql2/data
server-id=2
log-bin=/usr/local/var/mysql2/data/mysql-bin
[mysqld3]
port=3308
socket=/usr/local/mysql/mysql3.sock
datadir=/usr/local/var/mysql3/data
server-id=3
log-bin=/usr/local/var/mysql3/data/mysql-bin
重新启动多实例服务
mysqld_multi --defaults-extra-file=/etc/my.cnf stop
mysqld_multi --defaults-extra-file=/etc/my.cnf start
既然是主从复制,就要分为主和从,这里以3306为主,3307/3308为从,所以需要在3306的服务客户端中为其他两个服务进行复制的授权
mysql -uroot -P3306 # 登录3306服务客户端
mysql> GRANT ALL ON *.* TO 'slave'@'192.168.1.%' IDENTIFIED BY '123.com';
mysql> show master status; # 查看二进制日志文件的偏移量
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 326 | | | |
+------------------+----------+--------------+------------------+-------------------+
为了更好的看出复制的的效果,先在3306中创建一个数据库
mysql> CREATE DATABASE cyj;
Query OK, 1 row affected (0.00 sec)
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| cyj | # 3306中新添加的数据库
| mysql |
| performance_schema |
| test |
+--------------------+
登录3307/3308指定复制3306的数据
mysql -uroot -P3307 -S /usr/local/mysql/mysql2.sock
mysql> SHOW DATABASES; # 查看3307中确实没有cyj数据库
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
# 开始复制
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.1', # 指定复制的主机,单机多实例主从可以写127.0.0.1
-> MASTER_USER='slave', # 3306授权时的用户
-> MASTER_PASSWORD='123.com', # 3306授权时的密码
-> MASTER_PORT=3306, # 3306服务的端口号
-> MASTER_LOG_FILE='mysql-bin.000001', # 指定复制的二进制文件名
-> MASTER_LOG_POS=326; # 指定二进制文件中的偏移量
# 启动从功能
mysql> start slave;
mysql> SHOW slave STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.1
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 417
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 374
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 看到以上这两条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: 417
Relay_Log_Space: 547
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 6907f123-6769-11ea-8a85-000c291bb9fe
Master_Info_File: /usr/local/var/mysql2/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
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
3308也是相同的步骤,完成之后查看3307/3308中的数据库,已经成功复制了3306刚才创建的cyj数据库
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| cyj |
| mysql |
| performance_schema |
| test |
+--------------------+
※如果把mysqld1的服务停止了,使用之前的systemctl start mysqld还可以启动之前旧的3306服务,而且之前的数据还在
mysqld_multi --defaults-extra-file=/etc/my.cnf stop 1
systemctl start mysqld
mysql -u root