mysql8 log_status 查詢pos與gtid不一致 bug解析
bug: 102175 已經詳細的介紹了mysql8 log_status 查詢結果出現pos跟gtid 不匹配的情況,導致備份後設定的gtid可能不正確。下面根據bug的描述,去看下程式碼,熟悉下相關的程式碼,按步驟在分析下。
主要的程式碼就是ordered_commit, 這部分中有binlog的組提交,flush sync,commit三個階段。
sync 階段在syncbinlog 後,設定了sync_binlog=1會更新binlog的位置資訊,程式碼如下
if (flush_error == 0 && total_bytes > 0) { DEBUG_SYNC(thd, "before_sync_binlog_file"); std::pair<bool, bool> result = sync_binlog_file(false); sync_error = result.first; } if (update_binlog_end_pos_after_sync) { THD *tmp_thd = final_queue; const char *binlog_file = nullptr; my_off_t pos = 0; while (tmp_thd->next_to_commit != nullptr) tmp_thd = tmp_thd->next_to_commit; if (flush_error == 0 && sync_error == 0) { tmp_thd->get_trans_fixed_pos(&binlog_file, &pos); update_binlog_end_pos(binlog_file, pos); } }
commit階段中,呼叫process_commit_stage_queue進行commit佇列的處理,下面的程式碼更新gtid_executed
/* Handle the GTID of the threads. gtid_executed table is kept updated even though transactions fail to be logged. That's required by slave auto positioning. */ gtid_state->update_commit_group(first);
在update_commit_group 中我們看到需要先獲取一個global_sid_lock的讀鎖 void Gtid_state::update_commit_group(THD *first_thd) { DBUG_TRACE; bool gtid_threshold_breach = false; /* We are going to loop in all sessions of the group commit in order to avoid being taking and releasing the global_sid_lock and sidno_lock for each session. */ DEBUG_SYNC(first_thd, "update_gtid_state_before_global_sid_lock"); global_sid_lock->rdlock(); DEBUG_SYNC(first_thd, "update_gtid_state_after_global_sid_lock"); update_gtids_impl_lock_sidnos(first_thd); for (THD *thd = first_thd; thd != nullptr; thd = thd->next_to_commit) { bool is_commit = (thd->commit_error != THD::CE_COMMIT_ERROR); if (update_gtids_impl_do_nothing(thd) || (!is_commit && update_gtids_impl_check_skip_gtid_rollback(thd))) continue; bool more_trx_with_same_gtid_next = update_gtids_impl_begin(thd); if (!gtid_threshold_breach) gtid_threshold_breach = (thd->owned_gtid.gno > GNO_WARNING_THRESHOLD); if (thd->owned_gtid.sidno == THD::OWNED_SIDNO_GTID_SET) { update_gtids_impl_own_gtid_set(thd, is_commit); } else if (thd->owned_gtid.sidno > 0) { update_gtids_impl_own_gtid(thd, is_commit); } else if (thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS) { update_gtids_impl_own_anonymous(thd, &more_trx_with_same_gtid_next); } else { update_gtids_impl_own_nothing(thd); } update_gtids_impl_end(thd, more_trx_with_same_gtid_next); } update_gtids_impl_broadcast_and_unlock_sidnos(); global_sid_lock->unlock(); if (gtid_threshold_breach) LogErr(WARNING_LEVEL, ER_WARN_GTID_THRESHOLD_BREACH); }
上面是組提交binlog 修改已經gtid修改的情況,下面看下select * from performance_schema.log_status;的情況
透過debug跟蹤可以看到table_log_status::make_row()函式中有相關的鎖情況
/* Lock all resources */ for (it = resources.begin(); it != resources.end(); ++it) { (*it)->lock(); }
透過跟蹤,會執行下面函式,請求binlog log_lock
void Log_resource_binlog_wrapper::lock() { mysql_mutex_lock(binlog->get_log_lock()); }
以及global_sid_lock的寫鎖
void Log_resource_gtid_state_wrapper::lock() { global_sid_lock->wrlock(); }
堆疊如下
mysqld!Log_resource_gtid_state_wrapper::lock() (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/log_resource.cc:89) mysqld!table_log_status::make_row() (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/storage/perfschema/table_log_status.cc:256) mysqld!table_log_status::rnd_next() (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/storage/perfschema/table_log_status.cc:93) mysqld!ha_perfschema::rnd_next(unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/storage/perfschema/ha_perfschema.cc:1641) mysqld!handler::ha_rnd_next(unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/handler.cc:2980) mysqld!TableScanIterator::Read() (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/records.cc:361) mysqld!SELECT_LEX_UNIT::ExecuteIteratorQuery(THD*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_union.cc:1228) mysqld!SELECT_LEX_UNIT::execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_union.cc:1281) mysqld!Sql_cmd_dml::execute_inner(THD*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_select.cc:827) mysqld!Sql_cmd_dml::execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_select.cc:612) mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_parse.cc:4407) mysqld!dispatch_sql_command(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_parse.cc:4988) mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_parse.cc:1836) mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/sql_parse.cc:1320) mysqld!handle_connection(void*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/sql/conn_handler/connection_handler_per_thread.cc:301) mysqld!pfs_spawn_thread(void*) (/Users/xiaoyu.bai/Downloads/mysql-8.0.23/storage/perfschema/pfs.cc:2900) libsystem_pthread.dylib!_pthread_start (Unknown Source:0) libsystem_pthread.dylib!thread_start (Unknown Source:0)
所以在sync後,更新了binlog的值,這個時候查詢log_status,查詢獲取了寫鎖,組提交到commit階段,無法獲取讀鎖,導致沒法更新gtid,所以查詢的log_status是不匹配的,log_status應該在commit,更新gtid後,在獲取鎖資源讀取,也就是bug中提到的擴大鎖範圍。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25719946/viewspace-2901660/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL8:連線查詢MySql
- 關於MySQL8的WITH查詢學習MySql
- 9i 子查詢bug?
- 關於在powershell與cmd查詢vue版本時結果不一致Vue
- 一個oracle查詢引起的bugOracle
- 離線查詢與線上查詢
- 查詢與排序02,折半查詢排序
- mysql查詢去重方法解析MySql
- 查詢dba_jobs_running慢的bug
- Jive筆記8--查詢的Bug (轉)筆記
- jpa動態查詢與多表聯合查詢
- 閃回版本查詢與閃回事務查詢
- [BUG反饋]form表達提交查詢問題ORM
- 11.2.0.2.0 bug? 簡單查詢代價異常
- 第二章 :查詢與排序---------遞迴、查詢與排序補充排序遞迴
- 查詢 分析硬解析較高的sql,SQL
- Elasticsearch 查詢與過濾Elasticsearch
- MongoDB慢查詢與索引MongoDB索引
- 方法快取與查詢快取
- 反向索引與模糊查詢索引
- git stash關於程式碼中bug的查詢使用Git
- shortcut switch in terminal start pos & end pos
- sql語法相關子查詢與非相關子查詢SQL
- BST查詢結構與折半查詢方法的實現與實驗比較
- 域名解析服務查詢工具dnstracerDNS
- exists與in子查詢優化優化
- mySQL多表查詢與事務MySql
- MySQL索引與查詢優化MySql索引優化
- 查詢中的distinct與group by
- 查詢集合操作intersect與minus
- [python]pymongo查詢與修改PythonGo
- 從Oracle 11.2.0.4 BUG到Oracle子查詢展開分析Oracle
- 解決GAT專案Bug:軌跡分析查詢不到資料
- [ORACLE BUG]查詢結果錯誤--臨時表並行Oracle並行
- Oracle閃回查詢,閃回版本查詢與閃回事務查詢的使用區別總結Oracle
- 解Bug之路-記一次JVM堆外記憶體洩露Bug的查詢JVM記憶體洩露
- BUG—Nuget包版本不一致導致程式行為與預期不符
- Spark SQL解析查詢parquet格式Hive表獲取分割槽欄位和查詢條件SparkSQLHive