MySQL工作流程


mysql的工作流程:

  

1.mysql 架構

  mysql 分為 server 層和存儲引擎

1.1.server層

  

  • 連接器:管理連接權限驗證

  • 查詢緩存:命中緩存直接換回查詢結果

  • 分析器:分析語法

  • 優化器:生成執行計划,選擇索引

  • 執行器:操作索引返回結果

1.2. 存儲引擎

  存儲引擎負責數據的存儲和提取;其架構是插件式的。innodb 在 mysql5.5.5 版本開始成為 mysql 默認存儲引擎。

  

各存儲引擎比對:

  • InnoDB:支持事務,支持外鍵,InnoDB 是聚集索引,數據文件是和索引綁在一起的,必須要有主鍵,通過主鍵索引效率很高。但是輔助索引需要兩次查詢,先查詢到主鍵,然后再通過主鍵查詢到數據,不支持全文索引。

  • MyISAM:不支持事物,不支持外鍵,MyISAM 是非聚集索引,數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是獨立的,查詢效率上 MyISAM 要高於 InnnDB ,因此做讀寫分離的時候一般選擇用 InnoDB 做主機,MyISAM 做從機

  • Memory:有比較大的缺陷使用場景很少;文件數據都存儲在內存中,如果 mysqld 進程發生異常,重啟或關閉機器這些數據都會消失。

1.3.sql 的執行過程

  第一步客戶端連接上 mysql 數據庫的連接器,連接器獲取權限,維持管理連接;連接完成后如果你沒有后續的指令這個連接就會處於空閑狀態,如果太長時間不使用這個連接這個連接就會斷開,這個空閑時長默認是 8 小時,由 wait_timeout 參數控制。

  第二步你往 mysql 數據庫發送了一條 sql ,這個時候查詢緩存開始工作,看看之前有沒有執行過這個 sql ,如果有則直接返回緩存數據到客戶端,只要對表執行過更新操作緩存都會失效,因此一些很少更新的數據表可考慮使用數據庫緩存,對頻繁更新的表使用緩存反而弊大於利。使用緩存的方法如以下 sql ,通過 SQL_CACHE 來指定:

  select SQL_CACHE * from table where xxx=xxx

  第三步當未命中緩存的時候,分析器開始工作;分析器判斷你是 select 還是 update 還是 insert ,分析你的語法是否正確。

  第四步優化器根據你的表的索引和 sql 語句決定用哪個索引,決定 join 的順序。

  第五步執行器執行 sql ,調用存儲引擎的接口,掃描遍歷表或者插入更新數據。

2 mysql 日志

  2.1 mysql 日志介紹

  mysql 有兩個重要日志—— redolog 和 binlog ,redolog 是獨屬於 innodb 的日志,binlog 則是屬於 server 層的日志。下面介紹這兩個日志有什么用:當我們更新數據庫數據的時候,這兩個日志文件也會被更新,記錄數據庫更新操作。

  redolog 又稱作重做日志,用於記錄事務操作的變化,記錄的是數據修改之后的值,不管事務是否提交都會記錄下來。它在數據庫重啟恢復的時候被使用,innodb 利用這個日志恢復到數據庫宕機前的狀態,以此來保證數據的完整性。redolog 是物理日志,記錄的是某個表的數據做了哪些修改,redolog 是固定大小的,也就是說后面的日志會覆蓋前面的日志。

  binlog 又稱作歸檔日志,它記錄了對 MySQL 數據庫執行更改的所有操作,但是不包括 SELECT 和 SHOW 這類操作。binlog 是邏輯日志,記錄的是某個表執行了哪些操作。binlog 是追加形式的寫入日志,后面的日志不會被前面的覆蓋。

  2.2 數據更新過程

  我們執行一個更新操作是這樣的:讀取對應的數據到內存—>更新數據—>寫 redolog 日志—> redolog 狀態為 prepare —>寫 binlog 日志—>提交事務—> redolog 狀態為 commit ,數據正式寫入日志文件。我們發現 redolog 的提交方式為“兩段式提交”,這樣做的目的是為了數據恢復的時候確保數據恢復的准確性,因為數據恢復是通過備份的 binlog 來完成的,所以要確保 redolog 要和 binlog 一致。

 

 

 

6執行計划和慢查詢日志

 6.1 執行計划

  在查詢 sql 之前加上 explain 可查看該條 sql 的執行計划,如:

    EXPLAIN SELECT * FROM table

  這條 sql 會返回這樣一個表:

