乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      [MySQL 5.6] MySQL 5.6 group commit 性能測試及內(nèi)部實現(xiàn)流程 | Simple Life

       浸心閣 2016-01-12

      盡管Mariadb以及Facebook在long long time ago就fix掉了這個臭名昭著的問題,但官方直到 MySQL5.6 版本才Fix掉,本文主要關(guān)注三點:

      1.MySQL 5.6的性能如何

      2.在5.6中Group commit的三階段實現(xiàn)流程

       

      新參數(shù)

      MySQL 5.6提供了兩個參數(shù)來控制binlog group commit:

      binlog_max_flush_queue_time

      單位為微妙,用于從flush隊列中取事務(wù)的超時時間,這主要是防止并發(fā)事務(wù)過高,導致某些事務(wù)的RT上升。

      可以閱讀函數(shù)MYSQL_BIN_LOG::process_flush_stage_queue 來理解其功能

       

      binlog_order_commits

      當設(shè)置為0時,事務(wù)可能以和binlog不相同的順序被提交,從下面的測試也可以看出,這會稍微提升點性能,但并不是特別明顯.

       

      性能測試

      老規(guī)矩,先測試看看性能

      sysbench, 全內(nèi)存操作,5個sbtest表,每個表1000000行數(shù)據(jù)

       

      基本配置:

      innodb_flush_log_at_trx_commit=1

      table_open_cache_instances=5

      metadata_locks_hash_instances = 32

      metadata_locks_cache_size=2048

      performance_schema_instrument = ‘%=on’

      performance_schema=ON

      innodb_lru_scan_depth=8192

      innodb_purge_threads = 4

       

      關(guān)閉Performance Schema consumer:

      mysql> update setup_consumers set ENABLED = ‘NO';

      Query OK, 4 rows affected (0.02 sec)

      Rows matched: 12  Changed: 4  Warnings: 0

       

      sysbench/sysbench –debug=off –test=sysbench/tests/db/update_index.lua  –oltp-tables-count=5  –oltp-point-selects=0 –oltp-table-size=1000000 –num-threads=1000 –max-requests=10000000000 –max-time=7200 –oltp-auto-inc=off –mysql-engine-trx=yes –mysql-table-engine=innodb  –oltp-test-mod=complex –mysql-db=test   –mysql-host=$HOST –mysql-port=3306 –mysql-user=xx run

       

      update_index.lua

      threads sync_binlog = 0 sync_binlog = 1 sync_binlog =1binlog_order_commits=0
      1  900  610  620
      20 13,800 7,000 7,400
      60 20,000 14,500 16,000
      120 25,100 21,054 23,000
      200 27,900 25,400 27,800
      400 33,100 30,700 31,300
      600 32,800 31,500 29,326
      1000 20,400 20,200 20,500

      我的機器在壓到1000個并發(fā)時,CPU已經(jīng)幾乎全部耗完。

      可以看到,并發(fā)度越高,group commit的效果越好,在達到600以上并發(fā)時,設(shè)置sync_binlog=1或者0已經(jīng)沒有TPS的區(qū)別。

      但問題是。我們的業(yè)務(wù)壓力很少會達到這么高的壓力,低負載下,設(shè)置sync_binlog=1依舊增加了單個線程的開銷。

       

      另外也觀察到,設(shè)置binlog_max_flush_queue_time對TPS的影響并不明顯。

       

      實現(xiàn)原理

      我們知道,binlog和innodb在5.1及以后的版本中采用類似兩階段提交的方式,關(guān)于group commit問題的前世今生,可以閱讀MATS的博客,講述的非常詳細。嗯,評論也比較有意思。。。。。

       

      以下集中在5.6中binlog如何做group commit。在5.6中,將binlog的commit階段分為三個階段:flush stage、sync stage以及commit stage。5.6的實現(xiàn)思路和Mariadb的思路類似,都是維護一個隊列,第一個進入該隊列的作為leader線程,否則作為follower線程。leader線程收集follower的事務(wù),并負責做sync,follower線程等待leader通知操作完成。

       

      這三個階段中,每個階段都會去維護一個隊列:

      Mutex_queue m_queue[STAGE_COUNTER];

      不同session的THD使用the->next_to_commit來鏈接,實際上,在如下三個階段,盡管維護了三個隊列,但隊列中所有的THD實際上都是通過next_to_commit連接起來了。

       

      在binlog的XA_COMMIT階段(MYSQL_BIN_LOG::commit),完成事務(wù)的最后一個xid事件后,,這時候會進入MYSQL_BIN_LOG::ordered_commit,開始3個階段的流程:

       

      ###flush stage

       

      change_stage(thd, Stage_manager::FLUSH_STAGE, thd, NULL, &LOCK_log)

      |–>stage_manager.enroll_for(stage, queue, leave_mutex) //將當前線程加入到m_queue[FLUSH_STAGE]中,如果是隊列的第一個線程,就被設(shè)置為leader,否則就是follower線程,線程會這其中睡眠,直到被leader喚醒(m_cond_done)

      |–>leader線程持有LOCK_log鎖,從change_state線程返回false.

       

      flush_error= process_flush_stage_queue(&total_bytes, &do_rotate, &wait_queue); //只有l(wèi)eader線程才會進入這個邏輯

      |–>首先讀取隊列,直到隊列為空,或者超時(超時時間是通過參數(shù)binlog_max_flush_queue_time來控制)為止,對讀到的每個線程做flush_thread_caches,將binlog刷到cache中。注意在出隊列的時候,可能還有新的session被append到隊列中,設(shè)置超時的目的也正在于此

      |–>如果是超時,這時候隊列中還有session的話,就取出整個隊列的頭部線程,并將原隊列置空(fetch_queue_for),然后對取出的session進行flush_thread_caches

      |–>判斷總的寫入binlog的byte數(shù)是否超過max bin log size,如果超過了,就設(shè)置rotate標記

       

      flush_error= flush_cache_to_file(&flush_end_pos);

      |–>將I/O Cache中的內(nèi)容寫到文件中

       

      signal_update()  //通知dump線程有新的Binlog

       

      ###sync stage

       

      change_stage(thd, Stage_manager::SYNC_STAGE, wait_queue, &LOCK_log, &LOCK_sync)

      |–>stage_manager.enroll_for(stage, queue, leave_mutex)  //當前線程加入到m_queue[SYNC_STAGE]隊列中,釋放lock_log鎖;同樣的如果是SYNC_STAGE隊列的leader,則立刻返回,否則進行condition wait.

      |–>leader線程加上Lock_sync鎖

       

      final_queue= stage_manager.fetch_queue_for(Stage_manager::SYNC_STAGE);  //從SYNC_STAGE隊列中取出來,并清空隊列,主要用于commit階段

       

      std::pair<bool, bool> result= sync_binlog_file(false);  //刷binlog 文件(如果設(shè)置了sync_binlog的話)

       

      簡單的理解就是,在flush stage階段形成N批的組session,在SYNC階段又會由這N批組產(chǎn)生出新的leader來負責做最耗時的sync操作

       

      ###commit stage

       

      commit階段受到參數(shù)binlog_order_commits限制

      當binlog_order_commits關(guān)閉時,直接unlock LOCK_sync,由各個session自行進入Innodb commit階段(隨后調(diào)用的finish_commit(thd)),這樣不會保證binlog和事務(wù)commit的順序一致,如果你不關(guān)注innodb的ibdata中記錄的binlog信息,那么可以關(guān)閉這個選項來稍微提高點性能

       

      當打開binlog_order_commits時,才會進入commit stage,如下描述的

       

      change_stage(thd, Stage_manager::COMMIT_STAGE,final_queue, &LOCK_sync, &LOCK_commit)

      |–>進入新的COMMIT_STAGE隊列,釋放LOCK_sync鎖,新的leader獲取LOCK_commit鎖,其他的session等待

       

      THD *commit_queue= stage_manager.fetch_queue_for(Stage_manager::COMMIT_STAGE);  //取出并清空COMMIT_STAGE隊列

       

      process_commit_stage_queue(thd, commit_queue, flush_error)

      |–>這里會遍歷所有的線程,然后調(diào)用ha_commit_low->innobase_commit進入innodb層依次提交

       

      完成上述步驟后,解除LOCK_commit鎖

       

      stage_manager.signal_done(final_queue);

      |–>將所有Pending的線程的標記置為false(thd->transaction.flags.pending= false)并做m_cond_done廣播,喚醒pending的線程

       

      (void) finish_commit(the);  //如果binlog_order_commits設(shè)置為FALSE,就會進入這一步來提交存儲引擎層事務(wù); 另外還會更新grid信息

      Innodb的group commit和mariadb的類似,都只有兩次sync,即在prepare階段sync,以及sync Binlog文件(雙一配置),為了保證rotate時,所有前一個binlog的事件的redo log都被刷到磁盤,會在函數(shù)new_file_impl中調(diào)用如下代碼段:
      if (DBUG_EVALUATE_IF(“expire_logs_always”, 0, 1)
      && (error= ha_flush_logs(NULL)))
      goto end;

      ha_flush_logs 會調(diào)用存儲引擎接口刷日志文件

       

      參考文檔

      http://dimitrik./blog/archives/2012/06/mysql-performance-binlog-group-commit-in-56.html

      http://mysqlmusings./2012/06/binary-log-group-commit-in-mysql-56.html

      MySQL 5.6.10 source code

       

      原創(chuàng)文章,轉(zhuǎn)載請注明: 轉(zhuǎn)載自Simple Life

      本文鏈接地址: [MySQL 5.6] MySQL 5.6 group commit 性能測試及內(nèi)部實現(xiàn)流程

      文章的腳注信息由WordPress的wp-posturl插件自動生成


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多