配置MySQL服务多实例

2024-08-25 23:06:00
丁国栋
原创 178
摘要:配置MySQL服务多实例的最佳实践和注意事项。

因为使用容器部署MySQL有一些弊端,例如性能损失、可维护性等,所以我们选择在同一个Linux性能主机上部署多个MySQL实例,每个MySQL实例都独立提供完整的MySQL服务。

为了实现这个目标我们需要使用通用二进制的安装方式。我们可以去查阅MySQL官方的手册,例如


实际测试发现,在Ubuntu 22.04(jammy)中无法使用systemd来配置MySQL的多实例,原因是默认安装的MySQL服务器并没有支持通过systemd配置并启动。


在RHEL8中使用systemd配置mysql多实例。

RHEL8系统信息

系统版本:8.6 (Core)

内核版本:4.19.0-372.26.6.el8

systemd版本:systemd-239-58.0.4.an8_6.8.x86_64

MySQL版本:mysql-server-8.0.26


编辑 /etc/my.cnf 文件,添加以下内容:


[mysqld@replica01]
datadir=/var/lib/mysql-replica01
socket=/var/lib/mysql-replica01/mysql.sock
port=3307
mysqlx_port=33071 
log-error=/var/log/mysqld-replica01.log
pid-file=/run/mysqld/mysql-replica01.pid
bind-address=::
innodb_data_home_dir=/var/lib/mysql-replica01
[mysqld@replica02]
datadir=/var/lib/mysql-replica02
socket=/var/lib/mysql-replica02/mysql.sock
port=3308
mysqlx_port=33081 
log-error=/var/log/mysqld-replica02.log
pid-file=/run/mysqld/mysql-replica02.pid
bind-address=::
innodb_data_home_dir=/var/lib/mysql-replica02

接下来MySQL官方文档和RHEL8 systemd 的 unit 文件有所不同。我们要检查 /usr/lib/systemd/system/mysqld@.service 文件里的配置是不是 --defaults-group-suffix=@%I ,默认是 --defaults-group-suffix=.%I 这里是与MySQL官方文档不一样的地方,RHEL8这个发行版与之不同。


--defaults-group-suffix 是 MySQL 多实例管理的参数,用于区分不同实例的配置组(在 my.cnf 或 my-server.cnf 中)。
例如,若实例名为 instance1,则:

  • @%I 会匹配 [mysqld@instance1] 配置组。
  • .%I 会匹配 [mysqld.instance1] 配置组。

systemd 模板单元名为 mysqld@.service(使用 @ 符号),因此配置组后缀也采用 @%I 以保持命名一致性。

MySQL官方文档中提到:

systemd starts the server using a command such as this:
mysqld --defaults-group-suffix=@%I ...
The result is that the [server], [mysqld], and [mysqld@replica01] option groups are read and used for that instance of the service.

/usr/lib/systemd/system/mysqld@.service 例子

[Unit]
Description=MySQL 8.0 database server
After=syslog.target
After=network.target
[Service]
Type=notify
User=mysql
Group=mysql
ExecStartPre=/usr/libexec/mysql-check-socket --defaults-group-suffix=@%I
ExecStartPre=/usr/libexec/mysql-prepare-db-dir --defaults-group-suffix=@%I %n
# Note: we set --basedir to prevent probes that might trigger SELinux alarms,
# per bug #547485
ExecStart=/usr/libexec/mysqld --defaults-group-suffix=@%I --basedir=/usr
ExecStartPost=/usr/libexec/mysql-check-upgrade --defaults-group-suffix=@%I
ExecStopPost=/usr/libexec/mysql-wait-stop --defaults-group-suffix=@%I
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=300
# Place temp files in a secure directory, not /tmp
PrivateTmp=true
Restart=on-failure
RestartPreventExitStatus=1
# Sets open_files_limit
LimitNOFILE = 10000
# Set enviroment variable MYSQLD_PARENT_PID. This is required for SQL restart command.
Environment=MYSQLD_PARENT_PID=1
[Install]
WantedBy=multi-user.target
如果在启动时遇到问题,可以结合journal日志和MySQL错误日志修改。


使用通用二进制方式配置MySQL多实例。

所以我们依然使用传统的安装配置方式,每个实例使用单独的目录,使用mysqld命令初始化数据库,使用support-files/mysql.server来启动和关闭MySQL数据库。


因为主机上已经安装过MySQL server并且处于运行中,所以我们在安装第二个实例时就可以复用一些配置,比如省去了新增mysql用户和组。同时端口号需要用另外一个,不能使用默认的3306端口。


我们以 mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz 为例,演示在 Ubuntu 22.04 jammy  上配置,配置其服务端口为3307。

先准备一个基本的my.cnf配置文件:

[mysqld]
datadir=/usr/local/mysql/3307/data
socket=/usr/local/mysql/3307/mysql.sock
port=3307
log-error=/usr/local/mysql/3307/error.log

基本命令大致如下:

groupadd mysql
useradd -r -g mysql -s /bin/false mysql
cd ~/downloads
wget -c https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
tar xf mysql-5.7.30-linux-glibc2.12-x86_64.tar.gz
mkdir -p /usr/local/mysql/3307/
rsync -a ~/downloads/mysql-5.7.30-linux-glibc2.12-x86_64/ /usr/local/mysql/3307/
cd /usr/local/mysql/3307
#find /usr/local/mysql/3307/data -delete
echo |sudo tee /usr/local/mysql/3307/error.log
chown mysql:mysql -R /usr/local/mysql
/usr/local/mysql/3307/bin/mysqld --defaults-file=/usr/local/mysql/3307/my.cnf --basedir=/usr/local/mysql/3307 --datadir=/usr/local/mysql/3307/data --lc-messages-dir=/usr/local/mysql/3307/share --lc-messages=en_US --explicit_defaults_for_timestamp --initialize --user=mysql --console --log-error=/usr/local/mysql/3307/error.log
/usr/local/mysql/3307/support-files/mysql.server start

以上步骤需要注意以下几点:

  1. bin/mysqld第一个参数必须是 --defaults-file=/usr/local/mysql/3307/my.cnf,否则mysqld可能会加载其他 mysql 配置文件,导致初始化失败。
  2. 在使用mysqld初始化数据库时使用了--console --log-error=/usr/local/mysql/3307/error.log 参数,数据库的默认密码会输出到 /usr/local/mysql/3307/error.log 日志中,搜索字符串 [Note] A temporary password is generated for root@localhost
  3. Ubuntu系统特有的apparmor类似RHEL系的SELinux,需要进行配置或者禁用,否则可能会在/var/log/syslog里收到来自内核(apparmor运行在内核)的错误提示 apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/usr/local/mysql/3307/share/english/errmsg.sys" pid=1036654 comm="mysqld" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/usr/local/mysql/3307/data/" pid=1036654 comm="mysqld" requested_mask="r" denied_mask="r" fsuid=1000 ouid=135

使用密码登录到新的MySQL实例

sudo mysql -S /usr/local/mysql/3307/mysql.sock -p


使用ALTER USER语句完成用户的初始化(就像首次使用必须更改密码),否则会收到mysql提示:ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'XXXXXXXX'

在配置和调试的过程中,我们需要有以下认知:


  1. 从可信的官网文档中查找最佳实践方法,确保方法是对的,可以行得通的,如果出现问题,那问题多数不在官方,而是在自己的环境和步骤中;
  2. 在遇到问题时,坚信没有诡异的问题,只有没有搞明白的问题,问题依然存在的原因只是因为我们没有找到问题的根源;
  3. 保持心平气和的心态,不浮躁;


发表评论
博客分类