2020-08-14
右玉網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)公司從2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)公司。
集群有三個成員memberA、B、C成,其中memberB意外故障停掉了,然后memberA 執(zhí)行stop group_replication退去集群.此時整個集群不可用了(不能更新數(shù)據(jù))。
集群中唯一剩余的成員memberC上看到的成員狀態(tài)為:
但是memberA看到的狀態(tài)為:
查看最后的存活的memberC的錯誤日志發(fā)現(xiàn):
"Plugin group_replication reported: 'This server is not able to reach a majority of members in the group. This server will now block all updates. The server will remain blocked until contact with the majority is restored. It is possible to use group_replication_force_members to force a new group membership.' "
大概意思是當前的服務(wù)沒法獲取到成員的投票數(shù),當前服務(wù)將會阻塞所有的更新,直到能夠獲取到投票數(shù)??梢允褂胓roup_replication_force_members 來強制組成一個新的組。
開始認為這是MGR功能的一個bug,不過后來想想這樣的設(shè)定也是合理的,因為如果是當前的服務(wù)成員自身網(wǎng)絡(luò)或其他問題導(dǎo)致的無法與其他成員的通信成功,那么這樣的情況下這種設(shè)定也是合理的,因為不能讓它自動重新組成一個組,否則就會可能出現(xiàn)多個重復(fù)的組。對于為什么組成員A執(zhí)行stop group_replication后,剩余的memberC的視圖中memberA還是online狀態(tài),可能是因為memberB已經(jīng)unreachable,所以memberC去請求是否同意memberA退去時沒有得到結(jié)果,一直阻塞等待造成的。此時,memberA的退出結(jié)果應(yīng)該是無法多數(shù)投票通過的,因此memberA的退出結(jié)果應(yīng)該是失敗的。查看memberA的error日志,結(jié)果確實如此:
解決的方法是memberC也執(zhí)行stop group_replication停掉這個組,再重新組成一個新的組。
此時memberA再重新加入就成功了:
結(jié)果:
以此類推,當有多個server組成的group而有多數(shù)成員已經(jīng)意外故障時,導(dǎo)致整個組的停止更新,目前想到的解決的方法就是停掉現(xiàn)在的組,重新組成新的組。
ps:
增加Group Replication System Variables中g(shù)roup_replication_member_expel_timeout的大小,可以避免網(wǎng)絡(luò)問題或執(zhí)行事務(wù)慢造成的錯誤驅(qū)逐。
可以使用 show processlist 命令查看當前所有連接信息。
使用 explain 命令查詢 SQL 語句執(zhí)行計劃。
開啟慢查詢?nèi)罩?,查看慢查詢?SQL。
最近接了一個鍋,進入新公司接手了一個進入交付階段的項目.在code?review的時候發(fā)現(xiàn)很多問題,然后開始修復(fù)bug.
在測試階段突然發(fā)現(xiàn)幾乎所有涉及到更新的操作都失敗,下面貼出異常信息.
第一次 出現(xiàn)的時候百度了一下,猜想可能是多服務(wù)部署資源沖突,重啟服務(wù)故障消失.所以沒有特別重視
第二次 出現(xiàn)的時候只有測試環(huán)境部署,不存在多機資源沖突的問題,猜想是多線程資源交叉導(dǎo)致的,于是給可能導(dǎo)致資源競爭的地方加上了分布式鎖.
由于無法重現(xiàn)故障,所以并沒有確認問題得到解決.
第三次 故障依舊,當發(fā)現(xiàn)問題依然存在的時候,開始認真反思,發(fā)現(xiàn)自己解決問題的思路明顯有問題,過于片面,一直都只在應(yīng)用層面尋求解決問題的辦法,而且解決問題的方式也只是在嘗試百度出來的方法.并沒有去思考更深層的問題.
在Mysql5.5中,information_schema 庫中增加了三個關(guān)于鎖的表(MEMORY引擎);
INNODB_TRX ## 當前運行的所有事務(wù)
INNODB _LOCKS ## 當前出現(xiàn)的鎖
INNODB_LOCK_WAITS ## 鎖等待的對應(yīng)關(guān)系
通過查詢 INNODB_TRX 發(fā)現(xiàn)
當前事務(wù)中又兩個RUNNING狀態(tài)開始時間在一個小時之前
開始一直以為是鎖表了
查看了 INNODB _LOCKS? 事務(wù)信息之后發(fā)現(xiàn)有4行數(shù)據(jù)被鎖住了一直沒有釋放
從這里開始發(fā)現(xiàn)問題了,應(yīng)用已經(jīng)拋了異常,事務(wù)理所當然的應(yīng)該回滾才對,為什么資源依然沒有釋放,導(dǎo)致持續(xù)的阻塞呢?
其實最開始的異常信息就已經(jīng)給出了答案,回到開始的地方,再看異常信息就很清楚了,應(yīng)用里面的異常類是 MySQLTransactionRollBackException
是一個回滾異常, 這就說明在事務(wù)回滾的時候出了問題資源沒有得到釋放
然后開始查詢 MySQLTransactionRollBackException? 相關(guān)的信息
這個時候 innodb_rollback_on_timeout =0(默認配置)這個MySQL的配置開始進入我的視線,
舉個栗子
事務(wù)在鎖等待超時后是回滾事務(wù)內(nèi)所有的statement還是最后一條語句;
0表示rollback最后一條語句,默認值; 有點坑爹啊( 細思極恐 )
1表示回滾事務(wù)內(nèi)所有的statements;(此參數(shù)是只讀參數(shù),需在my.cnf中配置,并且重啟生效;)
吃過一次虧,這次并沒有盲目的相信百度到的信息
于是開始測試
一、驗證innodb_rollback_on_timeout=off的情況
1.session?A
開啟事務(wù),事務(wù)未提交,鎖住id=1的數(shù)據(jù)
2.session B?
開啟事務(wù),執(zhí)行更新id=2的數(shù)據(jù)成功(事務(wù)未提交,鎖住id=2),然后請求id=1等待鎖超時,id=2的數(shù)據(jù)更改為222.
3.session C
請求id=2的數(shù)據(jù)50秒后顯示等待鎖超時
執(zhí)行 SELECT * FROM information_schema.INNODB_TRX;
可發(fā)現(xiàn)有資源一直未釋放,具體到測試數(shù)據(jù)中就是id=2的資源一直被鎖定,線程一直被掛起.
總結(jié):通過實驗基本可以確定是業(yè)務(wù)資源交叉導(dǎo)致死鎖之后資源沒釋放造成的持續(xù)阻塞,
二.驗證innodb_rollback_on_timeout=on
修改配置后將驗證innodb_rollback_on_timeout=off的步驟再走一遍
發(fā)現(xiàn)鎖等待只能在業(yè)務(wù)層面盡量避免
on/off的區(qū)別在于session?C進入時不會持續(xù)阻塞,session B異常后全部回滾