mysql 活跃事务_MySQL日志与事务
整體架構
事務的基本概念
事務就是一組原子性的sql查詢,或者是一個獨立的工作單元
事務內的語句,要么全部執行成功,要么全部執行失敗
ACID標識原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)
一個運行良好的事務處理系統,必須要具備這些標準特征
原子性
要么所有操作全部成功,要么全部失敗回滾,不可能執行其中的一部分操作
一致性
失敗后事務最終沒有提交,所做的修改不會保存到數據庫中
隔離性
事務所做的修改在最終提交前,對其他事務是不可見的
持久性
一旦事務提交,所做的修改就會永久保存到數據庫中
事務需要用到更多的處理能力
可選擇適合業務的存儲引擎
事務的過程就是一個日志的寫入過程
以下從緩沖池和日志的角度,描述事務的提交
InooDB體系架構
InnoDB存儲引擎有多個內存塊,組成一個大的內存池,負責如下工作
維護所有進程/線程需要訪問的多個內部數據結構
緩存磁盤上的數據,方便快讀地讀取,同時在對磁盤文件的數據修改之前在這里緩存
重做日志(redo log)緩沖
其中,后臺線程的主要作用是負責刷新內存池中的數據,保證緩沖池中的內存緩存是最近的數據。此外將已修改的數據文件刷新到磁盤,同事保證數據庫發生異常的情況下InnoDB能回復到正常運行狀態
后臺線程
Master Thread
非常核心的后臺線程,負責將緩沖池中的數據異步刷新到磁盤,保證數據的一致性
IO Thread
InnoDB存儲引擎大量使用了AIO(Async IO異步IO)來處理IO請求,以提高性能。而IO Thread主要負責這些IO請求的回調處理
Purge Thread
回收已提交事務后,不需要的undolog
內存
緩沖池
InnoDB存儲引擎基于磁盤存儲,記錄則按頁的方式進行管理
緩沖池用于連接CPU與磁盤速度質檢的鴻溝,來提高數據庫的整體性能,就是一塊內存區域
在讀取頁的操作,會將磁盤放到緩沖池中(FIX)。下次讀取相同頁會先從緩沖池里拿
修改時會先修改緩沖池中的頁,然后按一定頻率刷新到磁盤(通過checnkpoint機制)
緩沖池中緩存的數據頁類型有:索引頁、數據頁、undo頁、插入緩沖、自適應哈希索引、InnoDB存儲的鎖信息、數據字典信息等
LRU List、FreeList和Flush List
LRU
緩沖池通過LRU(Lastest Recent Used,最近最少使用)算法進行管理
最頻繁使用的夜放在LRU列表的前端,最少使用的放在尾端
不能存儲新讀的頁時,首先釋放LRU尾端的頁(頁的大小默認為16kb)
InnoDB的LRU算法不是樸素的LRU算法,加入了midpoint位置
默認midpoint位置為5/8處,midpoint之前是old列表、之后是new列表(活躍的熱點數據在new列表)
為了防止熱點數據從LRU列表中擦除,引入了innodb_old_blocks_time表示讀取到mid位置后等待多久才會被加入到LRU列表的熱端
Free list
當數據庫剛啟動,LRU列表是空的,此時頁都存放在Free列表中
會先從Free列表中查找是否有可用的空閑頁,如有,則放到LRU列表中,否則根據LRU算法淘汰列表末尾的頁(不活躍的部分),分配給新頁
InnoDB的策略是盡量使用內存,因此對于一個長期運行的庫來說,未被使用的頁很少
Flush list
Flush列表中的頁都為臟頁列表,但臟頁也存在于LRU列表中
LRU列表用來管理緩沖池中頁的可用性,Flush列表用來管理將頁刷新回磁盤,二者互不影響
redo log
redo log buffer
在緩沖池中,有日志緩沖(默認8m)。在寫入的時候,會先寫入日志緩沖中
以下三種情況,會將日志緩沖刷新到磁盤的重做日志中
Master Thread會每秒都會把日志緩沖的數據刷新到日志文件
每個事務提交(事務commit)
日志重做的緩沖池剩余空間小于1/2時
redo log file
是innoDB本身的日志文件,在存儲引擎層
在事務提交時,必須把所有的日志寫入到redo log file進行持久化(Write Ahead Log)
重做日志分為多組(至少一組),每組至少有兩個日志文件
以循環的方式寫文件,文件1滿切換文件2,反之切換回文件1
日志大小太大會導致恢復時間很長,太小,可能會導致多次切換重做日志文件
會導致async checkpoint(下面有解釋),造成性能抖動
checkpoint技術
checkpoint本身是緩沖池
解決了以下問題
縮短數據庫的回復時間
緩沖池不夠用時,將頁刷新到磁盤
重做日志不可用時,刷新臟頁
具體來說
通過LSN(Log Sequence Number)來標記版本,緩沖池的頁有LSN,重做日志中也有LSN,Checkpoint也有LSN
緩沖池的頁會根據LRU算法算出最少使用的頁作為臟頁,刷回到磁盤
日志可以根據標記的LSN版本,來計算出需要需要重做的日志的部分是哪些
checkpoint的觸發有兩種
Sharp Checkpoint,在數據庫關閉的時候將所有臟頁都刷新回磁盤
Fuzzy Checkpoint
Master Thread Checkpoint 以每秒或者每十秒的速度從緩沖池的臟頁列表以一定比例的頁刷回磁盤
FLUSH_LRU_LIST Checkpoint 保證LRU列表中有差不多100個空閑頁可用,會從LRU列表尾端的頁移除
Async/Sync Flush Checkpoint
當重做日志不可用,則需要強制刷新一些頁回磁盤,臟頁從臟頁列表(Flush List)中選取
寫入到重做日志的LSN記為redo_lsn,已經刷新磁盤最新頁的LSN記為checkpoint_lsn
通過redo_lsn和checkpoint_lsn來判斷是否需要觸發Async/Sync Flush Checkpoint,算法如下
checkpoint_age = redo_lsn - checkpoint_lsn 記錄未刷到磁盤的日志
定義變量asycn_water_mark = 75% * total_redo_log_file_size
定義變量sycn_water_mark = 90% * total_redo_log_file_size
當async_water_mark < checkpoint_age < sycn_water_mark,觸發Async Flush,從Flush列表中刷新足夠的臟頁回磁盤,以滿足checkpoint_age < async_water_mark
Dirty Page too much Checkpoint,臟頁數量太多,導致強制進行Checkpoint,目的還是為了保證緩沖池有足夠可用的頁
縮短數據庫的恢復時間,在數據更新的時候,會同時更新redo log以及緩沖池緩存,數據庫異常(如斷電等)的時候,可以直接從checkpoint的點開始從redolog恢復數據
redo log與bin log
redo log是發生在存儲引擎這一層,是innodb的日志文件系統,而bin log是在mysql的server層,所有的日志都有
兩個日志必須是狀態一致的,所以他們的日志寫入,則是一個事務的提交過程
bin log記錄的是完整的邏輯記錄,redo log記錄的是物理日志
事務提交的過程,稱為兩階段提交
在進行一個事務的時候(未提交),會把redo log寫到緩存buffer中,再通過master thread刷到磁盤中,此時標記為未提交(prepare)
接著在binlog中,寫入二進制日志
當binlog寫完,再把redo log從prepare狀態改為commit,此時事務提交完成
為什么要進行這樣的一個提交流程呢?
如果剛好在寫入redo log的時候斷點,那重啟后事務回滾,日志一樣同步
如果redo log已經寫完,在bin log寫入的時候斷電,重啟后發現二者日志的狀態不一致,則事務未提交,根據日志回滾
都寫完日志,但未commit,依然回滾
都寫完,已commit,狀態同步,完成事務提交
二階段的提交保證了兩者日志的一致性
總結
本文大致描述了事務、緩沖池、checkpoint、日志之間的關聯,但還有許多細節需要深究。例如redo log以及undo log的關系、checkpoint的運行機制等等。
參考文檔
MySQL技術內幕(InnoDB存儲引擎)
高性能MySQL
總結
以上是生活随笔為你收集整理的mysql 活跃事务_MySQL日志与事务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql query profile_
- 下一篇: plsqldev远程连接mysql_PL