id select_type table partitions type possible_keys key key_len ref rows filtered extra  
1 simple                      

  這個表便是 sql 的執行計划,我們可以通過分析這個執行計划來知道我們 sql 的運行情況。現對各列進行解釋:

    1)id:查詢中執行 select 子句或操作表的順序。

    2)select_type:查詢中每個 select 子句的類型(簡單 到復雜)包括:

      • SIMPLE:查詢中不包含子查詢或者UNION;

      • PRIMARY:查詢中包含復雜的子部分;

      • SUBQUERY:在SELECT或WHERE列表中包含了子查詢,該子查詢被標記為SUBQUERY;

      • DERIVED:衍生,在FROM列表中包含的子查詢被標記為DERIVED;

      • UNION:若第二個SELECT出現在UNION之后,則被標記為UNION;

      • UNION RESULT:從UNION表獲取結果的SELECT被標記為UNION RESULT;

    3) type:表示 MySQL 在表中找到所需行的方式,又稱“訪問類型”,包括:

      • ALL:Full Table Scan, MySQL 將遍歷全表以找到匹配的行;

      • index:Full Index Scan,index 與 ALL 區別為 index 類型只遍歷索引樹;

      • range:索引范圍掃描,對索引的掃描開始於某一點,返回匹配值域的行,常見於 between < > 等查詢;

      • ref:非唯一性索引掃描,返回匹配某個單獨值的所有行。常見於使用非唯一索引即唯一索引的非唯一前綴進行的查找;

      • eq_ref:唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或唯一索引掃描;

      • onst 和 system:當 MySQL 對查詢某部分進行優化,並轉換為一個常量時,使用這些類型訪問。如將主鍵置於 where 列表中,MySQL 就能將該查詢轉換為一個常量,system 是 const 類型的特例,當查詢的表只有一行的情況下, 使用 system;

      • NULL:MySQL 在優化過程中分解語句,執行時甚至不用訪問表或索引。

    4)possible_keys:指出 MySQL 能使用哪個索引在表中找到行,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用。

    5)key:顯示 MySQL 在查詢中實際使用的索引,若沒有使用索引,顯示為 NULL。

    6)key_len:表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度。

    7)ref:表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值。

    8)rows:表示上述表的連接匹配條件,即哪些列或常量被用於查找索引列上的值。

    9)Extra:其他重要信息 包括:

      • Using index:該值表示相應的 select 操作中使用了覆蓋索引;

      • Using where:MySQL 將用 where 子句來過濾結果集;

      • Using temporary:表示 MySQL 需要使用臨時表來存儲結果集,常見於排序和分組查詢;

      • Using filesort:MySQL 中無法利用索引完成的排序操作稱為“文件排序”。

 6.2 慢查詢日志

  mysql 支持慢查詢日志功能—— mysql 會將查詢時間過長的 sql 相關信息寫入日志。這個查詢時間閥值由參數 long_query_time 指定, long_query_time 的默認值為 10,運行 10S 以上的查詢 sql 會被記錄到慢查詢日志中。默認情況下,Mysql 數據庫並不啟動慢查詢日志,需要我們手動來設置這個參數。慢查詢日志支持將日志記錄寫入文件,也支持將日志記錄寫入數據庫表。

可通過以下 sql 查看慢查詢日志是否開啟:

    show variables like '%slow_query_log%';

  通過以下 sql 開啟慢查詢:

    set global slow_query_log=1;

  使用 sql 修改慢查詢日志設置只對當前數據庫生效,如果 MySQL 重啟后則會失效。如果要永久生效,就必須修改配置文件 my.cnf。

  通過以下 sql 查看修改慢查詢的閾值:

    show variables like 'long_query_time%';

    et global long_query_time=4;

7 主從備份

 7.1 主從備份原理

  主從復制是指一台服務器充當主數據庫服務器,另一台或多台服務器充當從數據庫服務器,主服務器中的數據自動復制到從服務器之中。通過這種手段我們可以做到讀寫分離,主庫寫數據,從庫讀數據,從而提高數據庫的可用。MySQL 主從復制涉及到三個線程,一個運行在主節點(log dump thread),其余兩個(I/O thread, SQL thread)運行在從節點。

