Latch導致MySQL Crash
沃趣科技高階資料庫專家 董 紅 禹
一、問題概述
最近我們遇到一個MySQL的問題,分析後很有代表意義,特地寫出來供大家參考。
出現問題是,資料庫先是被置為只讀,然後過了一段時間,MySQL直接Crash掉了
發生Crash時MySQL的error日誌中列印了以下內容:
- ----------
- SEMAPHORES
- ----------
- OS WAIT ARRAY INFO: reservation count 1246555
- --Thread 140363572082432 has waited at row0upd.cc line 2354 for 253.00 seconds the semaphore:
- X-lock (wait_ex) on RW-latch at 0x7fa949340740 created in file buf0buf.cc line 1069
- a writer (thread id 140363572082432) has reserved it in mode wait exclusive
- number of readers 1, waiters flag 1, lock_word: ffffffffffffffff
- Last time read locked in file btr0sea.cc line 931
- Last time write locked in file /export/home/pb2/build/sb_0-17068951-1447697721.44/mysql-5.6.28/storage/innobase/row/row0upd.cc line 2354
根據日誌中我們可以看到,執行緒140363572082432要對記錄上一個X鎖,但是等待0x7fa949340740執行緒的RW-latch的釋放
我們在向下看查詢到如下資訊(涉及到使用者資訊 謂詞就用xxx代替):
- 173 lock struct(s), heap size 30248, 7925 row lock(s), undo log entries 7924
- MySQL thread id 5709783, OS thread handle 0x7fa8f0da7700, query id 92213034 10.23.163.54 citicqyh updating
- update TB_DEPARTMENT_INFO set TOTAL_USER=1 where ID='ac84f17e-82d3-4519-a1da-0d5a5a835d44'
- ---TRANSACTION 53065242, ACTIVE 313 sec fetching rows, thread declared inside InnoDB 2081
- mysql tables in use 2, locked 0
- MySQL thread id 5428690, OS thread handle 0x7fa8f0136700, query id 92213061 10.23.163.55 citicqyh Sending data
- SELECT COUNT(DISTINCT r.user_id) FROM TB_DEPARTMENT_INFO d left join tb_qy_user_department_ref r on r.department_id = d.id WHERE d.org_id = 'xxx' AND (d.dept_full_name LIKE 'xxx%' or d.dept_full_name = 'xxx
- Trx read view will not see trx with id >= xxx, sees < xxx
- ......還有很多select語句省略
根據上面資訊我們去資料庫中檢視了這些select語句,發現執行計劃都是全表掃描。
首先資料庫變成了只讀,最後資料庫crash了,crash輸出的資訊如下:
- ----------------------------
- END OF INNODB MONITOR OUTPUT
- ============================
- InnoDB: ###### Diagnostic info printed to the standard error stream
- InnoDB: Error: semaphore wait has lasted > 600 seconds
- InnoDB: We intentionally crash the server, because it appears to be hung.
- 7fa8f9580700 InnoDB: Assertion failure in thread 140363714529024 in file srv0srv.cc line 1754
- InnoDB: We intentionally generate a memory trap.
- InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
- InnoDB: If you get repeated assertion failures or crashes, even
- InnoDB: immediately after the mysqld startup, there may be
- InnoDB: corruption in the InnoDB tablespace. Please refer to
- InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html
- InnoDB: about forcing recovery.
InnoDB: Error: semaphore wait has lasted > 600 seconds 提示600秒沒有響應 資料庫選擇了Crash 強制重啟
從報錯資訊來看:
- update語句需要在記錄上面加X鎖,但是必須等待RW-Latch的釋放
- 由於有大量的select語句是全表掃描,一直佔用latch沒有釋放,update遲遲競爭不到RW-latch
- Innodb 的Diagnostic執行緒檢查到RW-Latch等待超過了600秒還沒有返回,認為系統出現了嚴重問題,於是觸發了MySQL服務的Crash。
二、進一步分析
這裡首先需要補充一下Latch的概念:Latch在MySQL中是用於保護高速緩衝區中共享資料的,舉個例子:
當我們執行select時,資料是快取在buffer pool中的,多個執行緒併發訪問或者修改這個資料必然需要一個併發控制機制,這個就是Latch
大家知道,資料庫要訪問的資料都必須先存在快取中,而快取一般比磁碟空間要小,資料快取使用hash表來記錄資料頁是否在記憶體中。在Oracle中的併發控制比較精細:首先會對hash桶加latch,並根據hash桶查詢對應的資料並加上pin,然後釋放Latch。而MySQL相對沒有控制得這麼精細,對應的RW-Latch在errlog中說的很清楚,該RW-Latch是在buf0buf.cc的1069行建立的
RW-latch at 0x7fa949340740 created in file buf0buf.cc line 1069
對應的程式碼摘錄如下:
- rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
跟蹤原始碼,知道這個Latch是MySQL在資料庫啟動,初始化 innodb_buffer_pool時,將Latch建立好的。對應的函式呼叫過·程:
- buf_pool_init_instance()->buf_chunk_init()->buf_block_init()
正是由於這個RW-Latch被長時間佔用了,其他的執行緒一直競爭不到,才導致了這個問題
三、修復建議
這類問題的發生多數都是因為SQL寫的不好,在表上面進行了大量的全表掃描佔用了大量的Latch,解決方案就是避免SQL長時間佔用latch:
- 修改select查詢避免全表掃描,避免latch長期被佔用
- 適當的加索引,讓select執行更快,也避免一個select鎖的資料更少
- 適當加大buffer pool instance,每個buffer pool都有自己獨立的Latch,避免latch競爭。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-2102421/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 故障分析 | MySQL : slave_compressed_protocol 導致 crashMySqlProtocol
- 【MySQL】一條SQL使磁碟暴漲並導致MySQL CrashMySql
- 故障分析 | MySQL 5.7 使用臨時表導致資料庫 CrashMySql資料庫
- 如何定位導致Crash的程式碼位置
- 執行SQL語句導致mysqld的crashMySql
- vip/public ip斷網,導致instance crash
- 系統crash掉導致ORA-00600的處理
- latch 相關效能問題診斷: latch: row cache objects等待事件導致CPU負載高Object事件負載
- openGauss 由於RemoveIPC未關閉導致資料庫crashREM資料庫
- 【MySQL】表索引損壞致Crash及修復過程一則MySql索引
- 早上MYSQL突然 CRASHMySql
- 【Mysql】JDB2導致磁碟io使用率高 導致mysql延遲過高MySqlDB2
- MySQL For Update導致全表排他鎖MySql
- MySQL Flush導致的等待問題MySql
- mysql crash with disk sector errorMySqlError
- 【Mysql】mysql主鍵的缺少導致備庫hangMySql
- fusion-io 卡使用率 100% 導致 Oracle RAC instance crash 問題Oracle
- Mysql 會導致索引失效的情況MySql索引
- MySQL:MySQL客戶端快取結果導致OOMMySql客戶端快取OOM
- MySQL:Analyze table導致'waiting for table flush'MySqlAI
- MYSQL order by排序導致效率低小優化MySql排序優化
- MySQL8.0 view導致的效能問題MySqlView
- mysql主鍵的缺少導致備庫hangMySql
- MySQL時區導致無法產生表MySql
- MySQL crash recovery恢復慢分析MySql
- MySQL InnoDB Update和Crash Recovery流程MySql
- 核心資料庫由於大量的latch free導致CPU資源耗盡的現場資料庫
- Oracle10.2.0.3 fox aix 上 In memory undo latch導致高CPU佔用問題解決OracleAI
- 【MySQL】MySQL5.6新特性之crash-safeMySql
- mysql的新建索引會導致insert被lockedMySql索引
- MySQL 網路導致的複製報錯案例MySql
- MySQL Bug導致異常當機的分析流程MySql
- swap空間不足導致mysql被OOM kill案例MySqlOOM
- innodb_undo_tablespaces導致Mysql啟動報錯MySql
- MySQL latch爭用深入分析MySql
- MySQL 的 crash-safe 原理解析MySql
- MySQL Case-時間問題導致MySQL例項批次當機MySql
- MySQL 5.6因為OOM導致資料庫重啟MySqlOOM資料庫