天天看點

MySQL核心月報 2014.10-MySQL· 捉蟲動态·從庫OOM

<b>bug背景</b>

人為直接的連上從庫 alter 表

<b>bug分析</b>

為啥資料類型不一緻會導緻 oom 呢?oom 表示程式在持續申請記憶體,把記憶體給用爆了。從庫的slave thread在應用rows_log_event時,如果發現主庫的表和從庫的表不相容,就會建立一個臨時中間表,做資料轉化:

在此過程中用的臨時表結構和field字段都是從thd的mem_root配置設定的,而每個rows_log_event應用時配置設定記憶體空間再do_apply_event後就不會再用了,但是 rows_log_event::do_apply_event() 結束後并沒有free_root釋放,而是在事務所有event做完後釋放的。類似下面這種包含大量更新語句的事務,每一個更新對應一個rows_log_event,備庫在應用時,在事務執行中間所有申請的記憶體都會保持,如果語句非常多的話,就導緻oom了。

<b>bug 修複</b>

像 query_log_event::do_apply_event() 在結束會調用free_root,來釋放thd-&gt;mem_root空間,而rows_log_event::do_apply_event()卻不能這樣幹,因為在下面的場景下,使用者的線程會調用 rows_log_event::do_apply_event()

mysqlbinlog mysql-bin.00000x | mysql -hxxxx -pxx -u

如果在中間釋放使用者線程的thd-&gt;mem_root的話,會有問題。

是以官方的修複方法是在log_event類構造函數初始化一個屬于log_event的 mem_root

在析構函數裡釋放

然後把rows_log_event::do_apply_event()本來從thd-&gt;mem_root申請的記憶體改為從自身的 m_event_mem_root 申請,這樣每個event應用完,被delete時其轉化過程中申請的記憶體也一并被釋放,避免了oom的産生。