facebook的mark大神最近一直在測試5.6的性能,并且發現了不少問題. 看來facebook是要跳過5.5,直接上5.6了。同為網際網路行業,facebook的許多需求和我們是類似的,online ddl, 熱點資料更新問題等。。。
當然,我最關注的還是5.6存在的bug。
related blog:
<a href="http://mysqlha.blogspot.com/2013/03/mysql-56-cached-update-only-workload.html">http://mysqlha.blogspot.com/2013/03/mysql-56-cached-update-only-workload.html</a>
<a href="http://mysqlha.blogspot.com/2013/03/mysql-56-no-odirectnofsync-for-you.html">http://mysqlha.blogspot.com/2013/03/mysql-56-no-odirectnofsync-for-you.html</a>
related bug:
<a href="http://bugs.mysql.com/bug.php?id=45892">http://bugs.mysql.com/bug.php?id=45892</a>
提到兩個問題,一個是從5.6.7開始innodb_flush_method有一個新值:o_direct_no_fsync。他的含義也很簡單。當檔案被設定為o_direct時,如果将其設定為o_direct_no_fsync時,就無需在寫檔案後,再做一次flush(實際上是随後的調用邏輯性能太差了,而不僅僅是fsync很慢的緣故)。
從函數fil_flush可以很清晰的看到,fil_buffering_disabled為true時,很快就釋放全局鎖fil_system->mutex,傳回。根據mark的測試,其性能提升也非常理想:
update-only & io-bound workload
updates/second for update 1 row by pk via sysbench
8 16 32 64 128 256 concurrent clients
18234 24359 10379 9795 9843 10283 o_direct
17996 26853 30265 28923 29293 29477 o_direct_no_fsync
可惜的是,這種設定隻對部分檔案系統是安全的,一些檔案系統,例如xfs,即使設定了o_direct,還需要将metadata資訊fsync到磁盤。另外當free list為空時(髒頁太快,page cleaner跟不上),使用者線程可能去從lru擷取一個空閑block,這會導緻如下backtrace。
os_thread_sleep,fil_flush,fil_flush_file_spaces,buf_flush_sync_datafiles,
buf_flush_single_page_from_lru,buf_lru_get_free_block,
buf_page_init_for_read,buf_read_page_low,..
這種場景發生在io-bound負載下,即使在掃描lru也沒有發現非髒block可以轉移到free list後,會去嘗試從lru尾部刷一個髒block(buf_flush_single_page_from_lru),然後将其放到free list上,這其中如果包含了sync操作,顯然會大大的影響使用者線程的性能。
buf_flush_list, log_preflush_pool_modified_pages, log_checkpoint_margin, log_check_margins, log_free_check, row_upd, row_upd_step, row_update_for_mysql, ha_innobase::update_row
當更新記錄時,由于要寫redo log,需要確定buffer有足夠的空間(log_free_check),是否需要刷日志由log_sys->check_flush_or_checkpoint來标記,當為true時,表示可能有log需要刷磁盤,或者需要 preflush buffer pool page,或者需要做一次checkpoint。當lsn – last_checkpoint_lsn >max_checkpoint_age時候,這個值必須為true。
注意在log_free_check中檢查check_flush_or_checkpoint時未持有log_sys->mutex。
在判斷是否需要做checkpoint時(log_checkpoint_margin),如果髒頁的lsn範圍(從每個bp instance的flush list上檢視)大于max_modified_age_sync了,需要去做刷髒頁操作(log_preflush_pool_modified_pages)
mark指出的問題是,如果有線程在做flush,後來的線程進入log_preflush_pool_modified_pages,輪詢每個bp instance,如果每個bp都正在做flush,那麼就會傳回false,可能會去強制将log_sys->check_flush_or_checkpoint設定為true,後面新來的線程是以可能持續的進入log_preflush_pool_modified_pages->buf_flush_list函數去輪詢每個bp instance,有任意一個bp instance正在被重新整理,都會導緻傳回值為false。線程在将log_sys->check_flush_or_checkpoint這樣一個全局可見的變量設定為true後會繼續loop。
讨論還在繼續,持續關注中….