建立多實例的 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 同步狀態是否正確,如果正確則不需要重新同步。