Learning Objectives
- 用 SHOW 系列指令查出伺服器上有哪些資料庫、表格、欄位與表格的建立方式
- 分辨 SHOW STATUS(伺服器的統計數字)與 SHOW VARIABLES(伺服器的設定值)
- 用 SHOW PROCESSLIST 查看目前的連線,必要時用 KILL 中斷
- 用 SHOW GRANTS、SHOW WARNINGS、SHOW ERRORS 查權限與上一個敘述的訊息
- 用 information_schema 以 SELECT 查詢表格、欄位與外鍵的資訊
- 在命令列使用 mysqlshow 與 mysqladmin 完成相同的管理工作
管理資料庫要知道哪些事
前幾課都在「使用」資料庫:建表格、新增資料、查詢。資料庫上線之後,管理者還要隨時掌握伺服器的情況:
| 想知道的事 | SQL 指令(在 mysql> 裡執行) |
命令列工具(在作業系統的終端機執行) |
|---|---|---|
| 有哪些資料庫、表格、欄位 | SHOW DATABASES、SHOW TABLES、SHOW COLUMNS |
mysqlshow |
| 伺服器的版本、執行多久、處理了多少查詢 | SELECT VERSION()、SHOW STATUS |
mysqladmin version、mysqladmin status |
| 伺服器的設定值 | SHOW VARIABLES |
mysqladmin variables |
| 誰連進來、正在做什麼 | SHOW PROCESSLIST、KILL |
mysqladmin processlist、mysqladmin kill |
| 某個帳號有什麼權限 | SHOW GRANTS |
(沒有對應工具) |
| 建立、刪除資料庫 | CREATE DATABASE、DROP DATABASE |
mysqladmin create、mysqladmin drop |
兩邊做得到的事大多相同。SQL 指令適合在 mysql> 裡邊查邊做;命令列工具適合寫進備份或監控的排程腳本,不必先進入 mysql>。
本課前半段在 SQL 直譯器裡練習 SHOW 指令與 information_schema,後半段用導覽介紹命令列工具。
直譯器裡的 employee 資料庫和前幾課相同。注意:直譯器沒有真的在運轉的伺服器,SHOW STATUS、SHOW TABLE STATUS、SHOW PROCESSLIST 的數字是模擬值,
只用來說明欄位的意思,不代表真實伺服器的數據。
查看資料庫、表格與欄位
| 指令 | 作用 |
|---|---|
SELECT VERSION(), USER(), DATABASE(); |
伺服器版本、目前登入的帳號、目前使用中的資料庫 |
SHOW DATABASES; |
這個帳號看得到的資料庫 |
USE employee; |
切換到某個資料庫 |
SHOW TABLES; |
目前資料庫裡的表格 |
SHOW COLUMNS FROM department; |
表格的欄位,和 DESCRIBE department; 相同 |
SHOW CREATE TABLE department; |
重新建立這個表格所需的完整 CREATE TABLE 敘述 |
SHOW TABLE STATUS; |
每個表格的儲存引擎、列數、資料大小等 |
SHOW ENGINES; |
伺服器支援的儲存引擎 |
SHOW DATABASES 只列出這個帳號有權限的資料庫;information_schema、performance_schema 是 MySQL 內建的系統資料庫,每個帳號都看得到。
mysql、sys 也是系統資料庫,只有管理者看得到。
原課程是 MySQL 4.1/5 的時代,有幾處寫法在 MySQL 8 已經不同:
SHOW TABLE TYPES已移除,改用SHOW ENGINES- 原講義
SHOW CREATE TABLE的結果是TYPE=InnoDB CHARSET=latin1、int(11)。MySQL 8 會顯示ENGINE=InnoDB、 預設字元集utf8mb4,而且從 8.0.19 起整數型別不再顯示寬度,只寫int
用 SHOW 認識 employee 資料庫
依序查出伺服器版本與目前的帳號、所有資料庫、目前資料庫的表格,再看 department 的欄位與建立敘述。SHOW CREATE TABLE 的結果可以直接複製去建立一個一模一樣的表格,第 14 課的 mysqldump 備份也是用同樣的方法產生 CREATE TABLE。
SHOW STATUS 與 SHOW VARIABLES 的差別
兩個指令的結果都是 Variable_name 和 Value 兩欄,很容易混淆:
SHOW VARIABLES |
SHOW STATUS |
|
|---|---|---|
| 內容 | 伺服器的設定值(系統變數) | 伺服器的統計數字(狀態變數) |
| 例子 | max_connections(最多可同時連線數)、datadir(資料檔放在哪裡)、secure_file_priv |
Uptime(已執行幾秒)、Threads_connected(目前連線數)、Com_select(執行過幾次 SELECT) |
| 會不會變 | 管理者修改設定才會變 | 伺服器每處理一個請求就可能變 |
| 怎麼修改 | 設定檔 /etc/mysql/mysql.conf.d/mysqld.cnf,或 SET GLOBAL |
不能修改,只能讀(FLUSH STATUS 可以把部分計數歸零) |
兩個指令都可以加 LIKE 篩選,% 代表任意字元:
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Com_%';
SELECT @@max_connections; -- 系統變數也可以用 @@ 讀取
SHOW STATUS 預設是 SESSION 範圍:計數只算目前這條連線;要看整個伺服器開機以來的總數,寫 SHOW GLOBAL STATUS。
Uptime 這類只有全域值的變數,兩種寫法結果相同。
SHOW TABLE STATUS 列出每個表格的引擎、列數(Rows)、資料與索引占用的位元組(Data_length、Index_length)、下一個自動編號(Auto_increment)。
InnoDB 的 Rows 是估計值,資料多的時候和 SELECT COUNT(*) 不一定相同;要精確的列數一定要 COUNT(*)。
統計數字會變,設定值不會
先看 Com_select 的值,執行兩個 SELECT 之後再看一次,計數增加了 2。接著讀兩個設定值與兩個表格的狀態。再提醒一次:這裡的計數、Data_length、Create_time 都是直譯器的模擬值;真實伺服器上 Com_select 一開始通常不是 0(例如 mysql 用戶端登入時自己就會送出一個 SELECT)。
想一想:SHOW 指令
想知道伺服器「最多可以同時有幾條連線」,應該執行哪個指令?
client 表格有 clientID、name、address、contactPerson、contactNumber 這些欄位。執行 SHOW COLUMNS FROM client; 會列出幾列?
目前使用的資料庫是 employee,執行 SHOW COLUMNS FROM nothing;(沒有這個表格)會出現什麼?
連線、權限與訊息
SHOW PROCESSLIST 列出目前連到伺服器的每一條連線(MySQL 稱為 thread):
| 欄位 | 意思 |
|---|---|
Id |
連線編號,KILL 要用它 |
User、Host |
哪個帳號、從哪裡連進來 |
db |
這條連線目前使用的資料庫 |
Command |
Query 正在執行敘述、Sleep 連著但閒置、Daemon 是伺服器內部的背景工作 |
Time |
目前狀態已經持續幾秒 |
State、Info |
正在做什麼、正在執行的敘述 |
有人執行了跑不完的查詢,拖慢整台伺服器時,管理者可以中斷它:
KILL QUERY 18; -- 只停止連線 18 正在執行的敘述,連線保留
KILL 18; -- 直接中斷連線 18(等於 KILL CONNECTION 18)
一般帳號只看得到、也只能中斷自己的連線;要看到所有人的連線需要 PROCESS 權限,要中斷別人的連線需要 CONNECTION_ADMIN(或舊的 SUPER)權限。
Id 不存在時會出現 ERROR 1094 (HY000): Unknown thread id: 18。
SHOW GRANTS 列出帳號的權限:SHOW GRANTS; 是自己,SHOW GRANTS FOR 'fred'@'localhost'; 是別人(需要讀取 mysql 系統資料庫的權限)。
SHOW PRIVILEGES 列出這個版本的 MySQL 有哪些權限可以授予,以及各自的適用範圍。以下節錄自真實的 MySQL 8.0.44:
+-------------------------+---------------------------------------+-------------------------------------------------------+
| Privilege | Context | Comment |
+-------------------------+---------------------------------------+-------------------------------------------------------+
| Alter | Tables | To alter the table |
| Create | Databases,Tables,Indexes | To create new databases and tables |
| Drop | Databases,Tables | To drop databases, tables, and views |
| File | File access on server | To read and write files on the server |
| Grant option | Databases,Tables,Functions,Procedures | To give to other users those privileges you possess |
| Process | Server Admin | To view the plain text of currently executing queries |
| Select | Tables | To retrieve rows from table |
| … | | |
| CONNECTION_ADMIN | Server Admin | |
| … | | |
+-------------------------+---------------------------------------+-------------------------------------------------------+
Context 說明這個權限能授予在哪一層:Server Admin 只能是全域權限(ON *.*);Tables 可以授予到單一表格。
大寫的 CONNECTION_ADMIN 這類是 MySQL 8 新增的「動態權限」,用來把原本 SUPER 一個大權限拆細。
SHOW WARNINGS 與 SHOW ERRORS 顯示上一個敘述產生的訊息。看到 1 row in set, 1 warning 卻不知道警告是什麼時,馬上執行 SHOW WARNINGS;。
SHOW ERRORS 只列出等級是 Error 的訊息。執行下一個會產生訊息的敘述之後,舊的訊息就被清掉了。
權限、連線清單與警告
建立帳號 fred 並授予 employee 資料庫的 SELECT、INSERT 權限,用 SHOW GRANTS 確認;SHOW PROCESSLIST 看目前的連線(模擬)。接著 SELECT 1/0 產生一個警告、重複的主鍵產生一個錯誤,分別用 SHOW WARNINGS 與 SHOW ERRORS 查看。
用 SELECT 查 information_schema
SHOW 指令的結果只能看,不能再篩選、排序或和別的資料合併。
information_schema 是 MySQL 內建的唯讀資料庫,把「資料庫裡有什麼」整理成一般的表格,所以可以用 SELECT 查詢,WHERE、GROUP BY、JOIN 都能用:
| 表格 | 內容 | 相當於 |
|---|---|---|
SCHEMATA |
資料庫 | SHOW DATABASES |
TABLES |
表格、引擎、估計列數 | SHOW TABLES、SHOW TABLE STATUS |
COLUMNS |
每個欄位的型別、能否 NULL、是否為索引 | SHOW COLUMNS |
STATISTICS |
索引 | SHOW INDEX |
KEY_COLUMN_USAGE |
主鍵、唯一鍵、外鍵用到的欄位;外鍵還有指向哪個表格的哪個欄位 | 沒有對應的 SHOW |
PROCESSLIST |
目前的連線 | SHOW PROCESSLIST |
查外鍵是最常見的用途:刪除一個表格之前,先查有哪些表格的外鍵指向它,
SELECT TABLE_NAME, COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_SCHEMA = 'employee'
AND REFERENCED_TABLE_NAME = 'employee';
information_schema 的表格名稱與欄位名稱習慣寫成大寫。查詢時一定要用 TABLE_SCHEMA 指定資料庫,否則會把其他資料庫的同名表格也查出來。
(直譯器只模擬了常用的幾個 information_schema 表格,欄位也比真實的少。)
從 information_schema 找出外鍵
三個查詢分別從 TABLES、COLUMNS、KEY_COLUMN_USAGE 取出資訊。第三個查詢列出 employee 資料庫所有的外鍵:每一列代表「這個表格的這個欄位,指向那個表格的那個欄位」。
想一想:連線與 information_schema
下面的查詢傳回什麼?
SELECT REFERENCED_TABLE_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'employee'
AND TABLE_NAME = 'employeeSkills'
AND REFERENCED_TABLE_NAME IS NOT NULL;
帳號 fred 只有 employee 資料庫的 SELECT 權限,沒有 PROCESS 權限。他執行 SHOW PROCESSLIST; 會看到什麼?
SELECT 1/0; 傳回什麼值?
導覽:mysqlshow 與 mysqladmin
以下在 Ubuntu 24.04 安裝的 MySQL 8.0 上操作。Ubuntu 上 MySQL 的 root 預設用 auth_socket 驗證:作業系統的管理者用 sudo 執行就能以 root 登入,不必輸入資料庫密碼。用其他資料庫帳號時改成 mysqladmin -u 帳號 -p 指令,-p 後面不寫密碼,執行時再輸入,密碼才不會留在指令紀錄裡。輸出裡的時間、連線數、查詢數都是示意值;版本號後面的 -0ubuntu0.24.04.1 是 Ubuntu 套件的編號,會隨套件更新而不同。
-
1
mysqlshow:列出資料庫、表格與欄位
mysqlshow不帶參數列出所有資料庫(同SHOW DATABASES);加上資料庫名稱列出表格(同SHOW TABLES);再加上表格名稱列出欄位,內容和SHOW FULL COLUMNS相同。加-v會多一欄每個表格的欄位數。mysqlshow --help可以看到所有選項。 -
2
mysqladmin version、status、ping:伺服器還好嗎
version顯示版本、連線方式與已執行時間;最後一行和status的內容相同:Threads是目前連線數、Questions是開機以來處理的敘述數、Slow queries是超過long_query_time(預設 10 秒)的慢查詢數、Queries per second avg是平均每秒處理幾個敘述。ping只檢查伺服器有沒有回應,常寫在監控腳本裡:伺服器正常時印出mysqld is alive,結束代碼是 0。 -
3
mysqladmin processlist 與 kill:找出並中斷有問題的連線
processlist的內容和SHOW PROCESSLIST相同(NULL 顯示成空白,數字靠左)。假設帳號 fred 的連線 18 執行了一個 10 分鐘的SELECT SLEEP(600)(用來模擬跑不完的查詢),已經過了 312 秒。mysqladmin kill 18中斷這條連線,成功時不會印出任何訊息;要中斷多條連線,用逗號分隔:kill 18,19。Id 不存在時會印出mysqladmin: kill failed on 18; error: 'Unknown thread id: 18'。 -
4
mysqladmin extended-status 與 variables
extended-status等於SHOW GLOBAL STATUS,variables等於SHOW GLOBAL VARIABLES,兩者都有數百列,通常接grep只看需要的幾個。grep -w只比對完整的字,max_connections才不會連mysqlx_max_connections也一起找出來。真實的輸出表格很寬(有些變數的值很長),下面把欄寬縮短了。 -
5
mysqladmin create 與 drop
create建立資料庫(同CREATE DATABASE),成功時沒有輸出。drop刪除資料庫,裡面的表格與資料全部消失,所以會先要求確認,輸入y才執行;加上-f(force)就不再詢問,寫在腳本裡時要特別小心。
動手寫:每個表格有幾個欄位
請查詢 information_schema.COLUMNS,列出 employee 資料庫每個表格的名稱(TABLE_NAME)與欄位數(欄位名稱取為 n_columns),依欄位數由多到少排序,欄位數相同時依表格名稱排序。
重點整理
| 想知道的事 | SQL | 命令列 |
|---|---|---|
| 資料庫、表格、欄位 | SHOW DATABASES、SHOW TABLES、SHOW COLUMNS、SHOW CREATE TABLE |
mysqlshow |
| 表格的引擎、列數、大小 | SHOW TABLE STATUS、information_schema.TABLES |
mysqlshow -v |
| 統計數字(會變) | SHOW [GLOBAL] STATUS |
mysqladmin status、extended-status |
| 設定值 | SHOW VARIABLES、SELECT @@變數 |
mysqladmin variables |
| 目前的連線 | SHOW PROCESSLIST、KILL [QUERY] id |
mysqladmin processlist、kill |
| 權限 | SHOW GRANTS [FOR 帳號]、SHOW PRIVILEGES |
|
| 上一個敘述的訊息 | SHOW WARNINGS、SHOW ERRORS |
|
| 外鍵與其他中繼資料 | information_schema.KEY_COLUMN_USAGE 等 |
|
| 建立、刪除資料庫 | CREATE DATABASE、DROP DATABASE |
mysqladmin create、drop |
- STATUS 是統計、VARIABLES 是設定;InnoDB 的
Rows/TABLE_ROWS是估計值 - 沒有 PROCESS 權限只看得到自己的連線
information_schema可以用 SELECT 查詢,要用TABLE_SCHEMA指定資料庫- MySQL 8:
SHOW TABLE TYPES改為SHOW ENGINES;TYPE=改為ENGINE=;Ubuntu 的 root 用sudo登入
下一課學習備份與復原:mysqldump、二進位日誌,以及檢查與修復表格。