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

案例描述:mysql

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

1、理論知識數據庫

一、關於commit原理,事務提交過程服務器

  一、尋找修改的數據頁:網絡

    一、若是該數據頁在內存中,則直接是內存讀;異步

    二、若是該數據頁內存中沒有,物理讀,就從磁盤調入內存;ide

  二、磁盤中的undo頁調入內存;性能

  三、先將原來的數據存入undo,而後修改數據(數據頁成髒頁);優化

  四、修改數據的信息生成redo數據存入log_buffer(內存buffer_pool的一個空間,默認16M)中;spa

複製代碼

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

複製代碼

  五、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)

複製代碼

  六、事務提交,刻意觸發log線程,將剩餘的log_buffer中的redo數據信息寫入磁盤中,數據量已剩很少,寫完提交成功。

注意:

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

    「日誌先行」,這是數據庫最基本的原則。

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

  三、意外掉電,內存髒頁丟失,可是磁盤的innodb_log_file中存放了redo日誌信息,待重啓服務器,MySQL經過讀取磁盤的log_files數據,自動將數據的修改從新跑一邊。

Q:爲何mysql commit速度老是很快,儘管事務修改的數據量可能很大?

A:

  由於事務提交,並非對磁盤數據進行修改,而是將修改數據的redo信息經過後臺log線程寫入磁盤的redo logfile中,完成mysql commit,不管事務修改的數據量有多大,這個過程速度是很快的。

  而內存中的髒塊,也就是修改後的數據頁,正常狀況下是由後臺相關write線程週期性的將髒頁數據刷入磁盤中,保證innodb buffer pool有足夠的乾淨塊、可用塊。

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

  一、MySQL讀取內存中undo頁信息

  二、經過undo信息找到髒頁,反着對數據進行修改

  三、do、undo的時間相同,且都會產成redo信息

  四、事務提交

MySQL回滾處理機制:

  若是線程中斷,事務沒有提交,undo會將記錄此信息,待另外一會話進程連上,查看該塊數據信息,MySQL自動回滾進行數據頁修改,而後被讀取。也就是說爲了不繫統由於rollback被hang住,經過直接殺死進程的方式,中斷事務,等待後來者要讀取該數據信息時進行回滾,再返回結果。

Q:rollback爲何有時候很慢,rollback的風險和風險避免方式?

A:

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

  一、rollback風險:容易致使系統被hang住;

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

三、存儲寫入性能分析

Q:mysql commit,存儲爲何寫速度可以保持在0ms,極少出現1ms狀況?

A:

  對於存儲來講,寫性能至關高:假設存儲cache總有空閒空間的狀況下,事務提交,將log buffer中剩餘的不多的redo數據寫入存儲cache,即爲完成mysql commit,這個過程是至關快的(可以保持在0ms,極少出現1ms狀況),後續redo數據由cache寫入磁盤的過程是後臺進行。

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

  一、災備同步過程:commit

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

    二、經過網絡同步binlog寫入遠端同步的服務器的存儲cache中;

    三、響應本地數據庫;

    四、事務提交成功;

  二、風險:

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

  三、解決:

    經過超時設置,網絡中斷超過限制,自動將同步改成災備異步,儘量少的影響業務commit超時失敗。

 

2、分析與處理

  存儲寫性能比較差,不少時段會達到5ms,甚至於10ms以上

    備註:災備同步已經中止的狀況下。

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

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

二、cache被佔滿

  一、海量數據寫入,commit數據佔滿cache;

  二、硬盤I/O異常,異常SQL致使的海量物理讀;

  解決:索引優化。

三、存儲性能差

  解決:找老闆掏錢,更換優質設備。

相關文章
相關標籤/搜索