日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL学习笔记-从基础到进阶

發布時間:2024/3/13 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL学习笔记-从基础到进阶 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MySQL自學筆記

  • MySQL
    • 基礎
      • SQL
        • SQL通用語法
        • SQL分類
        • DDL數據操作
        • 數據類型
        • DML數據操作
        • DQL數據操作
        • DCL數據控制
        • 函數
        • 約束
        • 多表查詢
        • 事務
    • 進階
      • 存儲引擎
      • **索引**(重點)
      • SQL優化
      • 視圖
      • 存儲過程
      • InnoDB引擎
        • 邏輯存儲結構
        • 架構
          • 內存架構
          • 磁盤架構
          • 后臺線程
      • 事務原理
      • MVCC

MySQL

課程連接

數據庫:存儲數據的倉庫,數據是有組織的進行存儲(DataBase, DB)

數據庫管理系統:操縱和管理數據庫的大型軟件(DataBase Management System, DBMS)

SQL : 操作關系型數據庫的編程語言,定義了一套操作關系型數據庫的統一標準(Structured Query Language, SQL)

基礎

  • 關系型數據庫(RDBMS)

    • 概念:建立在關系模型基礎上,有多張相互連接的二維表組成的數據庫
    • 使用表存儲數據,格式統一,便于維護
    • 使用SQL語言操作,標準統一,使用方便
  • MySQL啟動

net start mysql80net stop mysql80 * MySQL客戶端連接 mysql [-h 127.0.0.1] [-p 3306] -u root -p
  • MySQL數據模型
    • 數據庫管理系統 --> 數據庫 --> 二維表

SQL

SQL通用語法

  • SQL語句可以單行或多行書寫,以分號結尾
  • SQL語句可以使用空格/縮進來增強語句的可讀性
  • MySQL數據庫的SQL語句不區分大小寫,關鍵字建議使用大寫
  • 注釋
    • 單行注釋:–或#
    • 多行注釋:/* */

SQL分類

  • DDL (Data Definition Language) 數據定義語言,用來定義數據庫對象(數據庫、表、字段等)
  • DML(Data Manipulation Language) 數據操作語言,用來對數據庫表中的數據進行增刪改查
  • DQL(Data Query Language) 數據查詢語言,用來查詢數據庫中標的記錄
  • DCL(Data Control Language) 數據控制語言,用來創建數據庫用戶、控制數據庫的訪問權限

DDL數據操作

  • 查詢
#查詢所有數據庫SHOW DATABASES;#查詢當前數據庫SELECT DATABASE();
  • 創建
CREATE DATABASE [IF NOT EXISTS] 數據庫名 [DEFAULT CHARSET 字符集(UTF8MB4)] [COLLATE 排序規則];
  • 刪除
DROP DATABASE [IF EXISTS] 數據庫名;
  • 使用
USE 數據庫名;
  • 表操作-查詢
#查詢當前數據庫所有表show tables;#查詢表結構desc 表名;#查詢指定表的建表語句show create table 表名;
  • 表操作-創建
create table 表名(字段1 字段1類型 [comment 字段1注釋],字段2 字段2類型 [comment 字段2注釋],字段3 字段3類型 [comment 字段3注釋],......字段n 字段n類型 [comment 字段n注釋])[comment 表注釋];#注意:[..]為可選參數,最后一個字段結束沒有逗號
  • 表操作-修改
#添加字段alter table 表名 add 字段名 類型(長度)[comment 注釋] [約束];#修改字段數據類型 alter table 表名 modify 字段名 新數據類型(長度);#修改字段名和字段類型alter table 表名 change 舊字段名 新字段名 類型(長度) [comment 注釋] [約束];#刪除字段alter table 表名 drop 字段名;#修改表名alter table 表名 rename to 新表名;#刪除表drop table [if exists] 表名;#刪除指定表,并重新創建該表truncate table 表名;

數據類型

  • 數據類型-數值類型

  • 數值類型-字符類型

  • 數值類型-日期類型

DML數據操作

  • INSERT添加數據
#給指定字段添加數據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修改數據
#修改數據UPDATE 表名 SET 字段名1 =1, 字段名2 =2,...[WHERE 條件];#修改語句條件可以有或沒有,如果沒有默認修改整張表的所有數據#刪除數據DELETE FROM 表名 [WHERE 條件];#DELETE語句的條件可以有,也可以沒有,如果沒有條件,則刪除整張表的數據#DELETE語句不能刪除某一字段的值(可以使用UPDATE)

DQL數據操作

  • 基本查詢
#查詢多個字段SELECT 字段1, 字段2... FROM 表名;SELECT * FROM 表名;#設置別名 AS可省略SELECT 字段1[AS 別名1], 字段2[AS 別名2]...FROM 表名;#去除重復記錄SELECT DISTINCT 字段列表 FROM 表名;
  • 條件查詢
SELECT 字段列表 FROM 表名 WHERE 條件列表;#條件BETWEEN [MAX] AND [MIN]; --在某一范圍內,相當于 MIN <= AND <=MAXVALUE1 IN(VALUE2, VALUE3,); --相當于 VALUE1 = VALUE2 OR VALUE1 = VALUE3IS NULLIS NOT NULL; --查詢為NULL和不為NULLLIKE '_ _'; --查詢兩個字符的字段LIKE '%X'; --查詢最后為X的字段



  • 聚合函數
#將一列數據作為一個整體,進行縱向計算的函數-聚合函數count --統計數量max --最大值min --最小值avg --平均值sum --求和# NULL值不參與函數運算#語法SELECT 聚合函數(字段列表) FROM 表名;
  • 分組查詢
SELECT 字段列表 FROM 表名 [WHERE 條件] GROUP BY 分組字段名 [HAVING 分組后過濾條件];#WHERE 與 HAVING區別#執行時機不同:WHERE是分組前進行過濾,不滿足條件,不參與分組。HAVING是分組之后對結果進行過濾。#判斷條件不同:WHERE不能對聚合函數進行判斷,HAVING 可以。#執行順序:WHERE > 聚合函數 > HAVING#分組后一般查詢分組字段和聚合函數,查詢其他字段沒有意義
  • 排序查詢
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1, 字段2 排序方式2;#排序方式ASC 升序 默認值DESC 降序#注意:如果是多字段排序,當第一個字段值相同時,才會根據第二個字段進行排序
  • 分頁查詢
