深入淺出MySQL備忘錄

此文章爲《深入淺出MySQL》第二版的備忘錄。

第2章 SQL基礎

SQL語句分爲:

  • DDL(Data Definition Languages)語句: 數據庫結構定義爲語言。
  • DML(Data Manipulation Languages)語句: 數據操作語句。
  • DCL(Data Control Languages)語句: 權限控制語句。

MySQL自帶數據庫:

  • information_schema: 存儲數據庫對象信息,如用戶表,列,權限,字符集,分區等信息。此爲虛擬數據庫,其中的表均爲視圖。

    • SCHEMATA: 當前mysql實例的所有數據庫信息,show databases信息來源。
    • TABLES: 關於數據庫的表(視圖)信息,show table from ${schame_name}信息來源。
    • COLUMNS: show columns from ${schema_name}.${table_name}信息來源。
    • STATISTICS: 表的索引信息。show index from ${schema_name}.${table_name}信息來源。
  • cluster: 存儲集羣信息。
  • mysql: 存儲用戶權限信息。
  • test: 系統自動創建的測試數據庫,任何用戶均可使用。
在MySQL世界,drop語句操作的結果都顯示 0 rows affected。

WITH ROLLUP可對分類聚合後的結果進行再彙總。
UNION於UNION ALL的區別是會進行一次DISTINCT操作。
? contents 或者 ? <key_words> 可快速查詢使用手冊。

第3章 數據類型

若列被指定了zerofill,則會自動添加UNSIGNED屬性。
DECIMAL默認爲DECIMAL(10, 0)

TIMESTAMP:

  1. 表中的第一個TIMESTAMP列的默認值將被設置爲當前時間。
  2. 其值的存儲與讀取與時區有關。

VARCHAR會保留存儲後端空格,CHAR不會。

第4章 運算符

<=>: NULL安全的等於, 也即:

  • SELECT NULL <=> NULL return 1
  • SELECT NULL = NULL return 0

第5章 常用函數

第7章 存儲引擎

MySQL默認引擎在5.5後更改爲InnoDB。

第8章 合適的數據類型

對於InnoDB,內部行存儲合適未區分可變長度和固定長度。故推薦使用VARCHAR,其平均空間佔用更小。

編程與存儲時,精確計算需使用定點數(Decimal,Java中也有此類),浮點數會有誤差。
對於BLOB和TEXT,刪除和修改操作後均需使用OPTIMIZE TABLE對錶進行碎片整理。

第9章 字符集

字符集選擇原則

  1. 多語言支持或主要處理英文字符,UTF8。
  2. 只需要支持中文,GBK,因其較小,每個中文佔用2個字節,UTF8爲3個。
  3. 需要做大量的字符計算,排序,比較等,建議定長字符。
  4. 考慮客戶端的字符集。

show character set或查看information_schema.character_set顯示所有的字符集(MySQL字符串的存儲方式)和該字符集對應的校對規則(比較字符串的方式),其爲一對多的關係。
show collation like *或者查看information_schema.COLLATIONS查看相關字符集的校對規則。
校對規則結尾命名:

  1. _ic: 大小寫不敏感。
  2. _cs: 大小寫敏感。
  3. _bin: 比較字符編碼值。

show variables like ‘character_set_${scope}’;
show variables like ‘collation_${scope}’;
查看當前scope(server: 服務器, database: 數據庫)的字符集和校對規則。

第10章 索引

索引列的數據越分散,篩選結果集越小,作用越大,比如對於性別列作用不大。
使用短索引。
利用最左前綴。
普通索引均會保存主鍵鍵值,故主鍵儘可能選擇較短的數據類型。
HASH索引於BTREE索引:

  1. 只能使用=和<=>進行匹配。
  2. 無法進行排序優化。

第11章 視圖

不可更新的視圖:

  1. 包含聚合函數(SUM, MIN, MAX, COUNT等),DISTINCT, GROUP BY, HAVING, UNION, UNION ALL語句。
  2. 常量視圖。
  3. SELECT包含子查詢。
  4. FROM一個不能更新的視圖。
  5. WHERE中的子查詢引用了FROM中的表。

WITH CASCADED | LOCAL CHECK OPTION: 滿足該視圖即可更新 | 滿足所有相關視圖纔可更新。

SHOW TABLE STATUS FROM DB LIKE PATTERN.
SHOW CREATE VIEW VIEW_NAME
information_schema.views

第12章 存儲過程和函數

