本篇摘錄自黑馬程序員的B站教學視頻,由本人學習視頻內容後總結並提取摘要製作而成的簡要筆記。
黑馬程序員黑馬程序員 MySQL數據庫入門到精通,從mysql安裝到mysql高級、mysql優化全囊括
本筆記只記錄到進階篇(大部分),剩下的進階篇以及運維篇由於本人職業生涯沒有用武之地,所以沒有進行學習。
在此非常感謝兩位熱愛學習的小夥伴的鼎力相助,幫助我們完成了所有的章節內容,使得本篇超長筆記得以完結。至此,整個MySQL筆記從入門到高級的所有內容都已編寫完畢。
特別感謝:
- wlh (wen-lh) - Gitee.com
- B站同學:@守心-人
基礎篇
通用語法及分類
- DDL: 數據定義語言,用來定義數據庫對象(數據庫、表、字段)
- DML: 數據操作語言,用來對數據庫表中的數據進行增刪改
- DQL: 數據查詢語言,用來查詢數據庫中表的記錄
- DCL: 數據控制語言,用來創建數據庫用户、控制數據庫的控制權限
DDL(數據定義語言)
數據定義語言
數據庫操作
查詢所有數據庫:
SHOW DATABASES;
查詢當前數據庫:
SELECT DATABASE();
創建數據庫:
CREATE DATABASE [ IF NOT EXISTS ] 數據庫名 [ DEFAULT CHARSET 字符集] [COLLATE 排序規則 ];
刪除數據庫:
DROP DATABASE [ IF EXISTS ] 數據庫名;
使用數據庫:
USE 數據庫名;
注意事項
- UTF8字符集長度為3字節,有些符號佔4字節,所以推薦用utf8mb4字符集
表操作
查詢當前數據庫所有表:
SHOW TABLES;
查詢表結構:
DESC 表名;
查詢指定表的建表語句:
SHOW CREATE TABLE 表名;
創建表:
CREATE TABLE 表名(
|
最後一個字段後面沒有逗號
添加字段:
ALTER TABLE 表名 ADD 字段名 類型(長度) [COMMENT 註釋] [約束];
例:ALTER TABLE emp ADD nickname varchar(20) COMMENT '暱稱';
修改數據類型:
ALTER TABLE 表名 MODIFY 字段名 新數據類型(長度);
修改字段名和字段類型:
ALTER TABLE 表名 CHANGE 舊字段名 新字段名 類型(長度) [COMMENT 註釋] [約束];
例:將emp表的nickname字段修改為username,類型為varchar(30)
ALTER TABLE emp CHANGE nickname username varchar(30) COMMENT '暱稱';
刪除字段:
ALTER TABLE 表名 DROP 字段名;
修改表名:
ALTER TABLE 表名 RENAME TO 新表名
刪除表:
DROP TABLE [IF EXISTS] 表名;
刪除表,並重新創建該表:
TRUNCATE TABLE 表名;
DML(數據操作語言)
添加數據
指定字段:
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);
全部字段:
INSERT INTO 表名 VALUES (值1, 值2, ...);
批量添加數據:
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...);
INSERT INTO 表名 VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...);
注意事項
- 字符串和日期類型數據應該包含在引號中
- 插入的數據大小應該在字段的規定範圍內
更新和刪除數據
修改數據:
UPDATE 表名 SET 字段名1 = 值1, 字段名2 = 值2, ... [ WHERE 條件 ];
例:
UPDATE emp SET name = 'Jack' WHERE id = 1;
刪除數據:
DELETE FROM 表名 [ WHERE 條件 ];
DQL(數據查詢語言)
語法:
SELECT
|
基礎查詢
查詢多個字段:
SELECT 字段1, 字段2, 字段3, ... FROM 表名;
SELECT * FROM 表名;
設置別名:
SELECT 字段1 [ AS 別名1 ], 字段2 [ AS 別名2 ], 字段3 [ AS 別名3 ], ... FROM 表名;
SELECT 字段1 [ 別名1 ], 字段2 [ 別名2 ], 字段3 [ 別名3 ], ... FROM 表名;
去除重複記錄:
SELECT DISTINCT 字段列表 FROM 表名;
轉義:
SELECT * FROM 表名 WHERE name LIKE '/_張三' ESCAPE '/'
/ 之後的_不作為通配符
條件查詢
語法:
SELECT 字段列表 FROM 表名 WHERE 條件列表;
條件:
| 比較運算符 | 功能 |
|---|---|
| > | 大於 |
| >= | 大於等於 |
| < | 小於 |
| <= | 小於等於 |
| = | 等於 |
| <> 或 != | 不等於 |
| BETWEEN … AND … | 在某個範圍內(含最小、最大值) |
| IN(…) | 在in之後的列表中的值,多選一 |
| LIKE 佔位符 | 模糊匹配(_匹配單個字符,%匹配任意個字符) |
| IS NULL | 是NULL |
| 邏輯運算符 | 功能 |
|---|---|
| AND 或 && | 並且(多個條件同時成立) |
| OR 或 || | 或者(多個條件任意一個成立) |
| NOT 或 ! | 非,不是 |
例子:
-- 年齡等於30
|
聚合查詢(聚合函數)
常見聚合函數:
| 函數 | 功能 |
|---|---|
| count | 統計數量 |
| max | 最大值 |
| min | 最小值 |
| avg | 平均值 |
| sum | 求和 |
語法:
SELECT 聚合函數(字段列表) FROM 表名;
例:
SELECT count(id) from employee where workaddress = "廣東省";
分組查詢
語法:
SELECT 字段列表 FROM 表名 [ WHERE 條件 ] GROUP BY 分組字段名 [ HAVING 分組後的過濾條件 ];
where 和 having 的區別:
- 執行時機不同:where是分組之前進行過濾,不滿足where條件不參與分組;having是分組後對結果進行過濾。
- 判斷條件不同:where不能對聚合函數進行判斷,而having可以。
例子:
-- 根據性別分組,統計男性和女性數量(只顯示分組數量,不顯示哪個是男哪個是女)
|
注意事項
- 執行順序:where > 聚合函數 > having
- 分組之後,查詢的字段一般為聚合函數和分組字段,查詢其他字段無任何意義
排序查詢
語法:
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;
排序方式:
- ASC: 升序(默認)
- DESC: 降序
例子:
-- 根據年齡升序排序
|
注意事項
如果是多字段排序,當第一個字段值相同時,才會根據第二個字段進行排序
分頁查詢
語法:
SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查詢記錄數;
例子:
-- 查詢第一頁數據,展示10條
|
注意事項
- 起始索引從0開始,起始索引 = (查詢頁碼 - 1) * 每頁顯示記錄數
- 分頁查詢是數據庫的方言,不同數據庫有不同實現,MySQL是LIMIT
- 如果查詢的是第一頁數據,起始索引可以省略,直接簡寫 LIMIT 10
DQL執行順序
FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT
DCL
管理用户
查詢用户:
USE mysql;
|
創建用户:
CREATE USER '用户名'@'主機名' IDENTIFIED BY '密碼';
修改用户密碼:
ALTER USER '用户名'@'主機名' IDENTIFIED WITH mysql_native_password BY '新密碼';
刪除用户:
DROP USER '用户名'@'主機名';
例子:
-- 創建用户test,只能在當前主機localhost訪問
|
注意事項
- 主機名可以使用 % 通配
權限控制
常用權限:
| 權限 | 説明 |
|---|---|
| ALL, ALL PRIVILEGES | 所有權限 |
| SELECT | 查詢數據 |
| INSERT | 插入數據 |
| UPDATE | 修改數據 |
| DELETE | 刪除數據 |
| ALTER | 修改表 |
| DROP | 刪除數據庫/表/視圖 |
| CREATE | 創建數據庫/表 |
更多權限請看權限一覽表
查詢權限:
SHOW GRANTS FOR '用户名'@'主機名';
授予權限:
GRANT 權限列表 ON 數據庫名.表名 TO '用户名'@'主機名';
撤銷權限:
REVOKE 權限列表 ON 數據庫名.表名 FROM '用户名'@'主機名';
注意事項
- 多個權限用逗號分隔
- 授權時,數據庫名和表名可以用 * 進行通配,代表所有
函數
- 字符串函數
- 數值函數
- 日期函數
- 流程函數
字符串函數
常用函數:
| 函數 | 功能 |
|---|---|
| CONCAT(s1, s2, …, sn) | 字符串拼接,將s1, s2, …, sn拼接成一個字符串 |
| LOWER(str) | 將字符串全部轉為小寫 |
| UPPER(str) | 將字符串全部轉為大寫 |
| LPAD(str, n, pad) | 左填充,用字符串pad對str的左邊進行填充,達到n個字符串長度 |
| RPAD(str, n, pad) | 右填充,用字符串pad對str的右邊進行填充,達到n個字符串長度 |
| TRIM(str) | 去掉字符串頭部和尾部的空格 |
| SUBSTRING(str, start, len) | 返回從字符串str從start位置起的len個長度的字符串 |
| REPLACE(column, source, replace) | 替換字符串 |
使用示例:
-- 拼接
|
數值函數
常見函數:
| 函數 | 功能 |
|---|---|
| CEIL(x) | 向上取整 |
| FLOOR(x) | 向下取整 |
| MOD(x, y) | 返回x/y的模 |
| RAND() | 返回0~1內的隨機數 |
| ROUND(x, y) | 求參數x的四捨五入值,保留y位小數 |
日期函數
常用函數:
| 函數 | 功能 |
|---|---|
| CURDATE() | 返回當前日期 |
| CURTIME() | 返回當前時間 |
| NOW() | 返回當前日期和時間 |
| YEAR(date) | 獲取指定date的年份 |
| MONTH(date) | 獲取指定date的月份 |
| DAY(date) | 獲取指定date的日期 |
| DATE_ADD(date, INTERVAL expr type) | 返回一個日期/時間值加上一個時間間隔expr後的時間值 |
| DATEDIFF(date1, date2) | 返回起始時間date1和結束時間date2之間的天數 |
例子:
-- DATE_ADD
|
流程函數
常用函數:
| 函數 | 功能 |
|---|---|
| IF(value, t, f) | 如果value為true,則返回t,否則返回f |
| IFNULL(value1, value2) | 如果value1不為空,返回value1,否則返回value2 |
| CASE WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果val1為true,返回res1,… 否則返回default默認值 |
| CASE [ expr ] WHEN [ val1 ] THEN [ res1 ] … ELSE [ default ] END | 如果expr的值等於val1,返回res1,… 否則返回default默認值 |
例子:
select
|
約束
分類:
| 約束 | 描述 | 關鍵字 |
|---|---|---|
| 非空約束 | 限制該字段的數據不能為null | NOT NULL |
| 唯一約束 | 保證該字段的所有數據都是唯一、不重複的 | UNIQUE |
| 主鍵約束 | 主鍵是一行數據的唯一標識,要求非空且唯一 | PRIMARY KEY |
| 默認約束 | 保存數據時,如果未指定該字段的值,則採用默認值 | DEFAULT |
| 檢查約束(8.0.1版本後) | 保證字段值滿足某一個條件 | CHECK |
| 外鍵約束 | 用來讓兩張圖的數據之間建立連接,保證數據的一致性和完整性 | FOREIGN KEY |
約束是作用於表中字段上的,可以再創建表/修改表的時候添加約束。
常用約束
| 約束條件 | 關鍵字 |
|---|---|
| 主鍵 | PRIMARY KEY |
| 自動增長 | AUTO_INCREMENT |
| 不為空 | NOT NULL |
| 唯一 | UNIQUE |
| 邏輯條件 | CHECK |
| 默認值 | DEFAULT |
例子:
create table user(
|
外鍵約束
添加外鍵:
CREATE TABLE 表名(
|
刪除外鍵:
ALTER TABLE 表名 DROP FOREIGN KEY 外鍵名;
刪除/更新行為
| 行為 | 説明 |
|---|---|
| NO ACTION | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則不允許刪除/更新(與RESTRICT一致) |
| RESTRICT | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則不允許刪除/更新(與NO ACTION一致) |
| CASCADE | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則也刪除/更新外鍵在子表中的記錄 |
| SET NULL | 當在父表中刪除/更新對應記錄時,首先檢查該記錄是否有對應外鍵,如果有則設置子表中該外鍵值為null(要求該外鍵允許為null) |
| SET DEFAULT | 父表有變更時,子表將外鍵設為一個默認值(Innodb不支持) |
更改刪除/更新行為:
ALTER TABLE 表名 ADD CONSTRAINT 外鍵名稱 FOREIGN KEY (外鍵字段) REFERENCES 主表名(主表字段名) ON UPDATE 行為 ON DELETE 行為;
多表查詢
多表關係
- 一對多(多對一)
- 多對多
- 一對一
一對多
案例:部門與員工
關係:一個部門對應多個員工,一個員工對應一個部門
實現:在多的一方建立外鍵,指向一的一方的主鍵
多對多
案例:學生與課程
關係:一個學生可以選多門課程,一門課程也可以供多個學生選修
實現:建立第三張中間表,中間表至少包含兩個外鍵,分別關聯兩方主鍵
一對一
案例:用户與用户詳情
關係:一對一關係,多用於單表拆分,將一張表的基礎字段放在一張表中,其他詳情字段放在另一張表中,以提升操作效率
實現:在任意一方加入外鍵,關聯另外一方的主鍵,並且設置外鍵為唯一的(UNIQUE)
查詢
合併查詢(笛卡爾積,會展示所有組合結果):
select * from employee, dept;
笛卡爾積:兩個集合A集合和B集合的所有組合情況(在多表查詢時,需要消除無效的笛卡爾積)
消除無效笛卡爾積:
select * from employee, dept where employee.dept = dept.id;
內連接查詢
內連接查詢的是兩張表交集的部分
隱式內連接:
SELECT 字段列表 FROM 表1, 表2 WHERE 條件 ...;
顯式內連接:
SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 連接條件 ...;
顯式性能比隱式高
例子:
-- 查詢員工姓名,及關聯的部門的名稱
|
外連接查詢
左外連接:
查詢左表所有數據,以及兩張表交集部分數據
SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 條件 ...;
相當於查詢表1的所有數據,包含表1和表2交集部分數據
右外連接:
查詢右表所有數據,以及兩張表交集部分數據
SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 條件 ...;
例子:
-- 左
|
左連接可以查詢到沒有dept的employee,右連接可以查詢到沒有employee的dept
自連接查詢
當前表與自身的連接查詢,自連接必須使用表別名
語法:
SELECT 字段列表 FROM 表A 別名A JOIN 表A 別名B ON 條件 ...;
自連接查詢,可以是內連接查詢,也可以是外連接查詢
例子:
-- 查詢員工及其所屬領導的名字
|
聯合查詢 union, union all
把多次查詢的結果合併,形成一個新的查詢集
語法:
SELECT 字段列表 FROM 表A ...
|
注意事項
- UNION ALL 會有重複結果,UNION 不會
- 聯合查詢比使用or效率高,不會使索引失效
子查詢
SQL語句中嵌套SELECT語句,稱謂嵌套查詢,又稱子查詢。
SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2);
子查詢外部的語句可以是 INSERT / UPDATE / DELETE / SELECT 的任何一個
根據子查詢結果可以分為:
- 標量子查詢(子查詢結果為單個值)
- 列子查詢(子查詢結果為一列)
- 行子查詢(子查詢結果為一行)
- 表子查詢(子查詢結果為多行多列)
根據子查詢位置可分為:
- WHERE 之後
- FROM 之後
- SELECT 之後
標量子查詢
子查詢返回的結果是單個值(數字、字符串、日期等)。
常用操作符:- < > > >= < <=
例子:
-- 查詢銷售部所有員工
|
列子查詢
返回的結果是一列(可以是多行)。
常用操作符:
| 操作符 | 描述 |
|---|---|
| IN | 在指定的集合範圍內,多選一 |
| NOT IN | 不在指定的集合範圍內 |
| ANY | 子查詢返回列表中,有任意一個滿足即可 |
| SOME | 與ANY等同,使用SOME的地方都可以使用ANY |
| ALL | 子查詢返回列表的所有值都必須滿足 |
例子:
-- 查詢銷售部和市場部的所有員工信息
|
行子查詢
返回的結果是一行(可以是多列)。
常用操作符:=, <, >, IN, NOT IN
例子:
-- 查詢與xxx的薪資及直屬領導相同的員工信息
|
表子查詢
返回的結果是多行多列
常用操作符:IN
例子:
-- 查詢與xxx1,xxx2的職位和薪資相同的員工
|
事務
事務是一組操作的集合,事務會把所有操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要麼同時成功,要麼同時失敗。
基本操作:
-- 1. 查詢張三賬户餘額
|
操作方式二:
開啓事務:
START TRANSACTION 或 BEGIN TRANSACTION;
提交事務:
COMMIT;
回滾事務:
ROLLBACK;
操作實例:
start transaction;
|
四大特性ACID
- 原子性(Atomicity):事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗
- 一致性(Consistency):事務完成時,必須使所有數據都保持一致狀態
- 隔離性(Isolation):數據庫系統提供的隔離機制,保證事務在不受外部併發操作影響的獨立環境下運行
- 持久性(Durability):事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的
併發事務
| 問題 | 描述 |
|---|---|
| 髒讀 | 一個事務讀到另一個事務還沒提交的數據 |
| 不可重複讀 | 一個事務先後讀取同一條記錄,但兩次讀取的數據不同 |
| 幻讀 | 一個事務按照條件查詢數據時,沒有對應的數據行,但是再插入數據時,又發現這行數據已經存在 |
這三個問題的詳細演示:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=55cd
併發事務隔離級別:
| 隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
|---|---|---|---|
| Read uncommitted | √ | √ | √ |
| Read committed | × | √ | √ |
| Repeatable Read(默認) | × | × | √ |
| Serializable | × | × | × |
- √表示在當前隔離級別下該問題會出現
- Serializable 性能最低;Read uncommitted 性能最高,數據安全性最差
查看事務隔離級別:
SELECT @@TRANSACTION_ISOLATION;
設置事務隔離級別:
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
SESSION 是會話級別,表示只針對當前會話有效,GLOBAL 表示對所有會話有效
進階篇
存儲引擎
MySQL體系結構:

存儲引擎就是存儲數據、建立索引、更新/查詢數據等技術的實現方式。存儲引擎是基於表而不是基於庫的,所以存儲引擎也可以被稱為表引擎。
默認存儲引擎是InnoDB。
相關操作:
-- 查詢建表語句
|
InnoDB
InnoDB 是一種兼顧高可靠性和高性能的通用存儲引擎,在 MySQL 5.5 之後,InnoDB 是默認的 MySQL 引擎
特點:
- DML 操作遵循 ACID 模型,支持事務
- 行級鎖,提高併發訪問性能
- 支持外鍵約束,保證數據的完整性和正確性
文件:
- xxx.ibd: xxx代表表名,InnoDB 引擎的每張表都會對應這樣一個表空間文件,存儲該表的表結構(frm、sdi)、數據和索引。
參數:innodb_file_per_table,決定多張表共享一個表空間還是每張表對應一個表空間
知識點:
查看 Mysql 變量:
show variables like 'innodb_file_per_table';
從idb文件提取表結構數據:
(在cmd運行)
ibd2sdi xxx.ibd
InnoDB 邏輯存儲結構:

MyISAM
MyISAM 是 MySQL 早期的默認存儲引擎。
特點:
- 不支持事務,不支持外鍵
- 支持表鎖,不支持行鎖
- 訪問速度快
文件:
- xxx.sdi: 存儲表結構信息
- xxx.MYD: 存儲數據
- xxx.MYI: 存儲索引
Memory
Memory 引擎的表數據是存儲在內存中的,受硬件問題、斷電問題的影響,只能將這些表作為臨時表或緩存使用。
特點:
- 存放在內存中,速度快
- hash索引(默認)
文件:
- xxx.sdi: 存儲表結構信息
存儲引擎特點
| 特點 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| 存儲限制 | 64TB | 有 | 有 |
| 事務安全 | 支持 | - | - |
| 鎖機制 | 行鎖 | 表鎖 | 表鎖 |
| B+tree索引 | 支持 | 支持 | 支持 |
| Hash索引 | - | - | 支持 |
| 全文索引 | 支持(5.6版本之後) | 支持 | - |
| 空間使用 | 高 | 低 | N/A |
| 內存使用 | 高 | 低 | 中等 |
| 批量插入速度 | 低 | 高 | 高 |
| 支持外鍵 | 支持 | - | - |
存儲引擎的選擇
在選擇存儲引擎時,應該根據應用系統的特點選擇合適的存儲引擎。對於複雜的應用系統,還可以根據實際情況選擇多種存儲引擎進行組合。
- InnoDB: 如果應用對事物的完整性有比較高的要求,在併發條件下要求數據的一致性,數據操作除了插入和查詢之外,還包含很多的更新、刪除操作,則 InnoDB 是比較合適的選擇
- MyISAM: 如果應用是以讀操作和插入操作為主,只有很少的更新和刪除操作,並且對事務的完整性、併發性要求不高,那這個存儲引擎是非常合適的。
- Memory: 將所有數據保存在內存中,訪問速度快,通常用於臨時表及緩存。Memory 的缺陷是對錶的大小有限制,太大的表無法緩存在內存中,而且無法保障數據的安全性
電商中的足跡和評論適合使用 MyISAM 引擎,緩存適合使用 Memory 引擎。
性能分析
查看執行頻次
查看當前數據庫的 INSERT, UPDATE, DELETE, SELECT 訪問頻次:
SHOW GLOBAL STATUS LIKE 'Com_______'; 或者 SHOW SESSION STATUS LIKE 'Com_______';
例:show global status like 'Com_______'
慢查詢日誌
慢查詢日誌記錄了所有執行時間超過指定參數(long_query_time,單位:秒,默認10秒)的所有SQL語句的日誌。
MySQL的慢查詢日誌默認沒有開啓,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
# 開啓慢查詢日誌開關
slow_query_log=1
# 設置慢查詢日誌的時間為2秒,SQL語句執行時間超過2秒,就會視為慢查詢,記錄慢查詢日誌
long_query_time=2
更改後記得重啓MySQL服務,日誌文件位置:/var/lib/mysql/localhost-slow.log
查看慢查詢日誌開關狀態:
show variables like 'slow_query_log';
profile
show profile 能在做SQL優化時幫我們瞭解時間都耗費在哪裏。通過 have_profiling 參數,能看到當前 MySQL 是否支持 profile 操作:
SELECT @@have_profiling;
profiling 默認關閉,可以通過set語句在session/global級別開啓 profiling:
SET profiling = 1;
查看所有語句的耗時:
show profiles;
查看指定query_id的SQL語句各個階段的耗時:
show profile for query query_id;
查看指定query_id的SQL語句CPU的使用情況
show profile cpu for query query_id;
explain
EXPLAIN 或者 DESC 命令獲取 MySQL 如何執行 SELECT 語句的信息,包括在 SELECT 語句執行過程中表如何連接和連接的順序。
語法:
# 直接在select語句之前加上關鍵字 explain / desc
EXPLAIN SELECT 字段列表 FROM 表名 HWERE 條件;
EXPLAIN 各字段含義:
- id:select 查詢的序列號,表示查詢中執行 select 子句或者操作表的順序(id相同,執行順序從上到下;id不同,值越大越先執行)
- select_type:表示 SELECT 的類型,常見取值有 SIMPLE(簡單表,即不適用表連接或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(UNION中的第二個或者後面的查詢語句)、SUBQUERY(SELECT/WHERE之後包含了子查詢)等
- type:表示連接類型,性能由好到差的連接類型為 NULL、system、const、eq_ref、ref、range、index、all
- possible_key:可能應用在這張表上的索引,一個或多個
- Key:實際使用的索引,如果為 NULL,則沒有使用索引
- Key_len:表示索引中使用的字節數,該值為索引字段最大可能長度,並非實際使用長度,在不損失精確性的前提下,長度越短越好
- rows:MySQL認為必須要執行的行數,在InnoDB引擎的表中,是一個估計值,可能並不總是準確的
- filtered:表示返回結果的行數佔需讀取行數的百分比,filtered的值越大越好
索引
索引是幫助 MySQL 高效獲取數據的數據結構(有序)。在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查詢算法,這種數據結構就是索引。
優缺點:
優點:
- 提高數據檢索效率,降低數據庫的IO成本
- 通過索引列對數據進行排序,降低數據排序的成本,降低CPU的消耗
缺點:
- 索引列也是要佔用空間的
- 索引大大提高了查詢效率,但降低了更新的速度,比如 INSERT、UPDATE、DELETE
索引結構
| 索引結構 | 描述 |
|---|---|
| B+Tree | 最常見的索引類型,大部分引擎都支持B+樹索引 |
| Hash | 底層數據結構是用哈希表實現,只有精確匹配索引列的查詢才有效,不支持範圍查詢 |
| R-Tree(空間索引) | 空間索引是 MyISAM 引擎的一個特殊索引類型,主要用於地理空間數據類型,通常使用較少 |
| Full-Text(全文索引) | 是一種通過建立倒排索引,快速匹配文檔的方式,類似於 Lucene, Solr, ES |
| 索引 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| B+Tree索引 | 支持 | 支持 | 支持 |
| Hash索引 | 不支持 | 不支持 | 支持 |
| R-Tree索引 | 不支持 | 支持 | 不支持 |
| Full-text | 5.6版本後支持 | 支持 | 不支持 |
B-Tree

二叉樹的缺點可以用紅黑樹來解決:
紅黑樹也存在大數據量情況下,層級較深,檢索速度慢的問題。
為了解決上述問題,可以使用 B-Tree 結構。
B-Tree (多路平衡查找樹) 以一棵最大度數(max-degree,指一個節點的子節點個數)為5(5階)的 b-tree 為例(每個節點最多存儲4個key,5個指針)

B-Tree 的數據插入過程動畫參照:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=68
演示地址:https://www.cs.usfca.edu/~galles/visualization/BTree.html
B+Tree
結構圖:

演示地址:https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html
與 B-Tree 的區別:
- 所有的數據都會出現在葉子節點
- 葉子節點形成一個單向鏈表
MySQL 索引數據結構對經典的 B+Tree 進行了優化。在原 B+Tree 的基礎上,增加一個指向相鄰葉子節點的鏈表指針,就形成了帶有順序指針的 B+Tree,提高區間訪問的性能。

Hash
哈希索引就是採用一定的hash算法,將鍵值換算成新的hash值,映射到對應的槽位上,然後存儲在hash表中。
如果兩個(或多個)鍵值,映射到一個相同的槽位上,他們就產生了hash衝突(也稱為hash碰撞),可以通過鏈表來解決。
特點:
- Hash索引只能用於對等比較(=、in),不支持範圍查詢(betwwn、>、<、…)
- 無法利用索引完成排序操作
- 查詢效率高,通常只需要一次檢索就可以了,效率通常要高於 B+Tree 索引
存儲引擎支持:
- Memory
- InnoDB: 具有自適應hash功能,hash索引是存儲引擎根據 B+Tree 索引在指定條件下自動構建的
面試題
- 為什麼 InnoDB 存儲引擎選擇使用 B+Tree 索引結構?
- 相對於二叉樹,層級更少,搜索效率高
- 對於 B-Tree,無論是葉子節點還是非葉子節點,都會保存數據,這樣導致一頁中存儲的鍵值減少,指針也跟着減少,要同樣保存大量數據,只能增加樹的高度,導致性能降低
- 相對於 Hash 索引,B+Tree 支持範圍匹配及排序操作
索引分類
| 分類 | 含義 | 特點 | 關鍵字 |
|---|---|---|---|
| 主鍵索引 | 針對於表中主鍵創建的索引 | 默認自動創建,只能有一個 | PRIMARY |
| 唯一索引 | 避免同一個表中某數據列中的值重複 | 可以有多個 | UNIQUE |
| 常規索引 | 快速定位特定數據 | 可以有多個 | |
| 全文索引 | 全文索引查找的是文本中的關鍵詞,而不是比較索引中的值 | 可以有多個 | FULLTEXT |
在 InnoDB 存儲引擎中,根據索引的存儲形式,又可以分為以下兩種:
| 分類 | 含義 | 特點 |
|---|---|---|
| 聚集索引(Clustered Index) | 將數據存儲與索引放一塊,索引結構的葉子節點保存了行數據 | 必須有,而且只有一個 |
| 二級索引(Secondary Index) | 將數據與索引分開存儲,索引結構的葉子節點關聯的是對應的主鍵 | 可以存在多個 |
演示圖:

聚集索引選取規則:
- 如果存在主鍵,主鍵索引就是聚集索引
- 如果不存在主鍵,將使用第一個唯一(UNIQUE)索引作為聚集索引
- 如果表沒有主鍵或沒有合適的唯一索引,則 InnoDB 會自動生成一個 rowid 作為隱藏的聚集索引
思考題
1. 以下 SQL 語句,哪個執行效率高?為什麼?
select * from user where id = 10;
|
答:第一條語句,因為第二條需要回表查詢,相當於兩個步驟。
2. InnoDB 主鍵索引的 B+Tree 高度為多少?
答:假設一行數據大小為1k,一頁中可以存儲16行這樣的數據。InnoDB 的指針佔用6個字節的空間,主鍵假設為bigint,佔用字節數為8.
可得公式:n * 8 + (n + 1) * 6 = 16 * 1024,其中 8 表示 bigint 佔用的字節數,n 表示當前節點存儲的key的數量,(n + 1) 表示指針數量(比key多一個)。算出n約為1170。
如果樹的高度為2,那麼他能存儲的數據量大概為:1171 * 16 = 18736;
如果樹的高度為3,那麼他能存儲的數據量大概為:1171 * 1171 * 16 = 21939856。
另外,如果有成千上萬的數據,那麼就要考慮分表,涉及運維篇知識。
語法
創建索引:
CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name, ...);
如果不加 CREATE 後面不加索引類型參數,則創建的是常規索引
查看索引:
SHOW INDEX FROM table_name;
刪除索引:
DROP INDEX index_name ON table_name;
案例:
-- name字段為姓名字段,該字段的值可能會重複,為該字段創建索引
|
使用規則
最左前綴法則
如果索引關聯了多列(聯合索引),要遵守最左前綴法則,最左前綴法則指的是查詢從索引的最左列開始,並且不跳過索引中的列。
如果跳躍某一列,索引將部分失效(後面的字段索引失效)。
聯合索引中,出現範圍查詢(<, >),範圍查詢右側的列索引失效。可以用>=或者<=來規避索引失效問題。
索引失效情況
- 在索引列上進行運算操作,索引將失效。如:
explain select * from tb_user where substring(phone, 10, 2) = '15'; - 字符串類型字段使用時,不加引號,索引將失效。如:
explain select * from tb_user where phone = 17799990015;,此處phone的值沒有加引號 - 模糊查詢中,如果僅僅是尾部模糊匹配,索引不會是失效;如果是頭部模糊匹配,索引失效。如:
explain select * from tb_user where profession like '%工程';,前後都有 % 也會失效。 - 用 or 分割開的條件,如果 or 其中一個條件的列沒有索引,那麼涉及的索引都不會被用到。
- 如果 MySQL 評估使用索引比全表更慢,則不使用索引。
SQL 提示
是優化數據庫的一個重要手段,簡單來説,就是在SQL語句中加入一些人為的提示來達到優化操作的目的。
例如,使用索引:
explain select * from tb_user use index(idx_user_pro) where profession="軟件工程";
不使用哪個索引:
explain select * from tb_user ignore index(idx_user_pro) where profession="軟件工程";
必須使用哪個索引:
explain select * from tb_user force index(idx_user_pro) where profession="軟件工程";
use 是建議,實際使用哪個索引 MySQL 還會自己權衡運行速度去更改,force就是無論如何都強制使用該索引。
覆蓋索引&回表查詢
儘量使用覆蓋索引(查詢使用了索引,並且需要返回的列,在該索引中已經全部能找到),減少 select *。
explain 中 extra 字段含義:
using index condition:查找使用了索引,但是需要回表查詢數據
using where; using index;:查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表查詢
如果在聚集索引中直接能找到對應的行,則直接返回行數據,只需要一次查詢,哪怕是select *;如果在輔助索引中找聚集索引,如select id, name from xxx where name='xxx';,也只需要通過輔助索引(name)查找到對應的id,返回name和name索引對應的id即可,只需要一次查詢;如果是通過輔助索引查找其他字段,則需要回表查詢,如select id, name, gender from xxx where name='xxx';
所以儘量不要用select *,容易出現回表查詢,降低效率,除非有聯合索引包含了所有字段
面試題:一張表,有四個字段(id, username, password, status),由於數據量大,需要對以下SQL語句進行優化,該如何進行才是最優方案:
select id, username, password from tb_user where username='itcast';
解:給username和password字段建立聯合索引,則不需要回表查詢,直接覆蓋索引
前綴索引
當字段類型為字符串(varchar, text等)時,有時候需要索引很長的字符串,這會讓索引變得很大,查詢時,浪費大量的磁盤IO,影響查詢效率,此時可以只降字符串的一部分前綴,建立索引,這樣可以大大節約索引空間,從而提高索引效率。
語法:create index idx_xxxx on table_name(columnn(n));
前綴長度:可以根據索引的選擇性來決定,而選擇性是指不重複的索引值(基數)和數據表的記錄總數的比值,索引選擇性越高則查詢效率越高,唯一索引的選擇性是1,這是最好的索引選擇性,性能也是最好的。
求選擇性公式:
select count(distinct email) / count(*) from tb_user;
|
show index 裏面的sub_part可以看到接取的長度
單列索引&聯合索引
單列索引:即一個索引只包含單個列
聯合索引:即一個索引包含了多個列
在業務場景中,如果存在多個查詢條件,考慮針對於查詢字段建立索引時,建議建立聯合索引,而非單列索引。
單列索引情況:
explain select id, phone, name from tb_user where phone = '17799990010' and name = '韓信';
這句只會用到phone索引字段
注意事項
- 多條件聯合查詢時,MySQL優化器會評估哪個字段的索引效率更高,會選擇該索引完成本次查詢
設計原則
- 針對於數據量較大,且查詢比較頻繁的表建立索引
- 針對於常作為查詢條件(where)、排序(order by)、分組(group by)操作的字段建立索引
- 儘量選擇區分度高的列作為索引,儘量建立唯一索引,區分度越高,使用索引的效率越高
- 如果是字符串類型的字段,字段長度較長,可以針對於字段的特點,建立前綴索引
- 儘量使用聯合索引,減少單列索引,查詢時,聯合索引很多時候可以覆蓋索引,節省存儲空間,避免回表,提高查詢效率
- 要控制索引的數量,索引並不是多多益善,索引越多,維護索引結構的代價就越大,會影響增刪改的效率
- 如果索引列不能存儲NULL值,請在創建表時使用NOT NULL約束它。當優化器知道每列是否包含NULL值時,它可以更好地確定哪個索引最有效地用於查詢
SQL 優化
插入數據
普通插入:
- 採用批量插入(一次插入的數據不建議超過1000條)
- 手動提交事務
- 主鍵順序插入
大批量插入:
如果一次性需要插入大批量數據,使用insert語句插入性能較低,此時可以使用MySQL數據庫提供的load指令插入。
# 客户端連接服務端時,加上參數 --local-infile(這一行在bash/cmd界面輸入)
|
主鍵優化
數據組織方式:在InnoDB存儲引擎中,表數據都是根據主鍵順序組織存放的,這種存儲方式的表稱為索引組織表(Index organized table, IOT)
頁分裂:頁可以為空,也可以填充一般,也可以填充100%,每個頁包含了2-N行數據(如果一行數據過大,會行溢出),根據主鍵排列。
頁合併:當刪除一行記錄時,實際上記錄並沒有被物理刪除,只是記錄被標記(flaged)為刪除並且它的空間變得允許被其他記錄聲明使用。當頁中刪除的記錄到達 MERGE_THRESHOLD(默認為頁的50%),InnoDB會開始尋找最靠近的頁(前後)看看是否可以將這兩個頁合併以優化空間使用。
MERGE_THRESHOLD:合併頁的閾值,可以自己設置,在創建表或創建索引時指定
文字説明不夠清晰明瞭,具體可以看視頻裏的PPT演示過程:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=90
主鍵設計原則:
- 滿足業務需求的情況下,儘量降低主鍵的長度
- 插入數據時,儘量選擇順序插入,選擇使用 AUTO_INCREMENT 自增主鍵
- 儘量不要使用 UUID 做主鍵或者是其他的自然主鍵,如身份證號
- 業務操作時,避免對主鍵的修改
order by優化
- Using filesort:通過表的索引或全表掃描,讀取滿足條件的數據行,然後在排序緩衝區 sort buffer 中完成排序操作,所有不是通過索引直接返回排序結果的排序都叫 FileSort 排序
- Using index:通過有序索引順序掃描直接返回有序數據,這種情況即為 using index,不需要額外排序,操作效率高
如果order by字段全部使用升序排序或者降序排序,則都會走索引,但是如果一個字段升序排序,另一個字段降序排序,則不會走索引,explain的extra信息顯示的是Using index, Using filesort,如果要優化掉Using filesort,則需要另外再創建一個索引,如:create index idx_user_age_phone_ad on tb_user(age asc, phone desc);,此時使用select id, age, phone from tb_user order by age asc, phone desc;會全部走索引
總結:
- 根據排序字段建立合適的索引,多字段排序時,也遵循最左前綴法則
- 儘量使用覆蓋索引
- 多字段排序,一個升序一個降序,此時需要注意聯合索引在創建時的規則(ASC/DESC)
- 如果不可避免出現filesort,大數據量排序時,可以適當增大排序緩衝區大小 sort_buffer_size(默認256k)
group by優化
- 在分組操作時,可以通過索引來提高效率
- 分組操作時,索引的使用也是滿足最左前綴法則的
如索引為idx_user_pro_age_stat,則句式可以是select ... where profession order by age,這樣也符合最左前綴法則
limit優化
常見的問題如limit 2000000, 10,此時需要 MySQL 排序前2000000條記錄,但僅僅返回2000000 - 2000010的記錄,其他記錄丟棄,查詢排序的代價非常大。
優化方案:一般分頁查詢時,通過創建覆蓋索引能夠比較好地提高性能,可以通過覆蓋索引加子查詢形式進行優化
例如:
-- 此語句耗時很長
|
count優化
MyISAM 引擎把一個表的總行數存在了磁盤上,因此執行 count(*) 的時候會直接返回這個數,效率很高(前提是不適用where);
InnoDB 在執行 count(*) 時,需要把數據一行一行地從引擎裏面讀出來,然後累計計數。
優化方案:自己計數,如創建key-value表存儲在內存或硬盤,或者是用redis
count的幾種用法:
- 如果count函數的參數(count裏面寫的那個字段)不是NULL(字段值不為NULL),累計值就加一,最後返回累計值
- 用法:count(*)、count(主鍵)、count(字段)、count(1)
- count(主鍵)跟count(*)一樣,因為主鍵不能為空;count(字段)只計算字段值不為NULL的行;count(1)引擎會為每行添加一個1,然後就count這個1,返回結果也跟count(*)一樣;count(null)返回0
各種用法的性能:
- count(主鍵):InnoDB引擎會遍歷整張表,把每行的主鍵id值都取出來,返回給服務層,服務層拿到主鍵後,直接按行進行累加(主鍵不可能為空)
- count(字段):沒有not null約束的話,InnoDB引擎會遍歷整張表把每一行的字段值都取出來,返回給服務層,服務層判斷是否為null,不為null,計數累加;有not null約束的話,InnoDB引擎會遍歷整張表把每一行的字段值都取出來,返回給服務層,直接按行進行累加
- count(1):InnoDB 引擎遍歷整張表,但不取值。服務層對於返回的每一層,放一個數字 1 進去,直接按行進行累加
- count(*):InnoDB 引擎並不會把全部字段取出來,而是專門做了優化,不取值,服務層直接按行進行累加
按效率排序:count(字段) < count(主鍵) < count(1) < count(*),所以儘量使用 count(*)
update優化(避免行鎖升級為表鎖)
InnoDB 的行鎖是針對索引加的鎖,不是針對記錄加的鎖,並且該索引不能失效,否則會從行鎖升級為表鎖。
如以下兩條語句:
update student set no = '123' where id = 1;,這句由於id有主鍵索引,所以只會鎖這一行;
update student set no = '123' where name = 'test';,這句由於name沒有索引,所以會把整張表都鎖住進行數據更新,解決方法是給name字段添加索引
視圖/存儲過程/觸發器

視圖
視圖(View)是一種虛擬存在的表。視圖中的數據並不在數據庫中實際存在,行和列數據來自定義視圖的查詢中使用的表,並且是在使用視圖時動態生成的。
通俗的講,視圖只保存了查詢的SQL邏輯,不保存查詢結果。所以我們在創建視圖的時候,主要的工作就落在創建這條SQL查詢語句上。
語法
創建視圖:
CREATE [OR REPLACE] VIEW 視圖名稱(列名列表)】AS SELECT語句[WITH[CASCADED|LOCAL] CHECK OPTION]
查詢視圖:
查看創建視圖語句:SHOW CRETE VIEW 視圖名稱;
查看視圖數據:查看視圖數據:SELECT*FROM 視圖名稱…;
修改視圖:
方式一:
CREATE [OR REPLACE]VIEW 視圖名稱(列名列表)AS SELECT語句[WITH[CASCADEDLLOCAL] CHECK OPTION
方式二:
ALTER VEW 視圖名稱(列名列表)AS SELECT語句[WITH[CASCADED|LOCAL]CHECK OPTION]
刪除視圖:
DROP VIEW [IF EXISTS]視圖名稱[,視圖名稱]
-- 創建視圖
|
檢查選項
視圖的檢查選項:
當使用WITH CHECK OPTION子句創建視圖時,MySOL會通過視圖檢查正在更改的每個行,例如 插入,更新,刪除,以使其符合視圖的定義。MVSOL允許基於另一個視圖創建視圖,它還會檢查依賴視圖中的規則以保持一致性。
為了確定檢查的範圍,mysql 提供了兩個選項:CASCADED 和 LOCAL,默認值為CASCADED。
cascaded:在對創建時含有該字段的視圖,插入數據時,該視圖依賴的視圖都會加上檢查,需要所有條件都滿足才能夠插入成功。
local:在對創建時含有該字段的視圖,插入數據時,對於該視圖依賴的視圖中含有檢查語句的條件進行檢查判斷。
更新及作用
視圖的更新:
要使視圖可更新,視圖中的行與基礎表中的行之間必須存在一對一的關係。
如果視圖包含以下任何一項,則該視圖不可更新:
- 聚合函數或窗口函數(SUM()、MIN()、MAX()、COUNT()等
- DISTINCT
- GROUP BY
- HAVINGA
- UNION 或者 UNION ALL
作用:
- 簡單
視圖不僅可以簡化用户對數據的理解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義為視圖,從而使得用户不必為以後的操作每次指定全部的條件。 - 安全
數據庫可以授權,但不能授權到數據庫特定行和特定的列上。通過視圖用户只能查詢和修改他們所能見到的數據。 - 數據獨立
視圖可幫助用户屏蔽真實表結構變化帶來的影響。
案例
-- 1.為了保證數據庫表的安全性,開發人員在操作tb_user表時,只能看到的用户的基本字段,屏蔽手機號和郵箱兩個字段。
|
存儲過程
存儲過程其實就類似 java,c 這種語言,這一部分可以通過文檔快速學習,不懂的再回過頭看視頻。
存儲過程是事先經過編譯並存儲在數據庫中的一段 SQL語句的集合,調用存儲過程可以簡化應用開發人員的很多工作,減少數據在數據庫和應用服務器之間的傳輸,對於提高數據處理的效率是有好處的。
存儲過程思想上很簡單,就是數據庫 SOL語言層面的代碼封裝與重用。
特點:
- 封裝,複用
- 可以接收參數,也可以返回數據
- 減少網絡交互,效率提升
基本語法
查看視圖數據:SELECT*FROM 視圖名稱…;
查看:
SELECT* FROM INFORMATION SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA='xx';--查詢數據庫的存儲過程及狀態信息
SHOW CREATE PROCEDURE 存儲過程名稱;--查詢某個存儲過程的定義
刪除:
DROP PROCEDURE [IF EXISTS]存儲過程名稱;
案例:
-- 存儲過程基本語法
|
變量
系統變量
系統變量 是MySQL服務器提供,不是用户定義的,屬於服務器層面。分為全局變量(GLOBAL)、會話變量(SESSION)。
查看系統變量
SHOW [SESSION |GLOBAL] VARIABLES ; --查看所有系統變量
SHOW[SESSION|GLOBAL] VARIABLES LIKE'; --可以通過LKE模糊匹配方式查找變量
SELECT @@[SESSION|GLOBAL]系統變量名; -- 查看指定變量的值
-- 變量:系統變量
|
注意:
- 如果沒有指定 session / global,默認 session,會話變量
- myesql 服務器重啓之後,所設置的全局參數會失效,要想不失效,需要更改/etc/my.cnf 中的配置。
用户定義變量
用户定義變量 是用户根據需要自己定義的變量,用户變量不用提前聲明,在用的時候直接用“@變量名”使用就可以。其作用域為當前連接。
賦值:
SET @var name = expr [, @var_name = expr]...;
SET @var name := expr [, @var_name := expr]...;
SELECT @var name := expr , @var name := expr ...;
SELECT 字段名 INTO @var_name FROM 表名;
使用:
SELECT @var_name;
案例:
-- 變量:用户變量
|
注意:
用户定義的變量無需對其進行聲明或者初始化,只不過獲取到的值為 NULL。
局部變量
局部變量 是根據需要定義的在局部生效的變量,訪問之前,需要DECLARE聲明。可用作存儲過程內的局部變量和輸入參數,局部變量的範圍是在其內聲明的BEGIN .. END塊。
聲明:
DECLARE 變量名 變量類型 [DEFAULT..];
變量類型就是數據庫字段類型:INT、BIGINT、CHAR、VARCHAR、DATE、TIME等。
賦值:
SET 變量名=值;
SET 變量名:=值;
SELECT 字段名 INTO 變量名 FROM 表名 ...;
案例:
-- 變量:局部變量
|
if 判斷
語法:
IF 條件1 THEN
|
案例:
create procedure p3()
|
參數(in, out, inout)
| 類型 | 含義 | 備註 |
|---|---|---|
| IN | 該類參數作為輸入,也就是需要調用時傳入值 | 默認 |
| OUT | 該類參數作為輸出,也就是該參數可以作為返回值 | |
| INOUT | 既可以作為輸入參數,也可以作為輸出參數**** |
用法:
CREATE PROCEDURE 存儲過程名稱([IN/OUT/INOUT 參數名 參數類型 ])
|
案例:
-- 根據傳入(in)參數score,判定當前分數對應的分數等級,並返回(out)
|
case
語法一:
CASE case value
|
語法二:
CASE
|
案例:
-- case
|
循環
while
while 循環是有條件的循環控制語句。滿足條件後,再執行循環體中的SQL語句。
語法:
#先判定條件,如果條件為true,則執行邏輯,否則,不執行邏輯
|
案例:
-- while計算從1累加到 n 的值,n 為傳入的參數值。
|
repeat
repeat是有條件的循環控制語句,當滿足條件的時候退出循環。
與 while 區別:
- 先進行循環一次再判斷。相當於 c 語言中的 do while();
- 滿足條件則退出
語法:
#先執行一次邏輯,然後判定邏輯是否滿足,如果滿足,則退出。如果不滿足,則繼續下一次循環
|
案例:
-- while計算從1累加到 n 的值,n 為傳入的參數值。
|
loop
LOOP 實現簡單的循環,如果不在SQL邏輯中增加退出循環的條件,可以用其來實現簡單的死循環。LOOP可以配合一下兩個語句使用。
- LEAVE:配合循環使用,退出循環。
- ITERATE:必須用在循環中,作用是跳過當前循環剩下的語句,直接進入下一次循環。
[begin label:] LOOP
|
案例:
-- loop 計算從1到n之間的偶數累加的值,n為傳入的參數值。
|
遊標-cursor
遊標(CURSOR)是用來存儲查詢結果集的數據類型,在存儲過程和函數中可以使用遊標對結果集進行循環的處理。遊標的使用包括遊標的聲明、OPEN、FETCH和 CLOSE,其語法分別如下。
通俗點講:類似於 c 語言中的結構體,java 中的實體類。
聲明遊標
DECLARE 遊標名稱 CURSOR FOR 查詢語句;
|
打開遊標:
OPEN 遊標名稱;
|
獲取遊標記錄:
FETCH 遊標名稱 INTO 變量[,變量];
|
關閉遊標:
CLOSE 遊標名稱;
|
案例:
-- 遊標
|
條件處理程序-handler
條件處理程序(Handler)可以用來定義在流程控制結構執行過程中遇到問題時相應的處理步驟。
語法:
DECLARE handler action HANDLERFOR condition value l, condition value.... statement;
|
案例:
create procedure p11(in uage int)
|
存儲函數:
存儲函數是有返回值的存儲過程,存儲函數的參數只能是IN類型的。
存儲函數用的較少,能夠使用存儲函數的地方都可以用存儲過程替換。
語法:
CREATE FUNCTION 存儲函數名稱([ 參數列表 ])
|
案例:
create function fun1(n int)
|
觸發器
觸發器是與表有關的數據庫對象,指在 insert/update/delete 之前或之後,觸發並執行觸發器中定義的SQL語句集合。觸發器的這種特性可以協助應用在數據庫端確保數據的完整性,日誌記錄,數據校驗等操作。
使用別名 OLD 和 NEW 來引用觸發器中發生變化的記錄內容,這與其他的數據庫是相似的。現在觸發器還只支持行級觸發,不支持語句級觸發。
| 觸發器類型 | NEW 和 OLD |
|---|---|
| insert 型觸發器 | NEW 表示將要或者已經新增的數據 |
| update 型觸發器 | OLD 表示修改之前的數據,NEW 表示將要或已經修改後的數據 |
| delete 型觸發器 | OLD 表示將要或者已經刪除的數據 |
語法:
創建:
CREATE TRIGGER trigger name
|
查看:
SHOW TRIGGERS;
|
刪除:
DROP TRIGGER [schema_name.]trigger_name; --如果沒有指定 schema name,默認為當前數據庫
|
案例:
-- 插入數據觸發器
|
鎖
介紹:
鎖是計算機協調多個進程或線程併發訪問某一資源的機制。在數據庫中,除傳統的計算資源(CPU、RAM、I/0)的爭用以外,數據也是一種供許多用户共享的資源。如何保證數據併發訪問的一致性、有效性是所有數據庫必須解決的一個問題,鎖衝突也是影響數據庫併發訪問性能的一個重要因素。從這個角度來説,鎖對數據庫而言顯得尤其重要,也更加複雜。
分類:
MySQL中的鎖,按照鎖的粒度分,分為一下三類:
- 全局鎖:鎖定數據庫中的所有表。
- 表級鎖:每次操作鎖住整張表。
- 行級鎖:每次操作鎖住對應的行數據。
全局鎖
介紹:
全局鎖就是對整個數據庫實例加鎖,加鎖後整個實例就處於只讀狀態,後續的DML的寫語句,DDL語句,已經更新操作的事務提交語句都將被阻塞。
其典型的使用場景是做全庫的邏輯備份,對所有的表進行鎖定,從而獲取一致性視圖,保證數據的完整性。
基本操作:
使用全局鎖:flush tables with read lock
釋放全局鎖:unlock tables
演示圖:


特點:
數據庫中加全局鎖,是一個比較重的操作,存在以下問題:
- 如果在主庫上備份,那麼在備份期間都不能執行更新,業務基本上就得停擺。
- 如果在從庫上備份,那麼在備份期間從庫不能執行主庫同步過來的二進制日誌(binlog),會導致主從延遲。(該結構會在後續主從複製講解)
解決方法:
在InnoDB引擎中,我們可以在備份時加上參數 –single-transaction 參數來完成不加鎖的一致性數據備份。
mysqldump --single-transaction -uroot -p123456 itcast > itcast.sql(只適用於支持「可重複讀隔離級別的事務」的存儲引擎)
原理補充:通過加上這個參數,確保了在備份開始時創建一個一致性的快照,通過啓動一個新的事務來實現這一點。(該事務的隔離級別是Repeatable Read級別),從而實現在該事務讀取下一直讀取的是創建時的數據,而不影響其他事務的讀寫操作。
表級鎖
每次操作鎖住整張表。鎖定粒度大,發生鎖的衝突的概率最高,併發度最低。應用在MyISAM、InnoDB、BDB等存儲引擎中。
對於表級鎖,主要分為一下三類:
- 表鎖
- 元數據鎖(meta data lock,MDL)
- 意向鎖
表鎖
對於表鎖,分為兩類:
- 表共享讀鎖(read lock)
- 表獨佔寫鎖(write lock)
讀鎖不會阻塞其他客户端的讀,但是會阻塞寫。寫鎖既會阻塞其他客户端的讀,又會阻塞其他客户端的寫。
語法:
//表級別的共享鎖,也就是讀鎖;
|
釋放所有鎖:
unlock tables (會話退出,也會釋放所有鎖)
元數據鎖
MDL加鎖過程是系統自動控制,無需顯式使用,在訪問一張表的時候會自動加上。MDL鎖主要作用是維護表元數據的數據一致性,在表
上有活動事務的時候,不可以對元數據進行寫入操作。為了避免DML與DDL衝突,保證讀寫的正確性。
- 對一張表進行 CRUD 操作時,加的是 MDL 讀鎖;
- 對一張表做結構變更操作的時候,加的是 MDL 寫鎖;
| 對應SQL | 鎖類型 | 説明 |
|---|---|---|
| lock tables xxx read /write | SHARED_READ_ONLY/SHARED_NO_READ_WRITE | |
| select 、 select … lock in share mode | SHARED_READ | 與SHARED_READ、SHARED_WRITE兼容,與EXCLUSIVE互斥 |
| insert 、update、delete、select …for update | SHARED_WRITE | 與SHARED_READ、SHARED_WRITE兼容,與EXCLUSIVE互斥 |
| alter table … | EXCLYSIVE | 與其他的MDL都互斥 |
查看元數據鎖:
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
意向鎖
為了避免DML在執行時,加的行鎖與表鎖的衝突,在InnoDB中引入了意向鎖,使得表鎖不用檢查每行數據是否加鎖,使用意向鎖來減
少表鎖的檢查。
意向共享鎖和意向獨佔鎖是表級鎖,不會和行級的共享鎖和獨佔鎖發生衝突,而且意向鎖之間也不會發生衝突,只會和共享表鎖(lock tables … read)和獨佔表鎖(lock tables … write)發生衝突
如果沒有「意向鎖」,那麼加「獨佔表鎖」時,就需要遍歷表裏所有記錄,查看是否有記錄存在獨佔鎖,這樣效率會很慢。
那麼有了「意向鎖」,由於在對記錄加獨佔鎖前,先會加上表級別的意向獨佔鎖,那麼在加「獨佔表鎖」時,直接查該表是否有意向獨佔鎖,如果有就意味着表裏已經有記錄被加了獨佔鎖,這樣就不用去遍歷表裏的記錄。
意向鎖的目的是為了快速判斷表裏是否有記錄被加鎖。
加鎖方式:
意向共享鎖:(先在表上加上意向共享鎖,然後對讀取的記錄加共享鎖)
由 select ... lock in share mode 添加
意向獨佔鎖:(先表上加上意向獨佔鎖,然後對讀取的記錄加獨佔鎖)
由 insert、update、delete、select ... for update 添加
AUTO-INC鎖(補充)


行級鎖
行級鎖,每次操作鎖住對應的行數據。鎖定粒度最小,發生鎖衝突的概率最低,併發度最高。應用在InnoDB存儲引擎中。
- 行鎖(Record Lock):鎖定單個行記錄的鎖,防止其他事務對此行進行update和delete。在RC、RR隔離級別下都支持。
- 間隙鎖(GapLock):鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事務在這個間隙進行insert,產生幻讀。在RR隔離級別下都支持。
- 臨鍵鎖(Next-Key Lock):行鎖和間隙鎖組合,同時鎖住數據,並鎖住數據前面的間隙Gap。在RR隔離級別下支持。
Record Lock(行鎖)
Record Lock 稱為記錄鎖,鎖住的是一條記錄。而且記錄鎖是有 S 鎖和 X 鎖之分。
InnoDB實現了以下兩種類型的行鎖:
- 共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排它鎖。
- 排他鎖(X):允許獲取排他鎖的事務更新數據,阻止其他事務獲得相同數據集的共享鎖和排他鎖。
| S(共享鎖) | X(排他鎖) | |
|---|---|---|
| S(共享鎖) | 兼容 | 衝突 |
| X(排他鎖) | 衝突 | 衝突 |
行鎖類型:
| SQL | 行鎖類型 | 説明 |
|---|---|---|
| insert,update,delete … | 排他鎖 | 自動加鎖 |
| select | 不加任何鎖 | |
| select … lock in share mode | 共享鎖 | 需要手動select之後加上lock in share mode |
| select … for update | 排他鎖 | 需要手動在select之後for update |
默認情況下,InnoDB在 REPEATABLE READ事務隔離級別運行,InnoDB使用 next-key鎖進行搜索和索引掃描,以防止幻讀。
- 針對唯一索引進行檢索時,對已存在的記錄進行等值匹配時,將會自動優化為行鎖。
- InnoDB的行鎖是針對於索引加的鎖,不通過索引條件檢索數據,那麼!nnoDB將對錶中的所有記錄加鎖,此時 就會升級為表鎖。
查看意向鎖及行鎖的加鎖情況:
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from peformance_schema.data_locks;
Gap Lock(間隙鎖)

Next-Key Lock(臨鍵鎖)

默認情況下,InnODB在 REPEATABLE READ事務隔離級別運行,InnoDB使用 next-key 鎖進行搜索和索引掃描,以防止幻讀。
- 索引上的等值查詢(唯一索引),給不存在的記錄加鎖時,優化為間隙鎖 。
- 索引上的等值查詢(普通索引),向右遍歷時最後一個值不滿足查詢需求時,next-keylock退化為間隙鎖。
- 索引上的範圍查詢(唯一索引)–會訪問到不滿足條件的第一個值為止。
InnoDB引擎
邏輯存儲結構


架構

內存架構




磁盤結構


後台線程

事務原理
事務:
事務 是一組操作的集合,它是一個不可分割的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要麼同時成功,要麼同時失敗。
特徵:
- 原子性(Atomicity):事務是不可分割的最小操作單元,要麼全部成功,要麼全部失敗。
- 一致性(Consistency) :事務完成時,必須使所有的數據都保持一致狀態。
- 隔離性(lsolation):數據庫系統提供的隔離機制,保證事務在不受外部併發操作影響的獨立環境下運行。
- 持久性(Durability):事務一旦提交或回滾,它對數據庫中的數據的改變就是永久的。
特性原理分類圖:

redo log
重做日誌,記錄的是事務提交時數據頁的物理修改,是用來實現事務的持久性。
該日誌文件由兩部分組成:重做日誌緩衝(redo log buffer)以及重做日誌文件(redo log file),前者是在內存中,後者在磁盤中。當事務提交之後會把所有修改信息都存到該日誌文件中,用於在刷新髒頁到磁盤,發生錯誤時,進行數據恢復使用。
Buffer Pool在產生髒頁數據的時候,會先將數據存儲到 redo log buffer 再存儲到 redo log 中進行磁盤持久化存儲,在內存出現異常(比如突然斷電)時,通過redo log中持久化的數據進行回滾。過程如下圖:

redo log 要寫到磁盤,數據也要寫磁盤,為什麼要多此一舉?
寫入 redo log 的方式使用了追加操作,所以磁盤操作是順序寫,而寫入數據需要先找到寫入位置,然後才寫到磁盤,所以磁盤操作是隨機寫。
undo log
回滾日誌,用於記錄數據被修改前的信息,作用包含兩個:提供回滾 和 MVCC(多版本併發控制)。
undo log 和 redo log 記錄物理日誌不一樣,它是邏輯日誌。可以認為當 delete 一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當 update 一條記錄時,它記錄一條對應相反的 update 記錄。當執行 rollback 時,就可以從 undo log 中的邏輯記錄讀取到相應的內容並進行回滾。
Undo log 銷燬:undo log 在事務執行時產生,事務提交時,並不會立即刪除undol0g,因為這些日誌可能還用於 MVCC。
Undo log 存儲:undo log 採用段的方式進行管理和記錄,存放在前面介紹的 rollback segment 回滾段中,內部包含1024個 undo log segment.
MVCC
當前讀:
讀取的是記錄的最新版本,讀取時還要保證其他併發事務不能修改當前記錄,會對讀取的記錄進行加鎖。對於我們日常的操作,如:select…lock in share mode(共享鎖),select… for update、update、insert、delete(排他鎖)都是一種當前讀。
快照讀:
簡單的select(不加鎖)就是快照讀,快照讀,讀取的是記錄數據的可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。
- Read committed:每次select,都生成一個快照讀。
- Repeatable Read:開啓事務後第一個select語句才是快照讀的地方。
- Serializable:快照讀會退化為當前讀。
MVCC:
全稱 Multi-Version Concurrency Control,多版本併發控制。指維護一個數據的多個版本,使得讀寫操作沒有衝突,快照讀為MVSOL實現MVCC提供了一個非阻塞讀功能。MVCC的具體實現,還需要依賴於數據庫記錄中的三個隱式字段、undo log日誌、read View。
三個隱藏字段

undo log
回滾日誌,在insert、update、delete的時候產生的便於數據回滾的日誌。
當insert的時候,產生的undoloq日誌只在回滾時需要,在事務提交後,可被立即刪除。
而update、delete的時候,產生的undo log日誌不僅在回滾時需要,在快照讀時也需要,不會立即被刪除。
那麼何時刪除?
- 事務提交後:
- 對於
INSERT操作,事務提交後,undo log可以被立即刪除,因為不再需要用於回滾。 - 對於
UPDATE和DELETE操作,undo log不會立即被刪除,因為它們可能在後續的快照讀取中被使用。
- 對於
- 快照讀取結束:
- 當所有依賴於該undo log的快照讀取操作結束後,undo log才會被刪除。這意味着如果有一個事務正在進行快照讀取,並且依賴於某個undo log,那麼這個undo log會一直保留直到該事務結束。

readview
ReadView(讀視圖)是 快照讀 SOL執行時MVCC提取數據的依據,記錄並維護系統當前活躍的事務(未提交的)id。
ReadView中包含了四個核心字段:
| 字段 | 含義 |
|---|---|
| m_ids | 當前活躍的事務ID集合 |
| min_trx_id | 最小活躍事務ID |
| max_trx_id | 預分配事務ID,當前最大事務ID+1(因為事務ID是自增的) |
| creator_trx_id | ReadView創建者的事務ID |


依次比較 undo log 日誌中版本數據鏈,找到可以進行訪問的版本數據。
MySQL管理
系統數據庫介紹
Mysql數據庫安裝完成後,自帶了一下四個數據庫,具體作用如下:
| 數據庫 | 含義 |
|---|---|
| mysql | 存儲MVSQL服務器正常運行所需要的各種信息(時區、主從、用户、權限等) |
| information_schema | 提供了訪問數據庫元數據的各種表和視圖,包含數據庫、表、字段類型及訪問權限等 |
| performance_schema | 為MySQL服務器運行時狀態提供了一個底層監控功能,主要用於收集數據庫服務器性能參數 |
| sys | 包含了一系列方便 DBA和開發人員利用 performance_schema性能數據庫進行性能調優和診斷的視圖 |
常用工具
mysql

mysqladmin

mysqlbinlog

mysqlshow

mysqldump

mysqlimport/source

運維篇
日誌
錯誤日誌
錯誤日誌是 MySQL 中最重要的日誌之一,它記錄了當 mysqld 啓動和停止時,以及服務器在運行過程中發生任何嚴重錯誤時的相關信息當數據庫出現任何故障導致無法正常使用時,建議首先查看此日誌。
該日誌是默認開啓的,默認存放目錄 /var/log/,默認的日誌文件名為 mysqld.log 。查看日誌位置:
show variables like '%log_error%'
二進制日誌
介紹
二進制日誌(BINLOG)記錄了所有的 DDL(數據定義語言)語句和 DML(數據操縱語言)語句,但不包括數據查詢(SELECT、SHOW)語句。
作用:
- 災難時的數據恢復;
- MySQL的主從複製。
在MVSOL8版本中,默認二進制日誌是開啓着的,涉及到的參數如下:
show variables like '%log_bin%'
日誌格式
MySQL服務器中提供了多種格式來記錄二進制記錄,具體格式及特點如下:
| 日誌格式 | 含義 |
|---|---|
| statement | 基於SQL語句的日誌記錄,記錄的是SQL語句,對數據進行修改的SQL都會記錄在日誌文件中。 |
| row | 基於行的日誌記錄,記錄的是每一行的數據變更。(默認) |
| mined | 混合了STATEMENT和ROW兩種格式,默認採用STATEMENT,在某些特殊情況下會自動切換為ROW進行記錄。 |
查看參數方式:show variables like '%binlog_format%';
日誌查看
由於日誌是以二進制方式存儲的,不能直接讀取,需要通過二進制日誌查詢工具 mysqlbinlog 來查看,具體語法:
mysqlbinlog[參數選項]logfilename
|
日誌刪除
對於比較繁忙的業務系統,每天生成的binlog數據巨大,如果長時間不清除,將會佔用大量磁盤空間。可以通過以下幾種方式清理日誌:
| 指令 | 含義 |
|---|---|
| reset master | 刪除全部 binlog 日誌,刪除之後,日誌編號,將從 binlog.000001重新開始 |
| purge master logs to ‘binlog.***’ | 刪除 *** 編號之前的所有日誌 |
| purge master logs before ‘yyyy-mm-dd hh24:mi:ss’ | 刪除日誌為”yyyy-mm-dd hh24:mi:ss”之前產生的所有日誌 |
也可以在mysql的配置文件中配置二進制日誌的過期時間,設置了之後,二進制日誌過期會自動刪除.
show variables like '%binlog_expire_logs_seconds%'
查詢日誌
查詢日誌中記錄了客户端的所有操作語句,而二進制日誌不包含查詢數據的SQL語句。默認情況下,查詢日誌是未開啓的。如果需要開啓查詢日誌,可以設置一下配置:
修改MySQL的配置文件 /etc/my.cnf 文件,添加如下內容:
#該選項用來開啓查詢日誌,可選值:0或者1;0代表關閉,1代表開啓
|
慢查詢日誌
慢查詢日誌記錄了所有執行時間超過參數 long_query_time 設置值並且掃描記錄數不小於 min_examined_row_limit的所有的SQL語句的日誌,默認未開啓。long_query_time 默認為 10 秒,最小為0,精度可以到微秒。
#慢查詢日誌
|
默認情況下,不會記錄管理語句,也不會記錄不使用索引進行查找的查詢。可以使用log_slow_admin_statements和更改此行為log_queries_not_using_indexes,如下所述。
#記錄執行較慢的管理語句
|
主從複製


原理

搭建實現
主庫配置



從庫配置



測試
1、在主庫上創建數據庫、表,並插入數據
create database db01;
|
2、在從庫中查詢數據,驗證主從是否同步。
分庫分表
介紹





Mycat概述



Mycat入門





Mycat配置
schema.xml
schema.xml作為MyCat中最重要的配置文件之一,涵蓋了MyCat的邏輯庫 、邏輯表 、分片規則、分片節點及數據源的配置.
主要包含以下三組標籤:
- schema標籤
- datanode標籤
- datahost標籤




rule.xml



Mycat分片
垂直分庫




水平分表



分片規則
範圍分片


取模分片


一致性hash算法


枚舉分片


應用指定算法


固定hash算法


字符串hash解析


按天分片


按自然月分片


Mycat管理及監控


讀寫分離

介紹

一主一從讀寫分離


雙主雙從







測試:
分別在兩台主庫Master1、Master2上執行DDL、DML語句,查看涉及到的數據庫服務器的數據同步情況。
create database db01;
|
雙主雙從讀寫分離


測試:
登錄MyCat,測試查詢及更新操作,判定是否能夠進行讀寫分離,以及讀寫分離的策略是否正確。
當主庫掛掉一個之後,是否能夠自動切換。
數據類型
整型
| 類型名稱 | 取值範圍 | 大小 |
|---|---|---|
| TINYINT | -128〜127 | 1個字節 |
| SMALLINT | -32768〜32767 | 2個宇節 |
| MEDIUMINT | -8388608〜8388607 | 3個字節 |
| INT (INTEGHR) | -2147483648〜2147483647 | 4個字節 |
| BIGINT | -9223372036854775808〜9223372036854775807 | 8個字節 |
無符號在數據類型後加 unsigned 關鍵字。
浮點型
| 類型名稱 | 説明 | 存儲需求 |
|---|---|---|
| FLOAT | 單精度浮點數 | 4 個字節 |
| DOUBLE | 雙精度浮點數 | 8 個字節 |
| DECIMAL (M, D),DEC | 壓縮的“嚴格”定點數 | M+2 個字節 |
日期和時間
| 類型名稱 | 日期格式 | 日期範圍 | 存儲需求 |
|---|---|---|---|
| YEAR | YYYY | 1901 ~ 2155 | 1 個字節 |
| TIME | HH:MM:SS | -838:59:59 ~ 838:59:59 | 3 個字節 |
| DATE | YYYY-MM-DD | 1000-01-01 ~ 9999-12-3 | 3 個字節 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 | 8 個字節 |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | 1980-01-01 00:00:01 UTC ~ 2040-01-19 03:14:07 UTC | 4 個字節 |
字符串
| 類型名稱 | 説明 | 存儲需求 |
|---|---|---|
| CHAR(M) | 固定長度非二進制字符串 | M 字節,1<=M<=255 |
| VARCHAR(M) | 變長非二進制字符串 | L+1字節,在此,L< = M和 1<=M<=255 |
| TINYTEXT | 非常小的非二進制字符串 | L+1字節,在此,L<2^8 |
| TEXT | 小的非二進制字符串 | L+2字節,在此,L<2^16 |
| MEDIUMTEXT | 中等大小的非二進制字符串 | L+3字節,在此,L<2^24 |
| LONGTEXT | 大的非二進制字符串 | L+4字節,在此,L<2^32 |
| ENUM | 枚舉類型,只能有一個枚舉字符串值 | 1或2個字節,取決於枚舉值的數目 (最大值為65535) |
| SET | 一個設置,字符串對象可以有零個或 多個SET成員 | 1、2、3、4或8個字節,取決於集合 成員的數量(最多64個成員) |
二進制類型
| 類型名稱 | 説明 | 存儲需求 |
|---|---|---|
| BIT(M) | 位字段類型 | 大約 (M+7)/8 字節 |
| BINARY(M) | 固定長度二進制字符串 | M 字節 |
| VARBINARY (M) | 可變長度二進制字符串 | M+1 字節 |
| TINYBLOB (M) | 非常小的BLOB | L+1 字節,在此,L<2^8 |
| BLOB (M) | 小 BLOB | L+2 字節,在此,L<2^16 |
| MEDIUMBLOB (M) | 中等大小的BLOB | L+3 字節,在此,L<2^24 |
| LONGBLOB (M) | 非常大的BLOB | L+4 字節,在此,L<2^32 |
權限一覽表
具體權限的作用詳見官方文檔
GRANT 和 REVOKE 允許的靜態權限
| Privilege | Grant Table Column | Context |
|---|---|---|
ALL [PRIVILEGES] |
Synonym for “all privileges” | Server administration |
ALTER |
Alter_priv |
Tables |
ALTER ROUTINE |
Alter_routine_priv |
Stored routines |
CREATE |
Create_priv |
Databases, tables, or indexes |
CREATE ROLE |
Create_role_priv |
Server administration |
CREATE ROUTINE |
Create_routine_priv |
Stored routines |
CREATE TABLESPACE |
Create_tablespace_priv |
Server administration |
CREATE TEMPORARY TABLES |
Create_tmp_table_priv |
Tables |
CREATE USER |
Create_user_priv |
Server administration |
CREATE VIEW |
Create_view_priv |
Views |
DELETE |
Delete_priv |
Tables |
DROP |
Drop_priv |
Databases, tables, or views |
DROP ROLE |
Drop_role_priv |
Server administration |
EVENT |
Event_priv |
Databases |
EXECUTE |
Execute_priv |
Stored routines |
FILE |
File_priv |
File access on server host |
GRANT OPTION |
Grant_priv |
Databases, tables, or stored routines |
INDEX |
Index_priv |
Tables |
INSERT |
Insert_priv |
Tables or columns |
LOCK TABLES |
Lock_tables_priv |
Databases |
PROCESS |
Process_priv |
Server administration |
PROXY |
See proxies_priv table |
Server administration |
REFERENCES |
References_priv |
Databases or tables |
RELOAD |
Reload_priv |
Server administration |
REPLICATION CLIENT |
Repl_client_priv |
Server administration |
REPLICATION SLAVE |
Repl_slave_priv |
Server administration |
SELECT |
Select_priv |
Tables or columns |
SHOW DATABASES |
Show_db_priv |
Server administration |
SHOW VIEW |
Show_view_priv |
Views |
SHUTDOWN |
Shutdown_priv |
Server administration |
SUPER |
Super_priv |
Server administration |
TRIGGER |
Trigger_priv |
Tables |
UPDATE |
Update_priv |
Tables or columns |
USAGE |
Synonym for “no privileges” | Server administration |
GRANT 和 REVOKE 允許的動態權限
| Privilege | Context |
|---|---|
APPLICATION_PASSWORD_ADMIN |
Dual password administration |
AUDIT_ABORT_EXEMPT |
Allow queries blocked by audit log filter |
AUDIT_ADMIN |
Audit log administration |
AUTHENTICATION_POLICY_ADMIN |
Authentication administration |
BACKUP_ADMIN |
Backup administration |
BINLOG_ADMIN |
Backup and Replication administration |
BINLOG_ENCRYPTION_ADMIN |
Backup and Replication administration |
CLONE_ADMIN |
Clone administration |
CONNECTION_ADMIN |
Server administration |
ENCRYPTION_KEY_ADMIN |
Server administration |
FIREWALL_ADMIN |
Firewall administration |
FIREWALL_EXEMPT |
Firewall administration |
FIREWALL_USER |
Firewall administration |
FLUSH_OPTIMIZER_COSTS |
Server administration |
FLUSH_STATUS |
Server administration |
FLUSH_TABLES |
Server administration |
FLUSH_USER_RESOURCES |
Server administration |
GROUP_REPLICATION_ADMIN |
Replication administration |
GROUP_REPLICATION_STREAM |
Replication administration |
INNODB_REDO_LOG_ARCHIVE |
Redo log archiving administration |
NDB_STORED_USER |
NDB Cluster |
PASSWORDLESS_USER_ADMIN |
Authentication administration |
PERSIST_RO_VARIABLES_ADMIN |
Server administration |
REPLICATION_APPLIER |
PRIVILEGE_CHECKS_USER for a replication channel |
REPLICATION_SLAVE_ADMIN |
Replication administration |
RESOURCE_GROUP_ADMIN |
Resource group administration |
RESOURCE_GROUP_USER |
Resource group administration |
ROLE_ADMIN |
Server administration |
SESSION_VARIABLES_ADMIN |
Server administration |
SET_USER_ID |
Server administration |
SHOW_ROUTINE |
Server administration |
SYSTEM_USER |
Server administration |
SYSTEM_VARIABLES_ADMIN |
Server administration |
TABLE_ENCRYPTION_ADMIN |
Server administration |
VERSION_TOKEN_ADMIN |
Server administration |
XA_RECOVER_ADMIN |
Server administration |
圖形化界面工具
- Workbench(免費): http://dev.mysql.com/downloads/workbench/
- navicat(收費,試用版30天): https://www.navicat.com/en/download/navicat-for-mysql
- Sequel Pro(開源免費,僅支持Mac OS): http://www.sequelpro.com/
- HeidiSQL(免費): http://www.heidisql.com/
- phpMyAdmin(免費): https://www.phpmyadmin.net/
- SQLyog: https://sqlyog.en.softonic.com/
安裝
小技巧
- 在SQL語句之後加上
\G會將結果的表格形式轉換成行文本形式 - 查看Mysql數據庫佔用空間:
SELECT table_schema "Database Name"
|
- 本文鏈接: https://jimhackking.github.io/運維/MySQL學習筆記/
- 版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!