SELECT 字段列表 FROM 表名 LIMIT 起始索引,查詢記錄數;#注意:起始索引從0開始,起始索引 = (查詢頁碼-1)*每頁顯示記錄數#分頁查詢是數據庫的方言,不同的數據庫有不同的實現,MySQL中是LIMIT#如果查詢的是第一頁數據,起始索引可以省略,直接簡寫為 LIMIT 10
  • 執行順序
#編寫順序SELECT -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY -> LIMIT #執行順序FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY -> LIMIT

DCL數據控制

  • 用戶管理
#查詢用戶USE mysql;SELECT * FROM user;#創建用戶 CREATE USER '用戶名'@'主機名' IDENTIFIED BY '密碼';#修改用戶密碼ALTER USER '用戶名'@'主機名' IDENTIFIED WITH mysql_native_password BY '新密碼';#刪除用戶DROP USER '用戶名'@'主機名';#注意:主機名可以使用%通配#這類操作開發人員操作較少,主要是DBA(Database Adminstrator 數據管理員)使用。
  • 權限控制
#查詢權限SHOW GRANTS FOR '用戶名'@'主機名';#授予權限GRANT 權限列表 ON 數據庫名.表名 TO '用戶名'@'主機名';#撤銷權限REVOKE 權限列表 ON 數據庫名。表名 FROM '用戶名'@'主機名';

函數

  • 字符串函數
SELECT 函數(參數);

  • 數值函數

  • 日期函數

  • 流程函數

約束

  • 概念:約束是作用于表中字段上的規則,用于限制存儲在表中的數據

  • 目的:保證數據庫中數據的正確、有效性和完整性

  • 分類:

AUTO_INCREMENT 使約束字段遞增
  • 注意:約束是作用于表中字段上,可以在創建表/修改表時添加約束

  • 外鍵約束:外鍵用來讓兩張表的數據之間建立連接,從而保證數據的一致性和完整性

#添加外鍵CREATE TABLE 表名(字段名 數據類型,...[CONSTRAINT] [外鍵名稱] FOREIGN KEY(外鍵字段名) REFERENCES 主表(主表列名) );ALTER TABLE 表名 ADD CONSTRAINT [外鍵名稱] FOREIGN KEY(外鍵字段名) REFERENCES 主表(主表列名);#刪除外鍵ALTER TABLE 表名 DROP FOREIGN KEY 外鍵名稱;
  • 外鍵約束刪除/更新行為
ALTER TABLE 表名 ADD CONSTRAINT [外鍵名稱] FOREIGN KEY(外鍵字段名) REFERENCES 主表(主表列名) ON UPDATE 行為 ON DELETE 行為;# NO ACTION 、RESTRICT 默認行為

多表查詢

  • 多表關系
#一對多(多對一) 如員工與職位的關系實現:在多的一方建立外鍵,指向一的一方的主鍵#多對多 如學生與課程的關系實現:建立第三張中間表,中間表至少包含兩個外鍵,分別關聯兩方主鍵#一對一 多用于單表拆分實現:在任意一方加入外鍵,關聯另外一方的主鍵,并且設置外鍵為唯一的(UNIQUE)
  • 多表查詢
#連接查詢 注意消除笛卡爾積的條件內連接:相當于查詢A、B交集部分數據##隱式內連接SELECT DISTINCT 字段列表 FROM1,表2 WHERE 連接條件...;DISTINCT對查詢結果去重##顯式內連接SELECT 字段列表 FROM1 [INNER] JOIN2 ON 連接條件...;外連接:左外連接:查詢左表所有數據,以及兩張表交集部分數據SELECT 字段列表 FROM1 LEFT [INNER] JOIN2 ON 連接條件... [WHERE 條件];右外連接:查詢右表所有數據,以及兩張表交集部分數據SELECT 字段列表 FROM1 RIGHT [INNER] JOIN2 ON 連接條件... [WHERE 條件];自連接:當前表與自身的連接查詢,自連接必須使用表別名#聯合查詢對于UNION查詢,是把多次查詢的結果合并起來,形成一個新的查詢結果集SELECT 字段列表 FROM 表A ...UNION[ALL]SELECT 字段列表 FROM 表B...;注意:對于聯合查詢的多張表的列數必須保持一致,字段類型也需要保持一致UNION ALL會將全部的數據直接合并在一起,UNION會對合并之后的數據去重 #子查詢SQL語句中嵌套SELECT語句,稱為嵌套查詢,又稱為子查詢SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);子查詢外部的語句可以是INSERT/ UPDATE / SELECT / DELETE 的任何一個根據子查詢結果不同,分為:標量子查詢(子查詢結果為單個值)列子查詢(子查詢結果為一列)行子查詢(子查詢結果為一行)表子查詢(子查詢結果為多行多列)根據子查詢位置,分為:WHERE之后、FROM之后、SELECT之后。

事務

  • 事務是一組操作的集合,它是一個不可分割的工作單位,事務會把所有操作作為一個整體一起向系統提交或撤銷操作請求,這些操作要么同時成功,要么同時失敗

  • 默認MySQL的事務是自動提交的

  • 事務操作

#查看/設置事務提交方式SELECT @@autoaommit;SET @@autocommit = 0; -- 0 手動提交 1 自動提交#提交事務COMMIT;#回滾事務ROLLBACK;#方式二 不用設置系統參數#開啟事務START TRANSACTIONBEGIN#提交事務COMMIT;#回滾事務ROLLBACK;
  • 事務四大特性
原子性(Atomicity):事務是不可分割的最小操作單元,要么全部成功,要么全部失敗一致性(Consistency):事務完成時,必須使所有的數據保持一致狀態隔離性(Isolation):數據庫系統提供的隔離機制,保證事務在不受外部并發操作影響的獨立環境下運行持久性(Durability):事務一旦提交或回滾,他對數據庫中的數據的改變是永久的
  • 并發事務問題
臟讀:一個事務讀取到另外一個事務還沒有提交的數據不可重復讀:一個事務先后讀取同一條記錄,但兩次讀取的數據不同,成之為不可重復讀幻讀:一個事務按照條件查詢數據時,沒有對應的數據行,但是在插入數據時,又發現這行數據已經存在,好像出現了’幻影‘
  • 并發事務隔離級別