創建二者需要CREATE ROUTINE權限,修改需要ALTER ROUTINE權限,執行需要EXECUTE權限。
DELIMITER $$可修改語句結束標示。
查看方式與VIEW的查看方式類似。

  1. 事件調度器
  2. 流程控制(IF, CASE, REPEAT等)
  3. 光標
  4. 條件和處理
  5. 變量

第13章 觸發器

第14章 事務控制與鎖定語句

(UN)LOCK TABLE.
事務控制中SAVEPOINT的使用。
分佈式事務命令XA,prepare狀態下出現異常,則 binlog不會存在記錄,會使數據不一致。數據完整性要求不高時可使用。

第15章 SQL中的安全問題

防止SQL注入:

  1. 對用戶輸入進行轉義,一般的ORM框架可實現。
  2. 使用數據庫提供的轉換函數,quote等。
  3. 代碼敏感字符攔截。

SQL MODE

不同嚴格程度SQL語法和數據校驗。

SQL_MODE的常見功能:

  1. ANSI和TRADITIONAL: 允許和不允許插入非法時間值,MOD(X, 0)等。
  2. NO_BACKSLASH_ESCAPES: 視 爲普通字符。
  3. PIPES_AS_CONCAT: 視 || 爲字符串連接符使其不報錯。

常用SQL_MODE:

  1. ANSI: 寬鬆模式。
  2. STRICT_TRANS_TABLE: 嚴格模式。
  3. TRADITIONAL: 嚴格中的嚴格模式。

第16章 SQL分區

SHOW VARIABLES LIKE ‘partition’ 查看是否支持分區。
創建表時使用partition關鍵詞設置分區。
若有主鍵或唯一鍵,則分區關鍵詞必須是其中之一。
分區類型:

  1. RANGE: 按照取值範圍進行分區。NULL值做最小值處理。
  2. LIST: 利用數組值包含關係進行分區。NULL值如果被允許則必須在候選項中。
  3. COLUMNS: 多列般的RANGE AND LIST(RANGE COLUMNS AND LIST COLUMNS關鍵詞)。
  4. HASH: 常規HASH, 列關鍵詞 % 分區數量確定分區號。當需要增加分區時,已有數據遷移代價太大。LINER HASH, 使用更加複雜的算法進行分區使上述得到優化,但使數據分佈不均勻。二者均只支持整數分區(非整數列需要使用函數轉換)。NULL被視爲0值。
  5. KEY: 支持除BLOB和TEXT外的所有類型列作爲分區鍵。可不指定分區鍵,默認使用主鍵或唯一索引列(非空纔不會報錯)。支持多分區鍵,同樣也可以使用LINIRE KEY。NULL被視爲0值。

## 子分區(複合分區)
可對每個分區(RANGE AND LIST)進行再分區(HASH AND SET)。
## 分區管理

SQL優化

  1. SHOW (global | session) STATUS LIKE (Com_% | Innodb_rows% | Connections | Uptime | Slow_queries) 查看命令執行DASHBOARD。
  2. —log-slow-queries=file_name 記錄慢查詢。
  3. Using explain or desc to analytic sql.
  • select_type: SIMPLE 簡單表,PRIMARY: 外層查詢,UNION: UNION中的第二個或後面的查詢,SUBQUERY: 子查詢的第一個SELECT。
  • type:訪問類型,性能由高到低爲:

    • NULL: 無需訪問即可得出答案。
    • const/system: 僅一個匹配行,如單表查詢中使用主鍵和唯一鍵進行查詢。
    • eq_ref: 多表連接中使用主鍵或唯一鍵進行關鍵。
    • ref: 使用非唯一索引或唯一索引的前綴匹配。
    • ref_or_null: 查詢條件中包含對NULL的查詢。.
    • index_merge: 索引合併優化。
    • unique_subquery: in後面是一個查詢主鍵字段的子查詢。
    • index_subquery: in後面是一個針對非唯一索引字段的子查詢。
    • range: 索引範圍掃描,如對於索引列的大於小於between操作。
    • index: 索引全掃描,遍歷整個索引查詢匹配到的行。如查詢一個被索引的列。
    • ALL: 全表掃描。
  1. explain extended and then show warnings to show the actual SQL that has been executed after SQL optimization. EXPLAIN PARTITIONS 可用於查看語句將操作的分區。
  2. SHOW PROFILE(S):
  • SELECT @@have_profiling 查看是否支持profile。
  • SELECT @@profiling 查看是否開啓此功能(默認關閉)。
  • SET profiling=1 開啓此功能。
  • SHOW PROFILES查看歷史SQL及耗時。
  • SHOW PROFILE (ALL | CPU | block io | source/源文件 etc.) ROR QUERY x 查看某個SQL的各階段耗時。

    • sending data 狀態表示開始訪問數據行並把結果返回,往往需要大量磁盤IO,故往往是最耗時的。
  • INFORMATION_SCHEMA.PROFILING 存有profiling信息。
  1. trace: 查看優化依據。
  • SET OPTIMIZER_TTACE=“enabled=on”, END_MARKER_IN_JSON=on;
  • SET OPTIMZER_TRACE_MAX_MEM_SIZE=10000000
  • INFORMATION_SCHEMA.OPTIMIZER_TRACE

索引

  • B-Tree: 廣泛使用。B代表balanced,其非二叉樹。
  • HASH: 僅Memory引擎支持。無法用在範圍查找。
  • R-Tree: 空間索引,MyISAM的一個特殊索引類型,主要用於地理空間數據類型。
  • Full-text: 全文索引。
前綴索引在Order By和Group By時無法使用。且無法實現覆蓋索引掃描。

Using index: 覆蓋索引掃描。所選擇的字段即爲索引,無需額外訪問。
Using where: 根據索引回表訪問數據。需要額外數據訪問或篩選。
Using index condition: 使用ICP(Index Condition Pushdown)的特徵,某些情況下無需訪問數據後篩選。

無法使用索引:

  1. LIKE “%xx”。
  2. 存在數據類型隱式轉換。如last_name=1
  3. 複合索引不包含最左邊列,即不滿足最左原則。
  4. MySQL估計使用索引比全表掃描更慢。比如last_name LIKE “T%”。使用trace可查看依據。
  5. OR左側有索引,右側無索引,涉及的索引則均不會被使用。(反正都要全表掃描,沒必要多一次索引掃描增加IO訪問)

SHOW STATUS LIKE “Handler_read%”: key表一個行被索引值讀的次數,越高越好。rnd_next表數據文件中讀下一行的請求數,越低越好。

定期檢查表: (analyze | check) table payment.
定期優化表: 若刪除了表的一大部分(另可使用alter table payment engine=innodb回收不用的空間),對含有可變長度行(VARCHAR, TEXT, BLOB等)的表進行了很多更改,應使用optimize table payment

常用優化

  • 大批量插曲數據

    • 文本數據採用load data infile 方式導入。
    • SET (UNIQUE_CHECKS | AUTOCOMMIT) =0。
  • 優化ORDER BY
    Using index: 有序索引順序掃描直接返回有序結果。select if from a order by id;
    Using filesort: 對返回的數據進行排序。不是通過索引直接返回排序結果的排序都叫filrsort,即時使用索引列排序依然會出現Using filesort. select * from a order by id; more puzzles...

    where and order by 使用相同的索引並且order by的順序與索引順序相同且排序均爲升序或降序。
    sort_buffer_size: 線程獨佔。
    max_length_for_sort_data: 若讀取的字段總大小小於此值,則一次讀取滿足條件的所有行,然後在排序區sort buffer中排序後直接輸出結果,內存消耗較大但效率高。否則僅取出排序字段和指針進行上述操作,若sort buffer不夠,則在臨時表中存儲排序結果。排序後根據指針回表讀取記錄。

  • GROUP BY

    • 在其後主動添加ORDER BY NULL可取消其默認的排序行爲,增加效率。
  • 嵌套查詢

    • 沒有連接查詢快
  • OR
  • 分頁

    • 根據索引查出滿足條件的所有行的某個字段後連表。
  • 使用SQL提示

    • SELECT SQL_BUFFER_RESULTS FROM table_name: 生成臨時結果集,可釋放鎖慢慢將數據回傳給客戶端。
    • use index: 指定希望MySQL去參考的索引。
    • ignore index: 忽略某些索引。
    • force index:

ORDER BY RAND()實現隨機排序。
WITH ROLLUP與ORDER BY互斥。
BIT_AND(),BIT_OR()聚合函數進行位運算。

第19章 優化數據庫對象

SELECT * FROM table PROCEDURE ANALYSE(): 讓MySQL根據已存在的數據特徵給出優化建議。
數據拆分: 垂直拆分,不常用列單獨存儲。水平拆分,不同時期數據於不同表或分區存儲。
逆規範化: 增加冗餘列。組新表。
維護數據完整性: 定時任務,觸發器。
使用中間表提高統計效率。

第20章 鎖

MyISAM, MEMORY: 表級鎖。開銷小,加鎖快,粒度大。適合以查詢爲主,只有少量按索引條件更新數據的應用,如WEB。
InnoDB: 行級鎖,也支持表級鎖。開銷大,加鎖慢,粒度小。併發度高。適合有大量按索引條件併發進行少量數據更新,同時又有併發查詢需求的應用如在在線事務系統。
DBD: 頁級鎖,也支持表級。介於上二者之間。

表鎖(MyISAM)

SHOW STATUS LIKE ‘table%’查看錶鎖爭用情況。
讀鎖可存在多個,有且只有一個寫鎖,寫鎖與讀鎖不共存。
LOCK TABLE(S) table (as t) WRITE給表加鎖。表使用別名時需要爲不同的別名都加鎖。
UNLOCK TABLES釋放鎖。

在自動加鎖的情況下,MyISAM總是直接獲取SQL所需要的所有鎖,所以MyISAM不會出現死鎖。
系統變量 concurrent_insert:
  1. 0: 不允許併發插曲
  2. 1: 如果MyISAM表中間沒有空洞,即沒有刪除行,允許讀鎖存在時另一進程在表尾插入記錄。MySQL的默認值,OPTIMIZE TABLE可整理空間碎片。
  3. 2: 不管有無空洞均允許表尾插入。

鎖調度機制: 等待隊列中有寫鎖請求頁給予最高優先級而與入列順序無關。這也是MyISAM不適合有大量更新和查詢操作的應用的原因。各類操作優先級可設定。maz_write_lock_count可設定當讀請求超過一定值後降低寫操作的優先級。

InnoDB鎖問題

於MyISAM: 有了事務和行級鎖。

併發事務帶來的問題:

  1. 更新丟失
  2. 贓讀
  3. 不可重複讀: 二次讀時數據被更改或刪除。
  4. 幻讀: 二次讀時有新的滿足查詢條件的結果。

SELECT @@tx_isolation
事務隔離級別:

  1. 未提交讀: 讀未提交不讀已損壞。
  2. 已提交讀: 讀已提交。
  3. 可重複讀:
  4. 可序列化

SHOW STATUS LIKE “innodb_row_lock%”查看行鎖爭用情況。
SELECT * FROM information_schema.innodb_locks查看鎖等待情況。
通過InnoDB Monitors觀察鎖衝突情況。(show engine innodb status)

InnoDB加鎖方法

SELECT ... LOCK IN SHARE MODE.
SELECT ... FOR UPDATE.

行鎖情形:

  1. record lock: 對索引項加鎖
  2. gap lock: 對記錄之間的間隙加鎖,主要作用於範圍篩選。可解決幻讀問題。對於不存在的記錄,也會使用此鎖,故不存在的記錄也會存在衝突。
  3. next-key lock: 對記錄及其前後間隙加鎖。

死鎖:

  • 如果一個事務先對某行加共享鎖(SSLECT)後又需要更新該行數據(UPDATE等),高併發環境下很可能會造成死鎖。
  • InnoDB的行鎖時通過給索引上的索引項加鎖實現的,如果沒有索引,將通過隱藏的聚簇索引來對記錄加鎖。如果不通過索引條件檢索數據,InnoDB將對所有記錄加鎖(表鎖)。
  • InnoDB是針對索引項加鎖,故如果使用同一索引鍵操作不同行的記錄,也會出現行衝突。
  • 通過不同索引鍵獲取同一記錄的鎖也會衝突。
  • 是否使用索引是MySQL通過計算不同執行計劃的代價決定的,所以分析鎖衝突時,有時需要檢查SQL的執行計劃。

BINLOG, 執行Log.

set innodb_locks_unsafe_for_binlog=‘on’: 在UPDATE INTO target ... SELECT ...source和CREATE TABLE target ... SELECT ... source時不給source加鎖。這會造成併發更新source相關字段時(不會被阻塞),binlog中日誌順序出現錯誤,數據恢復和複製會出現主從不一致的情況。這些SQL稱爲不確定的SQL(unsafe SQL)。默認爲off,但對於複雜查詢可能會有嚴重的性能問題,故可以使用導出文件再加載文件的方式。

複製模式

SET SESSION ISOLATION LEVEL SERIALIZABLE: 動態改變隔離級別。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章