catalog
- 短連接風暴
- 先處理占著連接但是不工作地線程
- 減少連接過程的消耗
- 慢查詢性能問題
- 索引沒有設計好
- 語句沒寫好
- 選錯索引
- QPS突增問題
短連接風暴
正常的短連接:
執行很少sql語句就斷開,下次需要的時候再重連。MySQL建立連接的過程成本很高,包含:網絡連接三次握手、登錄權限判斷、獲得連接的數據讀寫權限。
短連接模型存在風險:一旦數據庫處理得慢一些,連接數就會暴漲。
有兩個方法能夠有損地解決短鏈接風暴問題
先處理占著連接但是不工作地線程
如果連接數,可以優先斷開事務外空閑太久地連接。如果這樣還不夠,再考慮斷開事務內空閑太久的連接。
當一個客戶端處于sleep狀態,它的連接被服務端主動斷開后,客戶端并不會立即知道。而是在客戶端發起下一個請求的時候,才會收到報錯:
ERROR 2013 (HY000): Lost connection to MySQL server during query
有的應用端收到這個錯誤時不會重新連接,而是用這個句柄重試查詢,這回導致從應用端看MySQL一直沒恢復。
減少連接過程的消耗
讓數據庫跳過權限驗證階段。
方法:重啟數據庫,并使用-skip-grant-tables
參數啟動。這樣MySQL就會跳過所有的權限驗證階段,包括連接過程和語句執行過程在內。
這個風險極高。在MySQL8.0版本里,如果啟用-skip-grant-tables
參數,MySQL會默認把--skip-networking
參數打開,表示這時候數據庫只能被本地客戶端連接。
慢查詢性能問題
索引沒有設計好
通過緊急創建索引來解決。
直接執行alter table語句。
假設現在服務是一主一備,主庫A、備庫B,這個方案的大致流程是這樣的:
1、在備庫B上執行set sql_log_bin = off,不寫binlog,然后執行alter table,加上索引
2、執行主備切換
3、主庫是B,備庫是A。在A上執行set sql_log_bin = off,然后執行alter table,加上索引。
語句沒寫好
在之前的文章中,提到過,有時候一些錯誤會導致語句沒有使用上索引。
此時通過改寫sql語句來處理,query_rewrite功能,可以把輸入的一種語句改寫成另外一種模式。
如果我們一開始寫的是:
select * from t where id + 1 = 10000;
可以通過下面代碼增加一個語句改寫規則。
insert into query_rewrite.rewrite_rules(pattern,replacement,pattern_databas) values ("select * from t where id + 1 = ?","db1");
call query_rewrite.flush_rewrite_rules();
call query_rewrite.flush_rewrite_rules()
是讓插入的新規則生效。
選錯索引
應急方案:給語句加上force index;
QPS突增問題
QPS每秒查詢率(Query Per Second) 有時會由于業務高峰或者應用程序bug出現突增。
最好的辦法是讓業務把這個功能下掉,服務自然就會恢復。
下掉一個功能的方法如下:
1、如果是全新業務的bug,如果去欸的那個業務方會下掉這個功能,那么可以從數據庫端直接把白名單去掉
2、如果這個功能使用的是單獨的數據庫用戶,可以用管理員賬號把這個用戶刪掉,然后斷開現有連接。
3、如果這個功能和主體功能是部署在一起的,那么我們只能通過處理語句來限制。可以使用查詢重寫功能,把壓力最大的sql語句直接重寫為"select 1"返回。
下掉一個功能所帶來的副作用如下:
1、如果別的功能里面也用到了這個sql語句模板,會有誤傷
2、很多業務并不是靠著一個語句就能完成完整邏輯,所以單獨把一個語句以select 1的結果返回的話,可能會導致后面的業務邏輯一起失敗。