上表從上到下隔離級別越來越高,性能越來越差,安全性越來越高--查看事務隔離級別SELECT @@TRANSACTION_ISOLATION;--設置事務隔離級別 SESSION[當前窗口有效] GLOBAL[所有窗口有效]SET[SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {隔離級別}

進階

存儲引擎

  • MySQL體系結構

--連接層:最上層是一些客戶端和連接服務,主要完成一些類似于連接處理、授權認證、及相關的安全方案。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限--服務層:第二層架構主要完成大多數的核心服務功能,如SQL接口,并完成緩存的查詢,SQL的分析和優化,部分內置函數的執行。所有跨存儲引擎的功能也在這一層實現,如過程、函數等--引擎層:存儲引擎真正的負責了MySQL中數據的存儲和提取,服務器通過API和存儲引擎進行通信。不同的存儲引擎具有不同的功能,這樣我們可以根據自己的需要,來選取合適的存儲引擎--存儲層:主要將數據存儲在文件系統之上,并完善與存儲引擎的交互
  • 存儲引擎
#指定存儲引擎 默認INNODBCREATE TABLE 表名()ENGINE = 存儲引擎 [COMMENT 表注釋];#查詢數據庫支持的引擎SHOW ENGINE;
  • 存儲引擎特點
#innoDBinnoDB是一種兼顧高可靠性和高性能的通用存儲引擎,在MySQL5.5之后,是默認存儲引擎#特點DML操作遵循ACID模型,支持事務行級鎖,提高并發訪問性能支持外鍵FOREIGN KEY約束,保證數據的完整性和正確性#文件xxx.idb: xxx表示表名,innoDB引擎的每張表都會對應這樣一個表空間文件,存儲該表的表結構(frm sdi)、數據和索引。參數:innodb_file_per_table -- 是否開啟一張表對應一個表空間文件

#MySAM早期的默認存儲引擎#特點不支持事務,不支持外鍵支持表鎖,不支持行鎖訪問速度快#文件xxx.sdi --存儲表結構信息xxx.MYD --存儲數據xxx.MYI --存儲索引#Memory其數據表存儲在內存中,由于受到硬件問題、或斷點問題的影響,只能將這些表作為臨時表或緩存使用#特點內存存放hash索引#文件xxx.sdi

  • 存儲引擎選擇

索引(重點)

  • 索引(index)是幫助MySQL高效獲取數據的數據結構(有序)。在數據之外,數據庫系統還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法,這種數據結構就是索引。

  • 優缺點

  • 索引結構

MySQL的索引是在存儲引擎層實現的,不同的存儲引擎有不同的結構,主要包含一下幾種:

  • B-Tree(多路平衡查找樹)

二叉樹缺點:順序插入時,會形成一個鏈表,查詢性能大大降低。大數據量情況下,層級較深,檢索速度慢

紅黑樹:大數據量情況下,層級較深,檢索速度慢

B-Tree:以一顆最大度數(max-degree)為5階的B-Tree為例(每個節點最多存儲4個key,5個指針),樹的度數指的是一個節點的子節點個數

  • B+Tree

? 與B-Tree區別:所有的數據都會出現在葉子節點;葉子節點形成一個單向列表。

  • MySQL索引數據結構對經典B+Tree進行了優化,在原B+Tree的基礎上,增加一個指向相鄰葉子節點的鏈表指針,就形成了帶有順序指針的B+Tree,提高區間訪問的性能

  • Hash索引

哈希索引就是采用一定的hash算法,將鍵值換算成新的hash值,映射到對應的槽位上,然后存儲在hash 表中。如果兩個(或多個)鍵值,映射到一個相同的槽位上,他們就產生了hash沖突(hash碰撞),可以通過鏈表解決。

特點:hash索引只能用于對等比較(=、in),不支持范圍查詢(between、> 、< ...)無法利用索引完成排序操作;查詢效率高,通常只需要一次檢索就可以了,效率通常高于B+Tree索引

? 在MySQL中,支持hash索引的值Memory引擎,而innoDB中具有自適應hash功能,hash索引是存儲引擎根據B+Tree索引在指定條件下自動構建的。

  • 為什么InnoDB存儲引擎選擇使用B+Tree索引結構?

    1、相對于二叉樹,層級更少,搜索效率高

    2、對于B-Tree,無論是葉子節點還是非葉子節點,都會保存數據,這樣導致一頁存儲的鍵值減小,指針跟著減小,同樣保存大量的數據,只能增加樹的高度,導致性能降低

    3、相對于Hash索引,B+Tree支持范圍匹配和排序操作

  • 索引分類

在InnoDB引擎中,根據索引的存儲形式,又可以分為一下兩種:

  • 聚集索引選取規則

    1、如果存在主鍵,主鍵索引就是聚集索引

    2、如果不存在主鍵,將使用第一個唯一索引作為主鍵索引

    3、如果表沒有之間,或沒有合適的唯一索引,則引擎會自動生成一個rowid作為隱藏的聚集索引

回表查詢:先走二級索引找到對應的主鍵值,再根據主鍵值走聚集索引找到對應的行數據
  • 索引語法
--創建索引CREATE [UNIQUE | FULLTEXT] INDEX index_name ON table_name (index_col_name,...);--查看索引SHOW INDEX FROM table_name;--刪除索引DROP INDEX index_name ON table_name;
  • SQL性能分析
--執行頻次MySQL客戶端連接成功后,通過下面指令可以提供服務器狀態信息。查看當前數據庫的INSERT\UPDATE\DELETE\SELECT的訪問頻次: SHOW [SESSION|GLOBAL] STATUS LIKE 'Com_____'; --Com下劃線,幾個表示幾個字符 --慢查詢日志慢查詢日志記錄了所有執行時間超過指定參數(long_query_time 默認10秒)的所有SQL語句的日志。MySQL的慢查詢日志默認沒有開啟,需要在MySQL的配置文件(/etc/mysql/mysql.conf.d/mysqld.cnf)中配置如下信息,可以使用 vi/vim修改:#開啟MySQL慢查詢日志開關slow_query_log = 1;#設置慢查詢日志的時間,超過指定時間,就視為慢查詢,記錄在慢查詢日志long_query_time = 2;#慢查詢日志文件位置( /var/log/mysql/mysql-slow.log)slow_query_log_file = /var/log/mysql/mysql-slow.log--查看慢查詢日志是否開啟SHOW VARIABLES LIKE 'slow_query_log';--查看慢查詢日志實時內容tail -f mysql-slow.log--其他ubuntu常用指令重啟MySQL systemctl restart mysql關閉MySQL systemctl stop mysql --profile詳情show profiles能夠在做SQL優化時幫助我們了解時間都耗費到哪里去了。通過have_profiling參數,能夠看到當前MySQL是否支持profile操作:SELECT @@have_profiling;--默認profiling是關閉的,可以通過set語句在session(當前會話)/global(全局)級別開啟profiling:SELECT @@profiling; --查看是否開啟SET profiling = 1;--查看每一條SQL指令執行耗時情況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/DESCEXPLAIN SELECT 字段列表 FROM 表名 WHERE 條件;

--各字段含義id: SELECT查詢的序列號,表示查詢中執行SELECT子句或者是操作表的順序(id相同,執行順序從上到下;id不同,值越大,越優先執行);select_type: 表示SELECT的類型,常見的取值有SIMPLE(簡單表,即不使用表連接或者子查詢)、PRIMARY(主查詢,即外層查詢)、UNIONUNION中第二個或者后面的查詢語句)、SUBQUERY(SELECT/WHERE之后包含了子查詢)等;type: 表示連接類型,性能由好到差的連接類型為NULL 、system 、const 、eq_ref、ref、range、index、all;possible_key: 顯示可能應用在這張表上的索引,一個或多個;key: 實際使用的索引,如果為NULL,則沒有使用索引;key_len: 表示索引中引用的字節數,該值為索引字段最大可能長度,并非實際使用長度,在不損失精確性的前提下,長度越短越好;rows: MySQL認為必須要執行查詢的行數,在innoDB引擎的表中,是一個估計值,可能并不總是準確的;filtered: 表示返回結果的行數占需讀取行數的百分比,filtered的值越大越好;Extra: 額外的信息。
  • 索引使用

    • 最左前綴法則:如果索引了多列(聯合索引),要遵循最左前綴法則。其指的是查詢從索引的最左列開始,并且不跳過索引中的列,與索引時字段的位置沒有關系。如果跳過某一列,索引將部分失效(后面的字段索引失效),這個與創建索引時的順序有關。
    • 范圍查詢:聯合索引中,出現范圍查詢(>,<),范圍查詢右側的列索引失效。盡量使用(>=,<=)。
    • 索引列運算:不要在索引列上進行運算操作,索引將失效。
    • 字符串不加引號:字符串類型字段使用索引時,如果不加引號,索引將失效。
    • 模糊查詢:如果僅僅是尾部模糊匹配(like ‘xx%’),索引不會失效。如果頭部模糊匹配(like ‘%xx’),索引失效。
    • or 連接條件:用or分割開的條件,如果or前的條件中的列有索引,而后面的列中沒有索引,那么涉及的索引都會失效。即使左側有索引,右側有聯合索引,右側相當于沒有索引,依然or兩側索引失效。
    • 數據分布影響:如果MySQL評估使用索引比全表掃描更慢,則不使用索引。
  • SQL提示

