MySQL 集群方案 MySQL + MHA
MHA方案
MHA只負(fù)責(zé)主庫的高可用。主庫發(fā)生故障時,MHA會選擇一個數(shù)據(jù)最接近原主庫的候選主節(jié)點作為新的主節(jié)點,并補齊和之前宕機主庫差異的。補齊之后,再將寫VIP漂移到新主庫上。
MHA腦裂問題
問題點:網(wǎng)絡(luò)抖動觸發(fā)MHA切換后,VIP會漂到了新主庫上。當(dāng)網(wǎng)絡(luò)抖動恢復(fù)后,由于VIP并沒有及時從原主庫上摘除,因此2臺機器同時擁有VIP,同時提供服務(wù),產(chǎn)生了腦裂。
解決方案:為MHA 加入向其他物理機進(jìn)行探測的功能,讓通過對比更多的信息來判斷是網(wǎng)絡(luò)故障還是單機故障。
MySQL
。。。
基于Paxos的MGR版本的MySQL
。。。
基本用法 連接器
查看當(dāng)前所有連接
show processlist;
客戶端如果太長時間沒動靜,連接器就會自動將它斷開。這個時間由參數(shù) 控制的,默認(rèn)為 8 小時。
show variables like 'wait_timeout’;
單位為秒。如果在連接被斷開之后,客戶端再次發(fā)送請求的話,就會收到一個錯誤提醒: Lost to MySQL query。這時候如果就需要重連,再執(zhí)行請求。
客戶端級別的讀寫分離 聲明多個。Dao層進(jìn)行CRUD操作時通過為當(dāng)前線程注入枚舉值。實現(xiàn)ource接口,在upKey()方法中根據(jù)保存的枚舉值返回對應(yīng)的。 基數(shù)統(tǒng)計
通過基數(shù)統(tǒng)計可以判斷當(dāng)前索引添加是否合理。
mysql" data-lang="mysql">show index from <table_name>;
返回結(jié)果
MySQL誤用索引
四種方式修正索引,推薦順序由上到下。
添加索引或字段
方法一、大表時優(yōu)先考慮 gh-ost 或者pt---這樣的第三方方案,更加穩(wěn)妥。
原理:
gh-ost創(chuàng)建與原始表相似的幽靈表“源表名_gho”。增量地將數(shù)據(jù)從原始表分批次插入復(fù)制到幽靈表中(默認(rèn)1000條一次,–chunk-size=1000)。與此同時,另一個線程讀取將正在進(jìn)行的更改操作同步到幽靈表中。最后鎖定原始表,待完全追上后,將原始表替換為ghost表。
方法二、MySQL 5.6 以后,使用 DDL。
ALTER TABLE t1 ADD COLUMN x INT, ALGORITHM=INPLACE;
方法三、.0以后,alter語句加時間。非高峰期執(zhí)行,失敗后間隔一段時間繼續(xù)重試。
alter table table_nam wait 10 add column`
方法四、在從庫上執(zhí)行,然后主從切換。屬于傳統(tǒng)方案,容易操作失誤,但效率最高。
方法五、建空表后通過觸發(fā)器等刷新數(shù)據(jù)。
# 創(chuàng)建新表
CREATE TABLE main_table_new LIKE main_table;
# 在新表上添加字段或索引
ALTER TABLE main_table_new ADD COLUMN location VARCHAR(256);
# 復(fù)制舊表數(shù)據(jù)到新表
INSERT INTO main_table_new SELECT *, NULL FROM main_table;
# 重命名新表和舊表
RENAME TABLE main_table TO main_table_old, main_table_new TO main_table;
# 刪除舊表
DROP TABLE main_table_old;
健康檢查
1 語句返回成功只能說明數(shù)據(jù)庫的進(jìn)程還在。另外,當(dāng)日志滿了后,數(shù)據(jù)庫還是能提供查詢功能。所以查詢語句也不能用來判斷。
最好的解決方法是自建系統(tǒng)表
update health_check set t_modified=now();
如果是雙主架構(gòu),為了避免雙主同步時造成沖突,可以在表上再添加字段作為標(biāo)識。
SQL優(yōu)化
通過 分析 SQL 執(zhí)行計劃字段默認(rèn)值為系統(tǒng)當(dāng)前日期,返回的字段含義如下所述:
:可能使用到的索引。key:實際使用到的索引。:當(dāng)前使用的索引的長度。ref:關(guān)聯(lián) id 等信息。rows:掃描的行數(shù)。:結(jié)果集占總掃描記錄數(shù)的比例。Extra:額外信息。 語句僅停留在分析階段,不表示真實執(zhí)行狀態(tài)。 show (已棄用)
和紙上談兵不同,show 語句用于分析sql的具體執(zhí)行性能。
# 開啟性能分析
set profiling=0;
# 查詢性能分析
show profiles;
# 查看具體的SQL執(zhí)行步驟
show profile [type [, type] ... ]
[FOR QUERY n]
[LIMIT row_count [OFFSET offset]]
type參數(shù):
show 默認(rèn)情況下只顯示最近執(zhí)行的15 條SQL語句,可以通過設(shè)置ze來增大該值,最大值為 100。不過該功能實際已被棄用,將來會被移除。官方推薦用庫的**相關(guān)表替代,里面有87張表,部分功能默認(rèn)開啟。
庫
庫可用于分析SQL執(zhí)行性能,找出長事務(wù)和慢查詢。
查詢長事務(wù)
可以在 這個表中查詢長事務(wù)。比如下面這個語句,用于查找持續(xù)時間超過 60s 的事務(wù)。
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60
慢查詢?nèi)罩?/p>
通過以下命令行查詢是否開啟了記錄慢 SQL 的功能,以及慢查詢的閥值:
Show variables like 'slow_query%';
Show variables like 'long_query_time';
開啟慢查詢?nèi)罩?/p>
# 開啟慢查詢?nèi)罩?set global slow_query_log='ON';
# 指定慢查詢?nèi)罩镜刂?set global slow_query_log_file='/var/lib/mysql/test-slow.log';
# 設(shè)置慢查詢閥值
set global long_query_time=1;
pt-query-
建設(shè)中
處理慢SQL
方案一、定時檢測
上線一個定時監(jiān)控和殺掉慢 SQL 的腳本。腳本每分鐘執(zhí)行一次,檢測有沒有執(zhí)行時間超過指定閥值(如一分鐘)的慢 SQL。如果發(fā)現(xiàn),直接殺掉這個會話。
方案二、降級
請求超時進(jìn)行降級。
歷史數(shù)據(jù)清理 為什么刪除數(shù)據(jù)后表空間沒有釋放
和 的物理存儲結(jié)構(gòu)有關(guān)系。邏輯上雖然每個表是一顆 B+ 樹,但是物理上每條記錄都是存放在磁盤文件中,這些記錄通過一些位置指針來組織成一顆 B+ 樹。當(dāng) MySQL 刪除一條記錄的時候,只是把文件的這塊區(qū)域標(biāo)記為空閑,然后再修改 B+ 樹中相關(guān)的一些指針,完成刪除。實際被刪除的記錄還是存在。
解決方案
方法一、建立新表
將數(shù)據(jù)復(fù)制到新表,然后改名。速度最快,但是需要停服,
方法二、在線遷移。
分批刪除歷史數(shù)據(jù),采用主鍵刪除可以提高刪除效率。
方法三、釋放表空間
通過 TABLE 重建表,釋放存儲空間,執(zhí)行期間會鎖表。重建過程中,索引也會重建,所以表數(shù)據(jù)和索引數(shù)據(jù)都會更緊湊,查詢效率也會提升。但該優(yōu)化有個前提條件,MySQL 的配置必須是每個表獨立一個表空間(e = ON)。
集群優(yōu)化 從庫延遲原因
延遲的最直接表現(xiàn)是從庫消費relay log的速度遠(yuǎn)低于主庫生產(chǎn)日志的速度。可能原因如下:
大事務(wù)。主庫事務(wù)執(zhí)行多長,從庫之后也要執(zhí)行多長時間。在大表上執(zhí)行DDL。 監(jiān)控延遲程度 手動主從切換 從庫 =true,只讀。在從庫查看 r,低于5秒則執(zhí)行下一步字段默認(rèn)值為系統(tǒng)當(dāng)前日期,否則重試。設(shè)置主庫 =true,只讀。在從庫查看 r,等于0則執(zhí)行下一步,否則重試。把從庫 =false。把業(yè)務(wù)切換到從庫。 手動一主多從切換
例如主機A和備機A`互備,從機B、C、D作為主機A的從機,提供只讀功能。
使用GTID進(jìn)行切換
MySQL 5.6 版本引入的 GTID 模式。GTID 的全稱是 ,也就是全局事務(wù) ID,是一個事務(wù)在提交的時候生成的,是這個事務(wù)的唯一標(biāo)識。
格式是:GTID=:gno
是一個實例第一次啟動時自動生成的,是一個全局唯一的值;gno 是一個整數(shù),初始值是 1,每次提交事務(wù)的時候分配給這個事務(wù),并加 1。
GTID 模式的啟動也很簡單,我們只需要在啟動一個 MySQL 實例的時候,加上參數(shù) =on 和 ency=on 就可以了。