主節點 binary log dump 線程:

  當從節點連接主節點時,主節點會創建一個 logdump 線程,用於發送 binlog 的內容。在讀取 binlog 中的操作時,此線程會對主節點上的 binlog 加鎖,當讀取完成,甚至在發動給從節點之前,鎖會被釋放。

  從節點I/O線程: 用於從庫將主庫的 binlog復制到本地的 relay log中,首先,從庫庫會先啟動一個工作線程,稱為IO工作線程,負責和主庫建立一個普通的客戶端連接。如果該進程追趕上了主庫,它將進入睡眠狀態,直到主庫有新的事件產生通知它,他才會被喚醒,將接收到的事件記錄到 relay log(中繼日志)中。

從節點 SQL 線程:

  SQL 線程負責讀取 relay log 中的內容,解析成具體的操作並執行,最終保證主從數據的一致性。

7.2 主從備份延遲

  主備延遲最直接的表現是,備庫消費中繼日志( relay log)的速度,比主庫生產 binlog 的速度要慢。可能導致的原因有:

    • 大事務,主庫上必須等事務執行完成才會寫入 binlog,再傳給備庫,當一個事物用時很久的時候,在從庫上會因為這個事物的執行產生延遲。

    • 從庫壓力大。

  主備延遲當然是不好的,那么有哪些辦法盡量減小主備延遲呢?有下面幾個辦法:

    • 一主多從——多接幾個從庫,讓這些從庫來分擔讀的壓力。這樣方法適用於從庫讀壓力大的時候。

    • 通過 binlog 輸出到外部系統,比如 Hadoop 這類系統,讓外部系統提供統計類查詢的能力

8 分布式事務

  這里不再對分布式事物的概念做普及,直接介紹兩種分布式事務: XA 分布式事務和 TCC 分布式事務。

  8.1 XA 分布式事務

    XA 是兩階段提交的強一致性事物。在 MySQL 5.7.7 版本中,Oracle 官方將 MySQL XA 一直存在的一個 “bug” 進行了修復,使得MySQL XA 的實現符合了分布式事務的標准。

    XA 事務中的角色:

      • 資源管理器(resource manager):用來管理系統資源,是通向事務資源的途徑。數據庫就是一種資源管理器。資源管理還應該具有管理事務提交或回滾的能力。

      • 事務管理器(transaction manager):事務管理器是分布式事務的核心管理者。事務管理器與每個資源管理器(resource manager)進行通信,協調並完成事務的處理。事務的各個分支由唯一命名進行標識。

    XA 規范的基礎是兩階段提交協議:

  在第一階段,交易中間件請求所有相關數據庫准備提交(預提交)各自的事務分支,以確認是否所有相關數據庫都可以提交各自的事務分支。當某一數據庫收到預提交后,如果可以提交屬於自己的事務分支,則將自己在該事務分支中所做的操作固定記錄下來,並給交易中間件一個同意提交的應答,此時數據庫將不能再在該事務分支中加入任何操作,但此時數據庫並沒有真正提交該事務,數據庫對共享資源的操作還未釋放(處於鎖定狀態)。如果由於某種原因數據庫無法提交屬於自己的事務分支,它將回滾自己的所有操作,釋放對共享資源上的鎖,並返回給交易中間件失敗應答。

在第二階段,交易中間件審查所有數據庫返回的預提交結果,如所有數據庫都可以提交,交易中間件將要求所有數據庫做正式提交,這樣該全局事務被提交。而如果有任一數據庫預提交返回失敗,交易中間件將要求所有其它數據庫回滾其操作,這樣該全局事務被回滾。

mysql 允許多個數據庫實例參與一個全局的事務。MySQL XA 的命令集合如下:

     -- 開啟一個事務,並將事務置於 ACTIVE 狀態,此后執行的 SQL 語句都將置於該是事務中。

 

      XA START xid

 

    •  

    • -- 將事務置於 IDLE 狀態,表示事務內的 SQL 操作完成。

    •     

      • XA END xid

    • -- 事務提交的准備動作,事務狀態置於 PREPARED 狀態。事務如果無法完成提交前的准備操作,該語句會執行失敗。

    •     

      • XA PREPARE xid

    • -- 事務最終提交,完成持久化。

    •     

      • XA COMMIT xid

    • -- 事務回滾終止

    •     

      • XA ROLLBACK xid

    • -- 查看 MySQL 中存在的 PREPARED 狀態的 xa 事務。

    •     

    •   
            XA RECOVER

    MySQL 在 XA 事務中扮演的是參與者的角色,被事務協調器所支配。XA 事務比普通本地事務多了一個 PREPARE 狀態,普通事務是 begin-> commit 而分布式事務是 begin->PREPARE 等其他數據庫事務都到 PREPARE 狀態的時候再 PREPARE->commit。分布式事務 sql 示例:

    xa start 'aaa';

    insert into table(xxx) values(xxx);

    xa end 'aaa'; 

    xa prepare 'aaa';

    xa commit 'aaa';