--SQL提示,是優化數據庫的一個重要手段,簡單來說,就是在SQL語句中加入一些人為的提示來達到優化操作的目的use index: 建議使用某個索引,最終取決于MySQLexplain select 字段列表 from 表名 use index(索引名) where 條件;ignore index: 不要使用某個索引explain select 字段列表 from 表名 ignore index(索引名) where 條件;force index: 必須使用某個索引explain select 字段列表 from 表名 force index(索引名) where 條件;
  • 覆蓋索引
覆蓋索引:在查詢使用了索引,并且需要返回的字段或列,在該索引中都能找到。盡量使用覆蓋索引,減少select *--extra 信息using index condition :查找使用了索引,但需要回表查詢數據using where;using index: 查找使用了索引,但是需要的數據都在索引列中能找到,所以不需要回表查詢
  • 前綴索引
當字段類型為字符串(varchar,text等)時,有時候需要索引很長的字符串,這會讓索引變得很大,查詢時,浪費大量的磁盤IO,影響查詢效率。此時可以只將字符串的一部分前綴建立索引,這樣大大節約索引空間,提升效率。--語法:create index idx_name on table_name(column(n));--前綴長度可以根據索引的選擇性來決定,而選擇性是指不重復的索引值和數據表的記錄總數的壁紙,索引選擇性越高,查詢效率就越高,唯一索引的選擇性為1。select count(distinct 字段) /count(*) from 表名;select count(distinct substring(字段,start,length )) /count(*) from 表名;
  • 單列索引與聯合索引
單列索引:一個索引只包含單個列聯合索引:一個索引包含多列如果存在多個查詢條件,建議建立聯合索引,使用時注意最左前綴法則
  • 索引設計原則

SQL優化

  • insert優化
--批量插入insert into table_name values(),(),().....;--手動提交事務start transaction;insert into ...;...insert into ...;commit;--主鍵順序插入主鍵數據順序插入要比亂序效率高--大批量插入數據如果一次性插入大量數據,使用insert性能較低,此時可以使用MySQL數據庫提供的load指令進行插入:#客戶端連接服務器時,加上參數 --local-infilemysql --local-infile -u root -p#設置全局參數 local-infile為1,開啟從本地加載文件導入數據的開關select @@local-infile; -- 查看狀態set local-infile = 1; --開啟#執行load指令將數據加載到表結構中load data local infile '文件位置' into table '表名' fields terminated by '數據分隔符' lines terminated by '換行符 \n';
  • 主鍵優化
--數據組織方式InnoDB存儲引擎中,表數據都是根據主鍵順序組織存放的,這種存儲方式的表稱為索引組織表(index organized table,IOT)--頁分裂頁可以為空,也可以存儲一半,也可以存儲100%。每個頁包含2-N行數據(如果一行數據過大,會行溢出),根據主鍵排列。至少包含兩行數據的原因是,如果只存放一列,而數據又是順序組織存放,就形成了鏈表如果主鍵數據亂序存放,可能發生頁分裂現象--頁合并當刪除一行記錄時,實際上記錄并沒有被物理刪除,只是記錄被標記為刪除并且它的空間變得允許被其他記錄聲明使用。當頁中刪除的記錄達到MERGE_THRESHOLD(默認為頁的50%)InnoDB會開始尋找最靠近的頁(前或后)看看是否可以將兩個頁合并以優化空間使用。MERGE_THRESHOLD: 合并頁的閾值,可以在創建表或創建索引時指定。--主鍵設計原則滿足業務需求的情況下,盡量降低主鍵的長度;插入數據時,盡量選擇順序插入,選擇使用auto_increment自增主鍵;盡量不要使用uuid做主鍵或者其他自然主鍵,如身份證號;業務操作時,避免對主鍵修改。
  • order by
--order by 排序Using filesort :通過表的索引或全表掃描,讀取滿足條件的數據行,然后在緩沖區sort buffer中完成排序操作,所有不是通過索引直接返回排序結果的排序都叫filesort.Using index: 通過有序索引順序掃描直接返回有序數據,這種情況為using index,不需要額外排序,效率高--優化設置根據排序字段建立合適的索引,多字段排序時,可建立聯合索引,遵循最左前綴法則;盡量使用覆蓋索引;多字段排序,一個升序一個降序,此時需要注意聯合索引在創建時的規則(asc / desc);如果不可避免出現filesort,大數據量排序時,可以適當增大排序緩沖區大小sort_buffer_size(默認256k)。
  • group by優化
