1. 程式人生 > >關於MySQL的commit非規律性失敗案例的深入分析 關於MySQL的commit非規律性失敗案例的深入分析

關於MySQL的commit非規律性失敗案例的深入分析 關於MySQL的commit非規律性失敗案例的深入分析

關於MySQL的commit非規律性失敗案例的深入分析

 

案例描述:

  一個普通的事務提交,在應用裡面會提示commit超時,失敗。

一、理論知識

1、關於commit原理,事務提交過程

  1、尋找修改的資料頁:

    1、如果該資料頁在記憶體中,則直接是記憶體讀;

    2、如果該資料頁記憶體中沒有,物理讀,就從磁碟調入記憶體;

  2、磁碟中的undo頁調入記憶體;

  3、先將原來的資料存入undo,然後修改資料(資料頁成髒頁);

  4、修改資料的資訊生成redo資料存入log_buffer(記憶體中的一個空間,預設16M)中;

mysql> show variables like '%log_buffer%';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.01 sec)

  5、log_buffer通過log執行緒(後臺執行緒,非常勤快),持續不斷的將redo資訊寫入disk的innodb_log_file中;

mysql> show variables like 'innodb_log_file%';
+---------------------------+----------+
| Variable_name             | Value    |
+---------------------------+----------+
| innodb_log_file_size      | 50331648 |
| innodb_log_files_in_group | 2        |
+---------------------------+----------+
2 rows in set (0.01 sec)

  6、事務提交,刻意觸發log執行緒,將剩餘的log_buffer中的redo資料資訊寫入磁碟中,資料量已剩不多,寫完提交成功。

注意:

  1、修改記錄前,一定要先寫日誌;

    “日誌先行”,這是資料庫最基本的原則。

  2、事務提交過程中,一定要保證日誌先落盤,才能算事務提交完成。

  3、意外掉電,記憶體髒頁丟失,但是磁碟的innodb_log_file中存放了redo日誌資訊,待重啟伺服器,MySQL通過讀取磁碟的log_files資料,自動將資料的修改重新跑一邊。

Q:為什麼mysql commit速度總是很快,儘管事務修改的資料量可能很大?

A:

  因為事務提交,並不是對磁碟資料進行修改,而是將修改資料的redo資訊通過後臺log執行緒寫入磁碟的redo logfile中,完成mysql commit,無論事務修改的資料量有多大,這個過程速度是很快的。

  而記憶體中的髒塊,也就是修改後的資料頁,正常情況下是由後臺相關write執行緒週期性的將髒頁資料刷入磁碟中,保證innodb buffer pool有足夠的乾淨塊、可用塊。

2、關於rollback原理,回滾過程

  1、MySQL讀取記憶體中undo頁資訊

  2、通過undo資訊找到髒頁,反著對資料進行修改

  3、do、undo的時間相同,且都會產成redo資訊

  4、事務提交

MySQL回滾處理機制:

  如果執行緒中斷,事務沒有提交,undo會將記錄此資訊,待另一會話程序連上,檢視該塊資料資訊,MySQL自動回滾進行資料頁修改,然後被讀取。也就是說為了避免系統因為rollback被hang住,通過直接殺死程序的方式,中斷事務,等待後來者要讀取該資料資訊時進行回滾,再返回結果。

Q:rollback為什麼有時候很慢,rollback的風險和風險避免方式?

A:

  rollback的時間取決於回滾前事務修改資料的時間,處理量大回滾時間長,處理量小回滾時間短。

  1、rollback風險:容易導致系統被hang住;

  2、風險避免方式:直接殺死會話程序或是mysql程序。

3、儲存寫入效能分析

Q:mysql commit,儲存為什麼寫速度能夠保持在0ms,極少出現1ms情況?

A:

  對於儲存來說,寫效能相當高:假設儲存cache總有空閒空間的情況下,事務提交,將log buffer中剩餘的很少的redo資料寫入儲存cache,即為完成mysql commit,這個過程是相當快的(能夠保持在0ms,極少出現1ms情況),後續redo資料由cache寫入磁碟的過程是後臺進行。

4、儲存級別的災備(同城災備)

  1、災備同步過程:commit

    1、redo、binlog寫入本地儲存cache;

    2、通過網路同步binlog寫入遠端同步的伺服器的儲存cache中;

    3、響應本地資料庫;

    4、事務提交成功;

  2、風險:

    網路出現問題(訊號斷續,纜線斷了),導致寫hang住,commit超時失敗。

  3、解決:

    通過超時設定,網路中斷超過限制,自動將同步改為災備非同步,儘可能少的影響業務commit超時失敗。

 

二、分析與處理

  儲存寫效能比較差,很多時段會達到5ms,甚至於10ms以上

    備註:災備同步已經停止的情況下。

1、儲存中BBU問題,出現監控BBU的bug;

  解決:重啟BBU,不行就更新BBU。

2、cache被佔滿

  1、海量資料寫入,commit資料佔滿cache;

  2、硬碟I/O異常,異常SQL導致的海量物理讀;

  解決:索引優化。

3、儲存效能差

  解決:找老闆掏錢,更換優質裝置。

@author:http://www.cnblogs.com/geaozhang/

案例描述:

  一個普通的事務提交,在應用裡面會提示commit超時,失敗。

一、理論知識

1、關於commit原理,事務提交過程

  1、尋找修改的資料頁:

    1、如果該資料頁在記憶體中,則直接是記憶體讀;

    2、如果該資料頁記憶體中沒有,物理讀,就從磁碟調入記憶體;

  2、磁碟中的undo頁調入記憶體;

  3、先將原來的資料存入undo,然後修改資料(資料頁成髒頁);

  4、修改資料的資訊生成redo資料存入log_buffer(記憶體中的一個空間,預設16M)中;

mysql> show variables like '%log_buffer%';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.01 sec)

  5、log_buffer通過log執行緒(後臺執行緒,非常勤快),持續不斷的將redo資訊寫入disk的innodb_log_file中;

mysql> show variables like 'innodb_log_file%';
+---------------------------+----------+
| Variable_name             | Value    |
+---------------------------+----------+
| innodb_log_file_size      | 50331648 |
| innodb_log_files_in_group | 2        |
+---------------------------+----------+
2 rows in set (0.01 sec)

  6、事務提交,刻意觸發log執行緒,將剩餘的log_buffer中的redo資料資訊寫入磁碟中,資料量已剩不多,寫完提交成功。

注意:

  1、修改記錄前,一定要先寫日誌;

    “日誌先行”,這是資料庫最基本的原則。

  2、事務提交過程中,一定要保證日誌先落盤,才能算事務提交完成。

  3、意外掉電,記憶體髒頁丟失,但是磁碟的innodb_log_file中存放了redo日誌資訊,待重啟伺服器,MySQL通過讀取磁碟的log_files資料,自動將資料的修改重新跑一邊。

Q:為什麼mysql commit速度總是很快,儘管事務修改的資料量可能很大?

A:

  因為事務提交,並不是對磁碟資料進行修改,而是將修改資料的redo資訊通過後臺log執行緒寫入磁碟的redo logfile中,完成mysql commit,無論事務修改的資料量有多大,這個過程速度是很快的。

  而記憶體中的髒塊,也就是修改後的資料頁,正常情況下是由後臺相關write執行緒週期性的將髒頁資料刷入磁碟中,保證innodb buffer pool有足夠的乾淨塊、可用塊。

2、關於rollback原理,回滾過程

  1、MySQL讀取記憶體中undo頁資訊

  2、通過undo資訊找到髒頁,反著對資料進行修改

  3、do、undo的時間相同,且都會產成redo資訊

  4、事務提交

MySQL回滾處理機制:

  如果執行緒中斷,事務沒有提交,undo會將記錄此資訊,待另一會話程序連上,檢視該塊資料資訊,MySQL自動回滾進行資料頁修改,然後被讀取。也就是說為了避免系統因為rollback被hang住,通過直接殺死程序的方式,中斷事務,等待後來者要讀取該資料資訊時進行回滾,再返回結果。

Q:rollback為什麼有時候很慢,rollback的風險和風險避免方式?

A:

  rollback的時間取決於回滾前事務修改資料的時間,處理量大回滾時間長,處理量小回滾時間短。

  1、rollback風險:容易導致系統被hang住;

  2、風險避免方式:直接殺死會話程序或是mysql程序。

3、儲存寫入效能分析

Q:mysql commit,儲存為什麼寫速度能夠保持在0ms,極少出現1ms情況?

A:

  對於儲存來說,寫效能相當高:假設儲存cache總有空閒空間的情況下,事務提交,將log buffer中剩餘的很少的redo資料寫入儲存cache,即為完成mysql commit,這個過程是相當快的(能夠保持在0ms,極少出現1ms情況),後續redo資料由cache寫入磁碟的過程是後臺進行。

4、儲存級別的災備(同城災備)

  1、災備同步過程:commit

    1、redo、binlog寫入本地儲存cache;

    2、通過網路同步binlog寫入遠端同步的伺服器的儲存cache中;

    3、響應本地資料庫;

    4、事務提交成功;

  2、風險:

    網路出現問題(訊號斷續,纜線斷了),導致寫hang住,commit超時失敗。

  3、解決:

    通過超時設定,網路中斷超過限制,自動將同步改為災備非同步,儘可能少的影響業務commit超時失敗。

 

二、分析與處理

  儲存寫效能比較差,很多時段會達到5ms,甚至於10ms以上

    備註:災備同步已經停止的情況下。

1、儲存中BBU問題,出現監控BBU的bug;

  解決:重啟BBU,不行就更新BBU。

2、cache被佔滿

  1、海量資料寫入,commit資料佔滿cache;

  2、硬碟I/O異常,異常SQL導致的海量物理讀;

  解決:索引優化。

3、儲存效能差

  解決:找老闆掏錢,更換優質裝置。