1. 程式人生 > 實用技巧 >7.innodb的事務機制、鎖等簡述

7.innodb的事務機制、鎖等簡述

1. innodb的核心特性

  1.1 Innodb的事務的ACID特性:

    ● Atomic(原子性):所有語句作為一個單元全部成功執行或全部取消,不能出現中間狀態

    ● Consistent(一致性):如果資料庫在事務開始時處於一致狀態,則在執行該事務期間將保留一致狀態

    ●Isolated(隔離性):事務之間不相互影響

    ●Durable(永續性):事務成功完成後,所做的所有更改準確地記錄在資料庫中,所做的更改不會丟失

  1.2 事務的宣告週期

    begin:

    sql 語句

    commit或者rollback :提交或者回滾

  1.3 自動提交機制(autocommit)   

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

注意:

線上修改引數
set autocommit=0; # 會話級別 ,及時生效
set global autocommit=0; #全域性級別 ,斷開視窗重連後生效,影響到所有新開的會話

(3)永久生效 vim /etc/my.cnf
autocommit=0;

  1.4 事務的acid 特性如何保證?

      1.4.1 一些概念名詞

        髒頁:記憶體髒頁,記憶體中發生了修改,沒寫入到磁碟之前,我們把記憶體頁稱為髒頁

        redolog : 重做日誌,一般會儲存在磁碟上(ib_logfile0,ib_logfile1) ,一般大小為50M 

        xx.ibd :這個是儲存資料和索引的檔案

        buffer_poll: 緩衝區域

        LSN: 日誌序列號 ,一般儲存磁碟資料頁,redo檔案,buffer pool,redo buffer ,作用:mysql 每次資料庫啟動,都會比較磁碟資料頁和redolog的LSN,必須要求兩者LSN一致資料才能正常啟動

        WAL::日誌優先寫的方式實現持久化

        CKPT:checkpoint,檢查點,就是將髒頁刷寫到磁碟的動作

        TXID:事務號,innodb會為每一個事務生成一個事務號,伴隨著整個事務週期。

    

      1.4.2 事務日誌redolog

          作用:主要功能 保證“D", A C 也有一定的作用

          ●記錄了記憶體資料頁的變化

          ●提供快速的持久化功能(WAL)

          ●CSR過程中實現前滾的操作(保證磁碟資料頁和redo日誌LSN一致)

        redo日誌位置: iblogfile0 ib_logfile1

情況一:
我們做了一個事務,begin;update;commit;
1.在begin時,會立即分配一個TXID=tx_01.
2.update時,會將需要修改的資料頁(dp_01,LSN),載入到data_buffer中,
3.DBWR執行緒,會進行dp_01資料頁修改更新,並更新LSN=102.
4.LogBWR日誌寫執行緒,會將dp_01資料頁的變化+LSN+TXID儲存到redobuffer中
5.執行commit時,LGWR日誌寫執行緒會將redobuffer資訊寫入redolog日誌檔案中,基於WAL原則在日誌完全寫入磁碟後,commit命令才執行成功,(會將此日誌打上commit標記)
6.假如此時宕機,記憶體髒頁沒有來的及寫入磁碟,記憶體資料全部丟失
7.mysql再次重啟時,必須要redlog和磁碟資料頁的LSN是一致的,但是,這時是不一致的
8.於是mysql此時無法正常啟動,那麼就是觸發CSR機制,在記憶體中追平LSN號,觸發CKPT,將記憶體資料頁更新到磁碟中,從而保證磁碟資料頁和redolog LSN一致,
這是mysql正常啟動
以上過程我們稱之基於redo的’前滾操作'

2. undo?

  undo日誌使用者存放資料被修改前的值,簡單的說如果修改某表中的某個值的話,例如將tba表中的id=2這行資料的name='a' 修改成為name='a2',那麼undo日誌就會用來存放name='a'的記錄,如果這個修改出現異常,可以使用undo日誌來實現回滾操作,來保證事務的一致性。

  關於undo的一系列引數:

    ▲innodb_max_undo_log_size :控制最大undo tablespace檔案的大小,當啟動了innodb_undo_log_truncate 時,undo tablespace 超過innodb_max_undo_log_size 閥值時才會去嘗試truncate該值預設大小為1G,truncate後的大小預設為10M

    ▲innodb_undo_tablespaces:設定undo獨立表空間個數,範圍為0-128, 預設為0,0表示表示不開啟獨立undo表空間 且 undo日誌儲存在ibdata檔案中。該引數只能在最開始初始化MySQL例項的時候指定,如果例項已建立,這個引數是不能變動的,如果在資料庫配置文 件 .cnf 中指定innodb_undo_tablespaces 的個數大於例項建立時的指定個數,則會啟動失敗,提示該引數設定有誤,如果設定了該引數為n(n>0),那麼就會在undo目錄下建立n個undo檔案(undo001,undo002 …… undo n),每個檔案預設大小為10M.