在分組操作時,可以通過索引來提高效率;分組操作時,索引的使用也要滿足最左前綴法則。
  • limit優化
一般分頁查詢時,通過創建 覆蓋索引 能夠比較好提高性能,可以通過覆蓋索引加子查詢形式進行優化
  • count優化
myisam引擎把一個表的總數存在了磁盤上,因此執行count(*)的時候會直接返回這個數,效率較高innoDB引擎執行count(*)時,需要把數據一行一行地從引擎里面讀出來,然后累積計數優化思路:自己計數

  • update優化
InnoDB的行鎖是針對索引加的鎖,不是針對記錄加的鎖,并且該索引不能失效,否則會從行鎖升級為表鎖在使用update修改數據時,盡量使用索引作為條件,防止在事務并發操作時,行鎖升級為表鎖,影響運行效率

視圖

  • 定義:視圖(View)是一種虛擬存在的表。視圖中的數據并不在數據庫中實際存在,行和列數據來自定義視圖的查詢中使用的表,并且是在使用視圖時動態生成的。

  • 語法

--創建CREATE [OR REPLACE] VIEW 視圖名稱[(列名列表)] AS SELECT語句 [WITH [CASCADED | LOCAL] CHECK OPTION];--查詢查看創建視圖語句:SHOW CREATE VIEW 視圖名稱;查看視圖數據: SELECT * FROM 視圖名稱 ..;--修改1) CREATE [OR REPLACE] VIEW 視圖名稱[(列名列表)] AS SELECT語句 [WITH [CASCADED | LOCAL] CHECK OPTION];2) ALTER VIEW 視圖名稱[(列名列表)] AS SELECT語句 [WITH [CASCADED | LOCAL] CHECK OPTION];--刪除DROP VIEW [IF EXISTS] 視圖名稱,...;
  • 視圖檢查選項
--當使用WITH CHECK OPTION子句創建視圖時,MySQL會通過視圖檢查正在更改的每個行,例如插入、更新、刪除,以使其符合視圖的定義。MySQL允許基于另一個視圖創建視圖,他還會檢查依賴視圖中的規則以保持一致性。為例確定檢查范圍,MySQL提供了兩個選項:CASCADED和LOCAL,默認值為CASCADED(級聯)。--CASCADED:--基于視圖(未加檢查條件)創建視圖時沒有加檢查選項,在增刪改時不會檢查自身創建條件,但是會判斷視圖的條件,如果滿足兩個視圖的條件則結果出現在視圖中,反之不然。如果創建的視圖加上了檢查選項,不僅會檢查自身條件,還會檢查基于的視圖條件,有一個視圖不滿足條件都會報錯。--LOCAL:--基于視圖(未加檢查條件)創建視圖時沒有加檢查選項,在增刪改時不會檢查自身創建條件,但是會判斷視圖的條件,如果滿足兩個視圖的條件則結果出現在視圖中,反之不然。如果創建的視圖加上了檢查選項,只會檢查自身條件,不會檢查基于的視圖條件,不滿足創建視圖的條件才會報錯。
  • 視圖的更新
