安裝 MySQL 只要一個指令。真正的工作在後面:給應用程式的使用者、一種不把 3306 連接埠暴露在網際網路上就能從自己電腦存取資料庫的方法、適合小伺服器的記憶體設定,以及不必你操心就會自動執行的備份。本指南在 Ubuntu 24.04 上把這四件事都講清楚。每一步都在我們的 Ubuntu 24.04 映像上執行過,下面的數字都來自那台伺服器。
請以具 sudo 權限的使用者執行指令。Ubuntu 設定指南會建立一位。
1. 安裝
sudo apt update
sudo apt install -y mysql-server
mysql --version
在我們的伺服器上,安裝花了 51 秒,裝上的是 MySQL 8.0.46。它會立即啟動,每次開機自動啟動,並且只在伺服器本機上監聽:一般連線是 127.0.0.1:3306,MySQL 較新的 X 協定是 127.0.0.1:33060。此時外部還什麼都連不到。
2. 建立資料庫與使用者
在 Ubuntu 上,MySQL 的 root 帳號使用 socket 驗證,所以 sudo mysql 不必密碼就能登入。為你的應用程式建立資料庫與使用者:
sudo mysql
CREATE DATABASE app CHARACTER SET utf8mb4;
CREATE USER 'app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'localhost';
EXIT;
用應用程式的連線方式測試:
mysql -u app -p app -e "SELECT CURRENT_USER();"
應該輸出 app@localhost。密碼錯誤會得到 ERROR 1045 (28000): Access denied for user 'app'@'localhost'。這位使用者在 app 裡可以做任何事,在它之外什麼都不能做。
3. 從你的電腦連線:SSH 通道
要在自己的電腦上使用 DBeaver、MySQL Workbench 或 mysql 命令列這類桌面用戶端,也不要開放連接埠。透過 SSH 轉送一個:
ssh -L 3307:127.0.0.1:3306 deploy@YOUR.SERVER.IP
NAT 方案要加上 -p 和控制台中的專屬 SSH 連接埠。保持這個視窗開著,把用戶端指向主機 127.0.0.1、連接埠 3307、使用者 app。本機端用 3307,是為了不和你電腦上可能在執行的 MySQL 衝突。在我們的測試中,伺服器透過通道立刻回應,而直接連到它位址上的 3306 則被拒絕。
4. 讓另一台伺服器直接存取
有時應用程式執行在第二台伺服器上,必須直接連到資料庫。這時資料庫需要具獨立 IPv4 的方案,因為 NAT 方案只轉送你的 SSH 連接埠。共三處修改,都只限於應用程式伺服器的位址(這裡是 203.0.113.20):
sudo sed -i 's/^bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
sudo ufw allow from 203.0.113.20 to any port 3306 proto tcp
CREATE USER 'app'@'203.0.113.20' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON app.* TO 'app'@'203.0.113.20';
如果 ufw 還沒啟用,先允許 SSH(sudo ufw allow OpenSSH),再執行 sudo ufw enable。詳細內容請見 ufw 指南。
我們分別檢查了兩道鎖。有防火牆規則但沒有對應的 MySQL 使用者時,伺服器以 error 1130: Host '…' is not allowed to connect to this MySQL server 拒絕。加上使用者後,連線成功。移除防火牆規則後,連線直接逾時。網際網路上的其他任何位址都會遇到同樣的逾時。
5. 更省記憶體
閒置且沒有自己的資料時,MySQL 8.0 在我們的伺服器上用了 383 MB。其中大部分是 Performance Schema,一個預先占用記憶體的診斷功能。在小型 VPS 上把它關掉,並自行設定主要快取的大小:
sudo tee /etc/mysql/mysql.conf.d/zz-small-vps.cnf >/dev/null <<'EOF'
[mysqld]
performance_schema = OFF
innodb_buffer_pool_size = 256M
max_connections = 50
EOF
sudo systemctl restart mysql
ps -o rss= -C mysqld
重新啟動後它只用了 165 MB。buffer pool 用來快取資料與索引,對同時執行應用程式的 2 GB 伺服器來說,256 MB 很合適。如果資料庫是伺服器上的主要負載、而且已經比快取還大,就把它調大。max_connections = 50 對一個使用連線集區的應用程式來說綽綽有餘。你會失去 performance_schema 的統計資料;如果哪天需要深入排查慢查詢,再把它打開。
6. 每晚備份
mysqldump --single-transaction 能在不鎖住應用程式的情況下,取得 InnoDB 資料表的一致性副本。把它放進一個小指令碼:
sudo tee /usr/local/bin/mysql-backup >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
mkdir -p /var/backups/mysql
mysqldump --single-transaction --routines --triggers app | gzip > /var/backups/mysql/app-$(date +%F).sql.gz
find /var/backups/mysql -name 'app-*.sql.gz' -mtime +14 -delete
EOF
sudo chmod 755 /usr/local/bin/mysql-backup
echo '0 3 * * * root /usr/local/bin/mysql-backup' | sudo tee /etc/cron.d/mysql-backup
sudo /usr/local/bin/mysql-backup && sudo ls -l /var/backups/mysql
每一行都有它的道理:
umask 077讓傾印檔只有 root 能讀(-rw-------),因為裡面是你的全部資料。pipefail讓mysqldump失敗時整個指令碼也失敗。沒有它,gzip會寫出一個空空的小壓縮檔並回報成功。我們故意弄壞指令,指令碼果然以代碼 2 結束。find … -mtime +14 -delete保留兩週的副本。- 指令碼以 root 執行,所以
mysqldump透過 socket 登入,不必把密碼寫進任何檔案。
從沒還原過的備份還不算數。把它還原到一個暫時的資料庫裡看看資料:
sudo mysql -e "CREATE DATABASE app_restore"
gunzip -c /var/backups/mysql/app-2026-10-25.sql.gz | sudo mysql app_restore
sudo mysql -e "SHOW TABLES FROM app_restore"
sudo mysql -e "DROP DATABASE app_restore"
在我們的測試中,還原出來的資料表和原表的資料列完全相同。同一顆磁碟上的副本在你失去伺服器時幫不上忙,所以不時用 scp 或 restic 把它們搬到另一台機器上。Managed Backups 還會另外提供整台伺服器的每日還原點。
選哪個方案
Micro(2 vCPU、2 GB、25 GB,$5/月)可以承載依上述調整的 MySQL 加一個網頁應用程式。如果資料庫本身超過幾個 GB,Small(4 GB、35 GB,$8/月)能讓你給 buffer pool 1 GB 或更多。兩者都是 NAT 方案,第 3 步的 SSH 通道照樣可用。第 4 步需要獨立 IPv4:Micro-IP 為 $10/月。
比較喜歡 PostgreSQL?PostgreSQL 指南依照相同的思路撰寫。所有方案都在 VPS 中,付款方式為 Base、Ethereum 或 Polygon 網路上的 USDT、USDC 或 ETH。
評論
目前還沒有評論。歡迎成為第一位。