我們什麼時候需要設定這個引數呢?

  當DB寫壓力較大時,可以設定獨立UNDO表空間,把UNDO LOG從ibdata檔案中分離開來,指定 innodb_undo_directory目錄存放,可以制定到高速磁碟上,加快UNDO LOG 的讀寫效能。

    ▲innodb_undo_log_truncate:InnoDB的purge執行緒,根據innodb_undo_log_truncate設定開啟或關閉、innodb_max_undo_log_size的引數值,以及truncate的頻率來進行空間回收和 undo file 的重新初始化,該引數生效的前提是,已設定獨立表空間且獨立表空間個數大於等於2個

3. undo空間管理

  如果需要設定獨立表空間,需要在初始化資料庫例項的時候,指定獨立表空間的數量、UNDO內部由多個回滾段組成,即 Rollback segment,一共有128個,儲存在ibdata系統表空間中,分別從resg slot0 - resg slot127,每一個resg slot,也就是每一個回滾段,內部由1024個undo segment 組成。

回滾段(rollback segment)分配如下:

slot 0 ,預留給系統表空間;
slot 1- 32,預留給臨時表空間,每次資料庫重啟的時候,都會重建臨時表空間;
slot33-127,如果有獨立表空間,則預留給UNDO獨立表空間;如果沒有,則預留給系統表空間;
回滾段中除去32個提供給臨時表事務使用,剩下的 128-32=96個回滾段,可執行 96*1024 個併發事務操作,每個事務佔用一個 undo segment slot,注意,如果事務中有臨時表事務,還會在臨時表空間中的 undo segment slot 再佔用一個 undo segment slot,即佔用2個undo segment slot。如果錯誤日誌中有:Cannot find a free slot for an undo log。則說明併發的事務太多了,需要考慮下是否要分流業務。

回滾段(rollback segment )採用 輪詢排程的方式來分配使用,如果設定了獨立表空間,那麼就不會使用系統表空間回滾段中undo segment,而是使用獨立表空間的,同時,如果回顧段正在 Truncate操作,則不分配

4.redo?

  當資料庫對資料做修改的時候,需要把資料頁從磁碟讀到buffer pool中,然後在buffer pool中進行修改,那麼這個時候buffer pool中的資料頁就與磁碟上的資料頁內容不一致,稱buffer pool的資料頁為dirty page 髒資料,如果這個時候發生非正常的DB服務重啟,那麼這些資料還在記憶體,並沒有同步到磁碟檔案中(注意,同步到磁碟檔案是個隨機IO),也就是會發生資料丟失,如果這個時候,能夠在有一個檔案,當buffer pool 中的data page變更結束後,把相應修改記錄記錄到這個檔案(注意,記錄日誌是順序IO),那麼當DB服務發生crash的情況,恢復DB的時候,也可以根據這個檔案的記錄內容,重新應用到磁碟檔案,資料保持一致。這個檔案就是redo log ,用於記錄 資料修改後的記錄,順序記錄.

4.1 redo 引數

  ▲innodb_log_files_in_group:redo log 檔案的個數,命名方式如:ib_logfile0,iblogfile1… iblogfilen。預設2個,最大100個。

  ▲innodb_log_file_size:檔案設定大小,預設值為 48M,最大值為512G,注意最大值指的是整個 redo log系列檔案之和,即(innodb_log_files_in_group * innodb_log_file_size )不能大於最大值512G。

  ▲innodb_log_group_home_dir:檔案存放路徑

  ▲innodb_log_buffer_size:Redo Log 快取區,預設8M,可設定1-8M。延遲事務日誌寫入磁碟,把redo log 放到該緩衝區,然後根據 innodb_flush_log_at_trx_commit引數的設定,再把日誌從buffer 中flush 到磁碟中

  █innodb_flush_log_at_trx_commit:作用如下圖所示:

  

   補充一下:這裡有一個fsync來重新整理I/O快取

    ==0 ###表示事務提交時,Innodb不會立即觸發將快取日誌寫到磁碟,而是每秒觸發一次快取日誌先回寫檔案系統快取中,然後立即呼叫作業系統fsync重新整理IO快取到磁碟檔案

   ==1 ### 表示當事務提交時,Innodb立即觸發將快取日誌寫到磁碟的檔案系統快取中,然後立即呼叫作業系統fsync重新整理io快取到磁碟檔案

   ==2 ### 表示當事務提交時,Innodb立即觸發將快取日誌寫到磁碟的檔案系統快取中,然後不會立即觸發重新整理快取,而是每秒觸發重新整理快取的。

4.2 redo空間管理

  Redo log檔案以ib_logfile[number]命名,Redo log 以順序的方式寫入檔案檔案,寫滿時則回溯到第一個檔案,進行覆蓋寫。(但在做redo checkpoint時,也會更新第一個日誌檔案的頭部checkpoint標記,所以嚴格來講也不算順序寫)。
實際上redo log有兩部分組成:redo log buffer 跟redo log file。buffer pool中把資料修改情況記錄到redo log buffer,出現以下情況,再把redo log buffer刷下到redo log file:

Redo log buffer空間不足
事務提交(依賴innodb_flush_log_at_trx_commit引數設定)
後臺執行緒
做checkpoint
例項shutdown
binlog切換