--要使視圖可更新,視圖中的行與基表中的行之間存在一對一關系。如果視圖包含一下任何選項,則該視圖不可更新:1、聚合函數或窗口函數(SUM() MIN() MAX() COUNT()2DISTINCT3、GROUP BY4、HAVING5UNION 或者 UNION ALL--視圖作用--簡單視圖不僅可以簡化用戶對數據的理解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義為視圖,從而使得用戶不必為以后的操作指定全部的條件。--安全數據庫可以授權,但不能授權到數據庫特定的行或特定的列上。通過視圖用戶只能查詢和修改他們所能見到的數據。--數據獨立視圖可以幫助用戶屏蔽真實表結構變化帶來的影響。

存儲過程

  • 定義

    存儲過程是事先經過編譯并存儲在數據庫中的一段SQL語句的集合,調用存儲過程可以簡化應用開發人員的很多工作,減少數據在數據庫和應用服務器之間的傳輸,對于提高數據處理的效率是有利的。

    存儲過程思想就是數據庫SQL語言層面的代碼封裝與重用

  • 特點

    1、封裝、復用

    2、可以接受參數,也可以返回數據

    3、減少網絡交互,提升效率

  • 語法

-- 創建CREATE PROCEDURE 存儲過程名([參數列表])BEGIN-- SQL語句END;-- 調用CALL 名稱([參數]);-- 查看-- 查詢指定數據庫的存儲過程及狀態信息SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = '數據庫名'; -- 查詢某個存儲過程的定義SHOW CREATE PROCEDURE 存儲過程名稱;-- 刪除DROP PROCEDURE [IF EXISTS] 存儲過程名稱;-- 注意在命令行中,執行存儲過程的SQL時,需要通過關鍵字 delimiter 指定SQL語句的結束符
  • 變量
-- 系統變量系統變量時MySQL服務器提供,不是用戶定義的,屬于服務器層面。分為全局變量(GLOBAL)、會話變量(SESSION)-- 查看系統變量SHOW [SESSION | GLOBAL] VARIABLES; -- 查看所有系統變量SHOW [SESSION | GLOBAL] VARIABLES LIKE '...'; -- 可以通過LIKE模糊匹配方式查找變量SHOW @@[SESSION | GLOBAL] 系統變量名; -- 查看指定變量的值-- 設置系統變量SET [SESSION | GLOBAL ] 系統變量名 =;SHOW @@[SESSION | GLOBAL] 系統變量名 =;-- 注意如果沒有指定 SESSION/ GLOBAL,默認為 SESSION;MySQL服務器重新啟動之后,所設置的全局參數會失效,如果想不失效,配置 my.cnf-- 用戶定義變量用戶定義變量是根據用戶需要自己定義的變量,用戶變量不用提前聲明,在用的時候直接用 "@變量名"使用。其作用域為當前連接會話-- 賦值SET @var_name = value, [@var_name = value],...;SET @var_name := value, [@var_name = value],...;SELECT @var_name := value, [@var_name = value],...;SELECT 字段名/聚合函數 INTO @var_name FROM 表名;-- 使用SELECT @var_name;-- 注意用戶自定義變量無需進行聲明或初始化,只不過獲取到的值為NULL-- 局部變量局部變量是根據需要定義在局部生效的變量,訪問之前,需要 DECLARE 聲明??捎米鞔鎯^程內的局部變量和輸入參數,局部變量的范圍是在其內部聲明的 BEGIN ... END-- 聲明DECLARE 變量名 變量類型 [DEFAULT value];-- 變量類型就是數據庫的字段類型-- 賦值SET 變量名 =;SET 變量名 :=;SELECT 字段名 INTO 變量名 FROM 表名 ...;
  • 參數
-- 參數類型IN :該類參數作為輸入,也就是需要調用時傳入值 ,默認OUT :該類參數作為輸出,也就是需要調用時傳出值,需要定義用戶變量接收INOUT :既可以作為輸入參數,又可以作為輸出參數-- 用法CREATE PROCEDURE 存儲過程名([IN / OUT / INOUT 參數名 參數類型])BEGINSQLEND;
  • 流程控制
-- ifIF 條件1 THEN...ELSEIF 條件2 THEN...ELSE...END IF;-- case-- 1CASE case_valueWHEN when_value1 THEN 語句[WHEN when_value1 THEN 語句]...[ELSE 語句]END CASE; -- 2CASEWHEN 條件表達式1 THEN 語句[WHEN 條件表達式2 THEN 語句]...[ELSE 語句]END CASE; -- whileWHILE 條件 DOSQL邏輯END WHILE; -- repeat 循環#先執行一次SQL語句,然后判定條件是否滿足,如果滿足則退出循環,不滿足繼續下一次循環REPEAT SQL邏輯UNTIL 條件END REPEAT; -- loop#LOOP實現簡單循環,如果不在SQL邏輯中增加退出循環的條件,可以用其來實現簡單的死循環。LOOP可以配合兩條語句使用:LEAVE -- 配合循環使用,退出循環ITERATE -- 必須用在循環中,作用是跳過當前循環剩下的語句,直接進入下一次循環[begin_label:] LOOPSQL邏輯END LOOP[end_label];LEAVE label; -- 退出指定標記的循環體ITERATE label; -- 直接進入下次循環
  • 游標
-- 定義游標(CURSOR)是用來存儲查詢結果集的數據類型,在存儲過程和函數中可以使用游標對結果集進行循環處理。游標的使用包括游標的聲明、OPEN、FETCH、和CLOSE-- 聲明游標DECLARE 游標名稱 CURSOR FOR 查詢語句;-- 打開游標OPEN 游標名稱;-- 獲取游標記錄; 定義變量,創建表格,循環獲取游標數據,并給表格插入數據FETCH 游標名稱 INTO 變量 [, 變量]..;-- 關閉游標CLOSE 游標名稱;-- 注意變量的聲明要在游標聲明之前
  • 條件處理程序
-- 條件處理程序(handler)可以用來定義在流程控制結構執行過程中遇到問題時行營的處理步驟。DECLARE handler_action HANDLER FOR condition_value [,condition_value]... 邏輯語句;-- handler_actionCONTINUE :繼續執行當前程序EXIT :終止執行當前程序-- condition_valueSQLSTATE sqlstate_value :狀態碼 如‘02000’SQLWARNING :所有以01開頭的 SQLSTATE代碼的簡寫NOT FOUND :所有以02開頭的 SQLSTATE代碼的簡寫SQLEXCEPTION :所有沒有被 SQLWARNING和 NOT FOUND捕獲的 SQLSTATE代碼的簡寫
  • 存儲函數
-- 存儲函數是有返回值的存儲過程,存儲函數的參數只能時IN類型。CREATE FUNCTION 函數名([參數列表])RETURNS type(參數列表的數據類型) [characteristic ...]BEGIN--SQLRETURN ...;END;-- characteristicDETERMINISTIC :相同的輸入參數總是產生相同的結果NO SQL :不包含SQL語句READS SQL DATA :包含讀取數據的語句,但不包含寫入數據的語句
  • 觸發器
-- 觸發器是與表有關的數據庫對象,指在insert/update/delete之前或之后,觸發并執行觸發器中定義的SQL語句集合。觸發器的這種特性可以協助應用在數據庫端保持數據的完整性,日志記錄,數據校驗等操作。-- 使用別名OLD和NEW來引用觸發器中發生的變化的記錄內容,這與其他的數據庫是相似的?,F在觸發器僅支持行級觸發,不支持語句級觸發-- 保證數據完整性、日志記錄、數據校驗-- 觸發器類型INSERT型觸發器:NEW表示將要或者已經新增的數據UPDATE型觸發器:OLD表示修改之前的數據,NEW表示將要或已經修改后的數據DELETE型觸發器:OLD表示將要或者已經刪除的數據-- 語法-- 創建CREATE TRIGGER trigger_nameBEFORE/ AFTER INSERT/ UPDATE/ DELETE ON table_name FOR EACH ROW -- 行級觸發器BEGINtrigger_statement;END;-- 查看SHOW TRIGGER;-- 刪除DROP TRIGGER [數據庫名.]trigger_name;-- 沒有指定數據庫,默認為當前數據庫

鎖是計算機協調多個進程或線程并發訪問某一資源的資質。

  • 全局鎖
-- 全局鎖就是對整個數據庫實例加鎖,加鎖后整個實例就處于只讀狀態,后續的DML的寫語句,DDL語句,已經更新操作的事務提交語句都將被阻塞。-- 典型場景是做全庫的邏輯備份,對所有的表進行鎖定,從而獲取一致性視圖,保證數據的完整性flush tables with read lock; -- 加全局鎖mysqldump -h遠程ip -uroot -p密碼 數據庫 > 備份文件; -- 數據備份,mysqldump是MySQL的工具,不是SQL語句unlock tables; -- 釋放全局鎖-- 特點1、如果在主庫上備份,那么在備份期間都不能執行更新,業務基本上停止。2、如果在從庫上備份,那么在備份期間從庫不能執行主庫同步過來的二進制日志,會導致主從延遲。在InnoDB引擎中,可以在備份時加 --single-transaction參數完成不加鎖的一致性數據備份mysqldump --single--transaction -h遠程ip -uroot -p密碼 數據庫 > 備份文件;
  • 表級鎖
-- 表級鎖,每次操作鎖住整張表。鎖定粒度大,發生鎖沖突的概率最高,并發度最低。應用在myisam 、InnoDB、BDB引擎中。-- 表鎖 分為兩類 # 表共享讀鎖(read lock) lock tables 表名... read; -- 加鎖unlock tables; /斷開客戶端連接 -- 釋放鎖# 表獨占寫鎖(write lock)lock tables 表名... write; -- 加鎖unlock tables; /斷開客戶端連接 -- 釋放鎖-- 注意讀鎖不會組測其他客戶端的讀操作,但是會阻塞寫。寫鎖會阻塞其他客戶端的讀操作,又會阻塞其他客戶端的寫操作。-- 元數據鎖(meta data lock ,MDL)MDL加鎖過程是系統自動控制,無序顯式使用,在訪問一張表的時候會自動加上。MDL鎖主要作用是維護表元數據一致性,在表上有活動事務時候,不可以對元數據進行寫操作。為了避免DML與DDL沖突,保證讀寫的正確性。在MySQL5.5中引入MDL,當對一張表進行增刪改查時,加MDL讀鎖(共享);對表結構進行變更操作時,加MDL寫鎖(排他)。-- 查看元數據鎖select object_type,object_schema,object_name,lock_type,lock_duration from perfromance_schema.metadata_locks;

-- 意向鎖為了避免DML在執行時,加的行鎖與表鎖的沖突,在innoDB中引入了意向鎖,使得表鎖不用檢查每行數據是否加鎖,使用意向鎖來減少表鎖的檢查# 意向共享鎖(IS):由語句select...lock in share mode添加與表鎖共享鎖兼容,與表鎖排他鎖互斥# 意向排他鎖(IX):由insert、update、delete、select..for update添加與表鎖均互斥,意向鎖之間不互斥-- 查看意向鎖語句select object_type,object_schema,object_name,lock_type,lock_duration from perfromance_schema.data_locks;
  • 行級鎖
-- 行級鎖,每次操作鎖住對應的行數據。鎖定粒度最小,發生鎖沖突的概率最低,并發度最高,應用在innoDB-- InnoDB的數據是基于索引組織的,行鎖是通過對索引上的索引項加鎖來實現的,而不是對記錄加鎖。對于行級鎖,主要分三類:1、行鎖(record lock):鎖定單個行記錄,防止其他事務對此行進行updatedelete。在RC、RR隔離級別下都支持2、間隙鎖(gap lock):鎖定索引記錄間隙(不含該記錄),確保索引記錄間隙不變,防止其他事務在該間隙insert,產生幻讀。在RR隔離級別下都支持3、臨鍵鎖(next-key lock): 行鎖與間隙鎖的組合,同時鎖住數據,并鎖住數據前面的間隙。在RR隔離級別下都支持-- 行鎖1、共享鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同數據集的排他鎖。2、排他鎖(X):允許獲取其他排他鎖的事務更新數據,阻止其他事務獲得相同數據集的共享鎖和排他鎖-- 注意默認情況下,InnoDBREPEATABLE READ事務隔離級別運行,InnoDB使用NEXT_KEY鎖進行搜索和索引掃描,以防止幻讀。1、針對唯一索引進行檢索,對已存在的記錄進行等值匹配時,將會自動優化為行鎖2InnoDB的行鎖是針對索引加的鎖,不通過索引條件檢索數據,那么引擎將對表中的所有記錄加鎖,此時就會升級為表鎖-- 查看行鎖語句select object_type,object_schema,object_name,lock_type,lock_duration from perfromance_schema.data_locks;

-- 間隙鎖 /臨鍵鎖1、索引上的等值查詢(唯一索引),給不存的記錄加鎖時,優化為間隙鎖。2、索引上的等值查詢(普通索引),向右遍歷時最后一個值不滿足查詢需求時,臨鍵鎖退化為間隙鎖3、索引上的范圍查詢(唯一索引)--會訪問到不滿足條件的第一個值為止-- 注意間隙鎖唯一目的是防止其他事務插入間隙。間隙鎖可以共存,一個事務采用的間隙鎖不會組織另一個事務在同一間隙上采用間隙鎖

InnoDB引擎

邏輯存儲結構

  • 表空間(ibd文件),一個MySQL實例可以對應多個表空間,用于存儲記錄、索引等數據。
  • 段,分數據段(leaf node segment)、索引段(non-leaf node segment)、回滾段(rollback segment)、InnoDB是索引組織表,數據段就是B+樹的葉子節點,索引段即為B+樹的非葉子節點。段用來管理多個區。
  • 區,表空間的單元結構,每個區的大小為1M。默認情況下,存儲引擎頁大小為16K,一個區中有64個連續的頁。
  • 頁,存儲引擎磁盤管理的最小單元,每個頁的大小默認為16K。為保證頁的連續性,存儲引擎每次從磁盤申請4-5個區。
  • 行,存儲引擎數據是按行進行存放的。

架構

內存架構
  • Buffer Pool :緩沖池是主內存中的一個區域,里面可以緩存磁盤上經常操作的真實數據,在執行增刪改查操作時,先操作緩沖池中的數據(若沒有數據,從磁盤加載并緩存),然后再以一定頻率刷新到磁盤,從而減少磁盤iIO,加快處理速度。

    緩沖池以頁為單位,底層采用鏈表數據結構管理頁。根據狀態頁分為三種類型:

    • free page: 空閑頁,未被使用
    • liean page: 被使用的頁,數據沒有被修改過
    • dirty page: 臟頁,被使用,數據被修改過,頁中數據與磁盤的數據產生不一致
  • Change Buffer :更改緩沖區(針對非唯一二級索引頁),在執行DML語句時,如果這些數據頁沒有在緩沖池中,不會直接操作磁盤,而會將數據變更存在更改緩沖區中,在未來數據被讀取時,再將數據合并恢復到緩沖池中,最后將合并后的數據刷新到磁盤中。

    • 緩沖區的意義

      與聚集索引不同,二級索引通常時非唯一的,并且以相對隨機的順序插入二級索引。同樣,刪除和更新可能會影響索引樹種不相鄰的二級索引頁,如果每一次操作磁盤,會造成大量的磁盤IO。有個緩沖區之后,可以在緩沖池合并處理,減少磁盤IO。

  • Adaptive Hash Index :自適應哈希索引,用于優化對緩沖池數據的查詢。存儲引擎會監控表上各索引頁的查詢,如果觀察到哈希索引可以提升速度,則建立哈希索引。無需干涉,系統根據情況自動建立

    參數: adaptive_hash_index – 查看是否開啟

  • Log Buffer :日志緩沖區,用來保存要寫入磁盤中的日志數據(redo log、undo log),默認大小為16MB,日志緩沖區的日志會定期刷新到磁盤。如果需要更新、插入或刪除許多行的事務,增加日志緩沖區的大小可以節省磁盤IO。

innodb_log_buffer_size -- 緩沖區大小innodb_flush_log_at_trx_commit -- 日志刷新到磁盤時機 (0 1 2)-- 0 日志再每次事務提交時寫入并刷新到磁盤-- 1 每秒將日志寫入并刷新到磁盤一次-- 2 日志再每次提交事務后寫入,并每秒刷新到磁盤一次
磁盤架構
  • System Tablespace :系統表空間時更改緩沖區的存儲區域。如果表是在系統表空間而不是每個表文件或通用表空間中創建的,它也可能包含表和索引數據。
innodb_data_file_path -- 表空間文件位置
  • File-Per-Table Tablespace :每個表的文件表空間包含單個存儲引擎表的數據和索引,并存儲在文件系統上的單個數據文件中。
innodb_file_per_table -- 開關
  • General Tablespace :通用表空間,需要通過用戶自己創建,在創建表時,可以指定該表空間。
CREATE TABLESPACE space_name ADD DATAFILE 'file_name.ibd' ENGINE = InnoDB;-- 創建表時使用CREATE TABLE ...() TABLESPACE space_name;
  • Undo Tablespace :撤銷表空間,MySQL實例在初始化時會自動創建兩個默認的undo表空間,初始大小16M,用于存儲undo log 日志。

  • Temporaty Tablespace :存儲引擎會話臨時表空間和全局臨時表空間,存儲用戶創建的臨時表等數據。

  • Doublewrite Buffer Files :雙寫緩沖區,存儲引擎將數據頁從Buffer Pool刷新到磁盤前,先將數據頁寫入雙寫緩沖區文件中,便于系統異常恢復數據。 xxx.dblwr文件

  • Redo Log :重做日志,是用來實現事務的持久性。該日志文件由兩部分組成:重做日志緩沖以及重做日志文件,前者是在內存中,后者在磁盤中。當事務提交之后會把所有修改信息都會存放到該日志中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復。

后臺線程
  • Master Thread :核心后臺線程,負責調度其他線程,還負責將緩沖池中的數據異步刷新到磁盤中,保持數據一致性,還包括臟頁的刷新、合并插入緩存、undo頁回收。

  • IO Thread :存儲引擎中使用了大量AIO來處理IO請求,極大化提高數據庫性能,該線程主要負責IO請求的回調。

Read thread -- 默認4個 ,負責讀操作Write thread -- 默認4個,負責寫操作 Log thread -- 默認1個,負責將日志緩沖區刷新到磁盤Insert buffer thread -- 默認1個,負責將寫緩沖區內容刷新到磁盤
  • Purge Thread :主要用于回收事務已經提交的undo log,在事務提交之后,undo log可能不用了,就用該線程回收。

  • Page Cleaner Thread:協助核心后臺線程刷新臟頁到磁盤的線程,它可以減輕Master Thread的工作壓力,減少阻塞。

事務原理

  • redo log 和undo log
-- 保證了數據的持久性、一致性和原子性 Redo Log :重做日志,是用來實現事務的持久性。該日志文件由兩部分組成:重做日志緩沖以及重做日志文件,前者是在內存中,后者在磁盤中。當事務提交之后會把所有修改信息都會存放到該日志中,用于在刷新臟頁到磁盤,發生錯誤時,進行數據恢復。 Undo log :回滾日志,用于記錄數據被修復前的信息,作用包含兩個:提供回滾和MVCC(多版本并發控制) undo log與redo log記錄物理日志不一樣,它是邏輯日志。可以認為當delete一條記錄時,undo log中會記錄一條對應的insert記錄,反之亦然,當update一條記錄時,它記錄一條對應相反的update記錄。當執行roolback時,就可以從undo log中的邏輯記錄讀取到相應的內容并進行回滾。 undo log銷毀:在事務執行時發生,事務提交時,并不會立即刪除undo log,因為這些日志可能用于MVCC undo log存儲:undo log采用段的方式進行管理和記錄,存放在前面介紹的rollback segment回滾段中,包含1024個undo log segment。 -- 鎖和MVCC保證了隔離性

MVCC

  • 當前讀

讀取的時記錄的最新版本,讀取時還要保證其他并發事務不能修改當前記錄,會對讀取的記錄進行加鎖。如:

select...lock in share mode(共享鎖)、select...for updateupdate、insert、delete(排他鎖)都是一種當前讀。
  • 快照讀

簡單的select(不加鎖)就是快照讀,讀取的時記錄數據的可見版本,有可能是歷史數據,不加鎖,是非阻塞讀。

Read Committed : 每次select,都生成一個快照讀。 Repeatable Read : 開啟事務后第一個select語句才是快照讀的地方。 Serializable : 快照讀會退化為當前讀
  • MVCC

全稱Multi-Version Concurrency Control,多版本并發控制。指維護一個數據的多個版本,使得讀寫操作沒有沖突,快照讀為MySQL實現MVCC提供了一個非阻塞讀功能。MVCC的具體實現,還需要依賴與數據庫記錄的三個隱式字段、undo log、readView。

  • 隱藏字段
DB_TRX_ID :最近修改事務ID,記錄插入這條記錄或最后一次修改該記錄的事務ID DB_ROLL_PTR :回滾指針,指向這條記錄的上一個版本,用于配合undo log,指向上一個版本 DB_ROW_ID : 隱藏主鍵,如果表結構沒有指定主鍵,將會生成該隱藏字段
  • undo log
insert時候,產生的日志旨在回滾時需要,在事務提交后,可被立即刪除。 當 update、 delete時候,產生的 undo log日志不僅在回滾時需要,在快照讀時也需要,不會被立即刪除 -- undo log版本連 不同事務或相同事務對同一條記錄進行修改,會導致記錄的日志生成一條記錄版本鏈表,鏈表頭部是最近的舊記錄,鏈表尾部是最早的舊記錄
  • readView
-- 讀視圖是快照讀SQL執行時MVCC提取數據的依據,記錄并維護系統當前活躍的事務(未提交的)id。 m_ids: 當前活躍的事務ID集合 min_trx_id: 最小活躍事務 max_trx_id: 預分配事務ID,當前最大事務ID+1(因為事務ID時自增的) creator_trx_id: 讀視圖創建者的事務ID

-- 不同隔離級別,生成ReadView的時機不同: READ COMMITTED : 在事務中每一次執行快照讀時生成讀視圖 REPEATABLE READ :僅在事務中第一次執行快照讀時生成讀視圖,后續復用該讀視圖

總結

以上是生活随笔為你收集整理的MySQL学习笔记-从基础到进阶的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。