mysql
MySQL 是最流行的關系型資料庫管理系統,在 WEB 應用方面 MySQL 是最好的 RDBMS(Relational Database Management System:關系資料庫管理系統)應用軟體之一,
mysql結構

如上圖所示,可分為用戶連接執行緒 -> 服務層 -> 存盤引擎
用戶連接執行緒:處理客戶端連接、授權、用戶認證等,
服務層:處理sql陳述句的決議、快取的處理和函式的實作等
存盤引擎:對于資料的存盤和提取(innodb、NDB Cluster支持事務,Mylsam、Memory不支持事務),
如無特殊說明,后文中描述的內容都是基于InnoDB,
ACID事務特性
mysql由start transaction標識事務的開啟,commit提交事務,rollback回滾事務,mysql在默認情況下開啟事務,即autocommit模式,在這種模式下,每一個sql陳述句都會被當成一個事務執行提交操作,當然也可以將autocommit的開關關上,需要注意的事,autocommit引數針對的事連接,修改引數只會對當前連接生效,如需全域修改,請修改啟動組態檔,
mysql當中,當執行一些特殊的陳述句的會后,會強制事務的提交,比如DDL陳述句(create table/drop table/alter/table),常用的增刪改查操作都不會強制提交事務
- 原子性(Atomicity)
原子性是指一個事務不可分割的一個作業單位,要么都成功,要么都失敗,針對單個事務而言
實作原理:undo log(回滾日志,由存盤引擎實作)
當事務對資料庫進行修改時,innodb會生成對應的undo log記錄,記錄sql執行相關資訊,當事務失敗呼叫rollback回滾時,會根據undolog中的資訊進行反向操作,將資料回滾到事務開啟之前的狀態,
- 一致性(Consistency)
一致性指的是事務執行前后資料的完整性沒有被破壞,包括物體完整性(如行的主鍵存在且唯一)、列完整性(如欄位的型別、大小、長度要符合要求)、外鍵約束、用戶自定義完整性(如轉賬前后,兩個賬戶余額的和應該不變)等等,
一致性是事務的終極目標,其他三個特性都是為一致性所服務的
資料庫實作一致性的措施體現:
不允許向整形列插入字串值、字串長度不能超過列的限制等
- 隔離性(Isolation)
隔離性指的是多個事務同時執行的時候,每個事務內部都應該與其他事務是隔離的,不能互相干擾,
資料庫的隔離級別:讀未提交(RU)、讀已提交(RC)、可重復讀(RR)、序列化也叫串行化(S)
實作原理:讀讀之間(MVCC多版本并發控制協議)、讀寫之間(鎖機制)
1、MVCC:MVCC是一種樂觀鎖的體現,主要是通過兩個隱藏列實作(事務版本號和undolog指標,也是undolog版本鏈),用戶在某一時刻對整個事務系統進行快照,之后再進行讀操作時,會將讀取到的事務中的事務版本號和快照比較,從而判斷資料對該快照是否可見,即對打快照時的事務是否可見,RR隔離級別下,事務在事務開始的時候進行快照動作,一直到事務提交都不會重新進行快照,RC則是每次select操作之前會重新建立快照,這就導致RC可能會在第二次select的時候讀到其他事務提交得資料,所以RC情況下可以避免臟讀問題可是無法避免重復讀和幻讀問題,
2、鎖機制:mysql鎖可以分為共享鎖(lock in share mode)、排它鎖(for update)、意向鎖(意向共享和意向排他)、間隙鎖(Gap lock),共享鎖、排它鎖是行鎖,鎖粒度小,性能好,意向鎖是表鎖,是資料庫自身的行為,不需要人工干預,在事務結束后會自行解除,多用在innodb當中,意向鎖主要解決事務開始時遍歷所有行的鎖持有情況從而導致性能較低的問題,事務在檢查行鎖之前會檢查意向鎖是否存在,存在則阻塞執行緒.
意向鎖協議:
-
- 事務要獲取表A某些行的S鎖必須要獲取表A的IS鎖(意向共享鎖)
- 事務要獲取表A某些行的X鎖必須要獲取表A的IX鎖(意向排他鎖)
間隙鎖:
innodb下間隙鎖的產生需要產生三個條件:
1、隔離級別為RR(mysql默認,不改即為這個)
2、當前讀(非快照讀)
3、查詢條件能夠走索引(這里提一句:mysql行鎖(間隙鎖也是行鎖)鎖的是索引,所以當查詢未使用索引的情況下,innodb會使用表鎖,這就會導致一些使用相同索引鍵的查詢也會出現鎖沖突)
注意:innodb使用一個相等條件請求對一個不存在的記錄加鎖的時候,也會產生間隙鎖
間隙鎖的作用:
當前讀幻讀的解決方法:間隙鎖可以鎖定一個范圍內的多條資料,防止事務執行的時候其他事務往這個范圍內插入資料,導致幻讀,這是主要目的,
- 持久性(Durability)
持久性指的是事務一單提交,它對資料庫產生的改變應該是持久的(單個事務而言).
實作原理:redo log(重做日志,存盤引擎實作)
在innodb當中,資料是存放在磁盤上的,但是如果每次查詢資料都需要讀磁盤的話,效率會相當低,為此,innodb提供了一個快取機制--Buffer Pool(簡稱BP),BP中包含了磁盤中部分資料的映射,作為訪問資料庫的快取,
當讀資料的時候,先讀BP,BP沒有在讀磁盤,然后將資料放入BP,
當寫資料的時候,先寫BP,BP會將資料定期重繪到磁盤當中(刷臟),
上面寫資料就會產生一個問題,當我們的機子死機了,BP資料還未刷到磁盤中那資料不就丟失啦?事務的持久性就得不到保證
為了解決這個問題:redo log 引入解決這個問題:
當資料修改時,會先記錄在redo log 中,然后再寫入BP中,當事務提交的時候,就會呼叫fsync介面對redolog進行刷盤(落磁盤),如果mysql宕機,就可以在重啟的時候讀取redolog的日志恢復資料庫中的資料.
既然redolog也要進行磁盤IO,為什么比BP快呢?
兩個原因:
1、BP是隨機IO,每次修改的位置隨機,redoLog屬于追加操作,順序IO.
2、BP是以頁(Page)為單位進行磁盤操作的,但是redolog只是做真正需要寫入的部分,相對BP來講,會少很多無效的IO.
最后提一嘴binog和redo log的區別:
1、redo log存盤引擎實作、binlog服務層實作(可參照第一張圖,不太擅長畫圖,sorry……)
2、redo log寫入的時機比較多,各種修改都會觸發,只是在事務提交的時候落磁盤而已,binlog則只會在事務提交的時候寫入,
3、binlog為二進制日志,根據引數不同可能是sql或者資料,redolog則是物理日志,內容基于Page,
第一次寫一篇比較完整的博客,完全根據自己的想法走,要是哪個位置寫的不太對,歡迎大家一起探討提高,感謝每一個路過的人,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/65776.html
標籤:MySQL