XA 事務存在的問題:

  • 單點問題:事務管理器在整個流程中扮演的角色很關鍵,如果其宕機,比如在第一階段已經完成,在第二階段正准備提交的時候事務管理器宕機,資源管理器就會一直阻塞,導致數據庫無法使用。

  • 同步阻塞:在准備就緒之后,資源管理器中的資源一直處於阻塞狀態,直到提交完成才能釋放資源。

  • 數據不一致:兩階段提交協議雖然為分布式數據強一致性所設計,但仍然存在數據不一致性的可能,比如在第二階段中,假設協調者發出了事務 commit 的通知,但是因為網絡問題該通知僅被一部分參與者所收到並執行了 commit 操作,其余的參與者則因為沒有收到通知一直處於阻塞狀態,這時候就產生了數據的不一致性。

 8.2 TCC 分布式事務

  TCC 又被稱作柔性事務,通過事務補償機制來達到事務的最終一致性,它不是強一致性的事務。TCC 將事務分為兩個階段,或者說是由兩個事務組成的。相對於 XA 事務來說 TCC 的並發性更好,XA 是全局性的事務,而 TCC 是由兩個本地事務組成。

  假設我們購買一件商品,后台需要操作兩張表——積分表加積分而庫存表扣庫存,這兩張表存在於兩個數據庫中,使用 TCC 事務執行這一事務:

  1)TCC 實現階段一:Try

  在 try 階段並不是直接減庫存加積分,而是將相關數據改變為預備的狀態。庫存表先鎖定一個庫存,鎖定的方式可以預留一個鎖定字段,當這個字段為一的時候表示這個商品被鎖定。積分表加一個數據,這個數據也是被鎖定狀態,鎖定方式和庫存表一樣。其 sql 形如:

    update stock set lock=1 where id=1;

    nsert into credits (lock,...) values (1,...)

  這兩條 sql 如果都執行成功則進入 Confirm 階段,如果執行不成功則進入 Cancel 階段

  2)TCC 實現階段二:Confirm

  這一階段正式減庫存加積分訂單狀態改為已支付。執行 sql 將鎖定的庫存扣除,為累加積分累加,以及一些其他的邏輯。

  3)TCC 實現階段三:Cancel

  當 try 階段執行不成功,就會執行這一階段,這個階段將鎖定的庫存還原,鎖定的積分刪除掉。退回到事務執行前的狀態。

  TCC 事務原理很簡單,使用起來卻不簡單。首先 TCC 事務對系統侵入性很大,其次是讓業務邏輯變得復雜。在實際使用中我們必須依賴 TCC 事務中間件才能讓 TCC 事務得以實現。通常一個 TCC 事務實現大概是這樣子的:某個服務向外暴露了一個服務,這個服務對外正常調用,其他服務並不能感知到 TCC 事務的存在,而其服務內部,分別實現了 Try,Confirm,Cancel 三個接口,注冊到 TCC 中間件上去。當調用這個服務的時候,其事務操作由該服務和 TCC 中間件共同完成。

  而 TCC 事務中間件還要做好其他事情,比如確保 Confirm 或者 Cancel 執行成功,如果發現某個服務的 Cancel 或者 Confirm 一直沒成功,會不停的重試調用他的 Cancel 或者 Confirm 邏輯,務必要他成功!即使在嘗試多次后無法成功也能通知到系統需要人工排查異常。TCC 事務還要考慮一些異常情況的處理,比如說訂單服務突然掛了,然后再次重啟,TCC 分布式事務框架要能夠保證之前沒執行完的分布式事務繼續執行。TCC 分布式事務框架還需要做好日志的記錄,保存下來分布式事務運行的各個階段和狀態,以便系統上線后能夠排查異常,恢復數據。目前開源的 TCC 事務框架有:Seata ByteTCC tcc-transaction等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM