创建多实例的 MariaDB
配置 mysqld_multi
若没有安装,先安装 MySQL, 另外 MySQL root 的 plugin 需采用 mysql_native_password。
为了同一台机器上管理两个 MySQL 实例,需要使用 mysqld_multi。 在 /etc/mysql/mariadb.conf.d/50-server.cnf 文档中创建两组实例组态。
# 在您修改 50-server.cnf 之前要 停止 MySQL 非常重要! sudo systemctl stop mysql # 需要修改 50-server.cnf,可先备份。 mkdir ~/bak cp /etc/mysql/mariadb.conf.d/50-server.cnf ~/bak
- 50-server.cnf 文件位置
-
- Linux
-
/etc/mysql/mariadb.conf.d/50-server.cnf
- Windows
-
\\%host%\root\etc\mysql\mariadb.conf.d\50-server.cnf
# this is only for the mysqld standalone daemon
[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid (1)
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql (2)
1 | 运行时创建的文件。注意! 确认该行是否跟您安装的 MariaDB 一样。 |
2 | 数据库文件夹 |
# this is only for the mysqld standalone daemon
[mysqld]
#
# * Basic Settings
#
# Multiple MySQL server configuration [mysqld_multi] mysqld = /usr/bin/mysqld_safe mysqladmin = /usr/bin/mysqladmin log = /var/log/mysqld_multi.log user = multi_admin password = 'multipass'(1) [mysqld2](2) server-id = 2 innodb_flush_method = O_DIRECT user = mysql pid-file = /var/run/mysqld/mysqld2.pid socket = /var/run/mysqld/mysqld2.sock port = 3307 basedir = /usr datadir = /var/lib/mysql2 tmpdir = /tmp lc-messages-dir = /usr/share/mysql skip-external-locking bind-address = 127.0.0.1 key_buffer_size = 16M max_allowed_packet = 16M thread_stack = 192K thread_cache_size = 8 myisam-recover = BACKUP query_cache_limit = 1M query_cache_size = 16M # log_error = /var/log/mysql/error.log expire_logs_days = 10 max_binlog_size = 100M character-set-server = utf8mb4 collation-server = utf8mb4_general_ci # this is only for the mysqld standalone daemon [mysqld1](3) server-id = 1 innodb_flush_method = O_DIRECT innodb_flush_log_at_trx_commit = 1 sync_binlog = 0 binlog-format = ROW binlog_do_db = mybb # # * Basic Settings #
1 | multipass 改为您要的密码,建议不要改。 |
2 | 增加 [mysqld2] 区段 (其实是拷贝原始的 [mysqld] 再改数据库位置)。 |
3 | 原始的 [mysqld] 变成 [mysqld1]。这里会混淆,[mysqld] 区段码覆已被覆盖成 [mysqld1] 区段码,原始的 [mysqld] 内容并没有变化。 |
最后,把 [mysqld1] (原本的 [mysqld]) 内的 log_error
注解成 # log_error
。
...
# this is only for the mysqld standalone daemon
[mysqld1]
server-id = 1
...
#
# Error log - should be very few entries.
#
# log_error = /var/log/mysql/error.log (1)
1 | 注解本行。 |
为什么? 因为在 /var/log/mysqld_multi.log
会有下列消息,该消息已说明要把 log-error 的组态关闭。
200925 18:46:07 mysqld_safe Can’t log to error log and syslog at the same time. Remove all --log-error configuration options for --syslog to take effect.
安装第二个 MySQL2 实例
sudo mysql_install_db --user=mysql --datadir=/var/lib/mysql2 --force
sudo mysqld_multi start
显示 mysqld_multi 数据库状态: sudo mysqld_multi report Reporting MariaDB servers MariaDB server from group: mysqld2 is running MariaDB server from group: mysqld1 is running (1)
1 | 如果不是上述消息表示有错,查一下 tail /var/log/mysqld_multi.log 。 |
检查 MySQL 行程情况:
ps -e | grep "mysql" (1)
1475 ? 00:00:00 mysqld_safe
1622 ? 00:00:07 mysqld
1889 pts/4 00:00:00 mysqld_safe
2282 pts/4 00:00:02 mysqld
检查 MySQL 通信情况:
sudo netstat -tlpn | grep mysql (1)
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 1622/mysqld
tcp 0 0 127.0.0.1:3307 0.0.0.0:* LISTEN 2282/mysqld
检查 3306 3307 通信情况:
sudo netstat -nlt | grep 330
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3307 0.0.0.0:* LISTEN
1 | 如果 netstat 命令不存在,运行 sudo apt install net-tools -y 安装。 |
mysqld2 改为原生密码认证
mysqlpw='MySQL root 密码'
sudo mysql --host=localhost --port=3307 --protocol=tcp mysql
-- 先显示 root 用户的远程帐号 (在 mysql 内):
select user, host from user where user='root' and host <> 'localhost';
-- 删除 root 除了 localhost 之外的其他远程帐号:
delete from user where user='root' and host <> 'localhost';
-- 原生密码认证需同时设置密码及 plugin:
update mysql.user set password=password('$mysqlpw') where user='root';
update user set plugin='mysql_native_password' where user='root';
flush privileges;
-- 退出 mysql
exit;
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp mysql
set global time_zone = '+8:00';
set time_zone = '+8:00';
检查调整后的情况: select timediff(now(), utc_timestamp); 结果如下: +--------------------------------+ | timediff(now(), utc_timestamp) | +--------------------------------+ | 08:00:00 | +--------------------------------+
mysqld_multi 关闭及启动
protocol=tcp
才有作用先不指定 protocol:
mysql -uroot -p$mysqlpw --host=localhost --port=3307 -N \
-e "show variables where variable_name = 'port';"
port 3306
登录 3307 但实际却为 3306,显然不正确。
指定 protocol=tcp:
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp -N \
-e "show variables where variable_name = 'port';"
port 3307
登录参数加上 protocol=tcp 才正确。
# mysqld1 授予 multi_admin 关闭数据库权限
mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp<<EOF
grant shutdown on *.* to 'multi_admin'@'localhost' identified by 'multipass'; (1)
flush privileges;
EOF
#mysqld2 授予 multi_admin 关闭数据库权限
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp<<EOF
grant shutdown on *.* to 'multi_admin'@'localhost' identified by 'multipass'; (1)
flush privileges;
EOF
1 | 要跟 50-server.cnf 内的 password='multipass ' 一致。 |
停止 mysqld_multi:
sudo mysqld_multi stop
显示 mysqld_multi 状态:
sudo mysqld_multi report
Reporting MariaDB servers
MariaDB server from group: mysqld2 is not running (1)
MariaDB server from group: mysqld1 is not running
启动 mysqld_multi:
sudo mysqld_multi start
显示 mysqld_multi 状态:
sudo mysqld_multi report
Reporting MariaDB servers
MariaDB server from group: mysqld2 is running
MariaDB server from group: mysqld1 is running
检查 mysqld_multi.log 是否异常:
tail /var/log/mysqld_multi.log -n20
1 | 如果不是上述消息表示有错, 检查一下前面的 multi_admin 关闭数据库权限。 |
sudo mysqld_multi stop
sudo mysqld_multi start
sudo mysqld_multi report
sudo systemctl disable mysql (1)
1 | mysql 的服务状态可能失效;为正常现像。
显示 mysql 服务状态: systemctl status mysql 结果如下: Status: "MariaDB server is down" Active: inactive (dead) |
sudo bash -c 'cat > /etc/init.d/mysqld_multi' << "EOF"
#!/bin/sh
### BEGIN INIT INFO
# Provides: scriptname
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Enable service provided by daemon.
### END INIT INFO
bindir=/usr/bin
if [ -x $bindir/mysqld_multi ]; then(1)
mysqld_multi="$bindir/mysqld_multi";
else
echo "Can't execute $bindir/mysqld_multi";
exit;
fi
bindir=/usr/bin
if test -x $bindir/mysqld_multi
then
mysqld_multi="$bindir/mysqld_multi";
else
echo "Can't execute $bindir/mysqld_multi";
exit;
fi
case "$1" in
'start' )
"$mysqld_multi" start $2(2)
;;
'stop' )
"$mysqld_multi" stop $2
;;
'report' )
"$mysqld_multi" report $2 >&2
;;
'restart' )
"$mysqld_multi" stop $2
"$mysqld_multi" start $2
;;
'status' )
"$mysqld_multi" report >&2
status=4
if [ -f /var/run/mysqld/mysqld.pid ]; then
if [ -f /var/run/mysqld/mysqld2.pid ]; then
status=0
fi
elif [ ! -f /var/run/mysqld/mysqld2.pid ]; then
status=3
fi
if [ $status -eq 4 ]; then
echo 'Usage: Make the service show question mark' >&2(3)
fi
exit $status
;;
*)
echo "Usage: $0 {start|stop|report|restart|status}" >&2
;;
esac
EOF
sudo chmod +x /etc/init.d/mysqld_multi
sudo update-rc.d mysqld_multi defaults
sudo update-rc.d mysqld_multi enable
1 | 启动 mysqld_multi 服务是运行 MySQL 已经写好的
/usr/bin/mysqld_multi (参阅: Manage Multiple MySQL Servers )。 |
2 | 虽然有实作第二个参数,但如果运行 service mysqld_multi [start | stop | restart] 将忽略第 2 个参数,
另外 service (systemctl) 只会判断主要实例作为是否真正需要运行启动、停止或重启,如果主从数据库状态不一致其运作将会异常。
启动数据库使用 mysqld_multi 即可,不应采用 service 。 |
3 | 让 service 显示成未知状态 ? ,参考: service --status-all 为什么会出现问号。 |
sudo service mysqld_multi status
主从拷贝
[mysqld1] (1)
server-id = 1
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
binlog-format = ROW (2)
binlog_do_db = mybb (3)
log_bin = /var/log/mysql/mysql-bin.log (4)
expire_logs_days = 10 (5)
1 | [mysqld1] 的设置值;即为源文件案的 [mysqld],下列变量已事先在前文加入。 |
2 | binlog-format 采用 ROW。 |
3 | log_do_db 同步的 database,如果多个 database 那么写成多行。 binlog_do_db = db1 binlog_do_db = db2 |
4 | 本行缺省为前置注解 (# ),把本行的注解取消。 |
5 | [mysqld] 的原始值 (没有改变),自动删除10 天前 Binary Log (binlog) 文件。 |
磁盘策略参数说明
- innodb_flush_method=O_DIRECT,设置刷新磁盘策略
-
设置值为
fsync
(默认值)、O_DSYNC
、O_DIRECT
,最好的方式是去测试。测试环境显示 mysql 版本: mysql --version mysql Ver 15.1 Distrib 10.3.27-MariaDB 查找 innodb_buffer_pool_size : mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -N \ -e 'SELECT @@innodb_buffer_pool_size;' 134217728 (默认值 128M)
在没有修改 innodb_flush_method 默认值为 fsyncNAS 测试 drupal 运行 cron: time drupal cron:execute fsync 的结果: real 2m27.843s user 0m51.667s sys 0m8.643s
在 50-server.cnf 中的 [mysqld1] 区段中加入 innodb_flush_method = O_DIRECTNAS 测试 drupal 运行 cron: time drupal cron:execute O_DIRECT 的结果: real 2m23.766s user 0m51.200s sys 0m8.595s
上述是 NAS 内的 LXC 的测试结果。
桌面型虚拟器内 LXC 测试结果。桌面型测试 drupal 运行 cron: time drupal cron:execute fsync 的结果: real 1m20.441s user 0m6.535s sys 0m21.448s O_DIRECT 的结果 real 1m15.751s user 0m6.801s sys 0m20.653s
- innodb_flush_log_at_trx_commit = 1,设置 Commit 写入磁盘策略。
-
可将 MySQL 写入到磁盘中流程当做三个实体为 MySQL_logbuff (MySQL 日志缓冲) OS_buff (操作系统缓冲) Disk (磁盘)
- 设置值 0
-
MySQL_logbuff 每隔 1 秒 → OS_buff → Disk
- 设置值 1
-
MySQL_logbuff → OS_buff → Disk
- 设置值 2
-
MySQL_logbuff → OS_buff 每隔 1 秒 → Disk
- sync_binlog = 1
-
设置 MySQL 二进制日志 (Binary log)同步到磁盘的频率。
-
0 当事务提交之后,MySQL 不做磁盘同步让 OS 自行决定,性能最好。
-
1 当每进行 1 次事务提交之后,MySQL 将进行磁盘同步强制写入磁盘。
-
n 每进行 n 次事务提交之后,MySQL 将进行磁盘同步强制写入磁盘。
-
innodb_flush_log_at_trx_commit
、sync_binlog
依实际情况决定,如果有不断电或者 Slave 只作为备份,两者可设为 0。
主从状态同步
mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp<<EOF
create user 'replication'@'localhost' identified by 'replication';
grant replication slave on *.* to 'replication'@'localhost';
flush privileges;
EOF
mysqldump -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -B \
--master-data=1 mybb > repl-1.sql (1) (2)
1 | 如果出错 mysqldump: Error: Binlogging on server not active ,可能是没有取消 log_bin 注解。 |
2 | 使用选项 --master-data=1 以便备份的文件 (repl-1.sql) 包含 CHANGE MASTER 的语句。 |
master-data=1
会将 CHANGE MASTER 语句写入 Dump 文件中,在导入从属数据后不需要配置同步的文件及位置。
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000007', MASTER_LOG_POS=843487;
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp < repl-1.sql (1)
1 | 若已经激活「从属模式」,则会出现下列消息,并提示要停止从属模式
ERROR 1198 (HY000) at line 22: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first 停止「从属模式」
停止「从属模式」后再次导入。 |
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp \
-e 'start slave;'
手动同步「主从状态」
--master-data=2
选项将 mybb 转存:mysqldump -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -B \
--master-data=2 mybb > repl-2.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000007', MASTER_LOG_POS=843487; (1)
1 | 跟 master-data=1 的差别只在于一个是注解。 |
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp < repl-2.sql
mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -e \
'show master status;'
+------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000007 | 843487 | mybb,mybb | | (1) +------------------+----------+--------------+------------------+
1 | Slave 按回传值同步。 |
登录 Slave:
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp
在 mysql 内运行下列:
stop slave;
change master to
master_host='localhost',
master_user='replication',
master_password='replication',
master_log_file='mysql-bin.000007', (1)
master_log_pos=843487; (1)
start slave;
1 | 别照抄按 Master status 的结果修改。 |
mysql -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp \
-e 'show slave status \G'
Slave_IO_State: Waiting for master to send event
Master_Host: localhost
Master_User: replication
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007 (1)
Read_Master_Log_Pos: 843487 (1)
Relay_Log_File: ...
Relay_Log_Pos: ...
Relay_Master_Log_File: mysql-bin.000007 (1)
...
Exec_Master_Log_Pos: 843487 (1)
...
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
...
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
...
1 | 若需要可比对 Master status。 |
phpMyAdmin 设置 Slave Database
- config.inc.php 文件位置
-
- Linux
-
/usr/share/phpmyadmin/config.inc.php
- Windows
-
\\%host%\root\usr\share\phpmyadmin\config.inc.php
/**
* phpMyAdmin configuration storage settings.
*/
/**
* Master Server
*/
$cfg['Servers'][$i]['verbose'] = 'Master';
/**
* Slave server
*/
$i++;
$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['verbose'] = 'Slave';
$cfg['Servers'][$i]['host'] = '127.0.0.1';
$cfg['Servers'][$i]['port'] = '3307';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
/**
* phpMyAdmin configuration storage settings.
*/
升级 MariaDB 10.x 至 10.3
mysql --version
mysqldump --help -x, --lock-all-tables 锁定所有表格 -A, --all-databases 所有数据库
备份 (单例及多实例主要数据库): mysqldump -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -x -A > db1.sql 备份多实例从属数据库 (单例不用运行): mysqldump -uroot -p$mysqlpw --host=localhost --port=3307 --protocol=tcp -x -A > db2.sql
停止多实例数据库服务: sudo mysqld_multi stop 停止单例数据库服务: sudo systemctl stop mysql
sources.list
或备份,如果不小心加错,可用回复:cat /etc/apt/sources.list cp /etc/apt/sources.list ~/sources.list.bak
可从官方 MariaDB 的 Repository 安装指定的版本,在 Download MariaDB Server - MariaDB.org 选择 Linux 版本、MariaDB 版本和存储库 (repository) 镜像。
例如选择 18.04 LTS "bionic"、MariaDB 10.3: https://mariadb.org/download/?t=repo-config&d=18.04+LTS+"bionic"&v=10.3&r_m=ossplanet
# MariaDB 10.3 repository list - created 2023-02-02 12:47 UTC
# https://mariadb.org/download/
deb https://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.3/ubuntu bionic main
# deb-src https://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.3/ubuntu bionic main
MariaDB 10.3
加入存储库 (Repository)sudo apt install software-properties-common
sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
sudo add-apt-repository 'deb https://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.3/ubuntu bionic main' (1)
1 | Ubuntu 20.04 TLS,MariaDB 10.4 为 https://ftp.ubuntu-tw.org/mirror/mariadb/repo/10.4/ubuntu focal main 。 |
sudo apt update
sudo apt install mariadb-server -y
启动多实例数据库服务: sudo mysqld_multi start 显示多实例数据库服务状态: sudo mysqld_multi report Reporting MariaDB servers MariaDB server from group: mysqld2 is running MariaDB server from group: mysqld1 is running 启动单例数据库服务: sudo systemctl start mariadb
更新数据库 (单例及多实例主要数据库): sudo mysql_upgrade --port=3306 --protocol=tcp -uroot -p$mysqlpw 更新多实例从属数据库 (单例不用运行): sudo mysql_upgrade --port=3307 --protocol=tcp -uroot -p$mysqlpw
多实例从属数据库检查 Slave 同步状态是否正确,如果正确则不需要重新同步。