mysql (1):高階篇(上)
一 日誌
1.1 錯誤日誌
錯誤日誌是 MySQL 中最重要的日誌之一,它記錄了當 mysqld 啟動和停止時,以及伺服器在執行過程中發生任何嚴重錯誤時的相關資訊。當資料庫出現任何故障導致無法正常使用時,建議首先檢視此日誌。
該日誌是預設開啟的,預設存放目錄 /var/log/,預設的日誌檔名為 mysqld.log 。檢視日誌位置show variables like '%log_error%';
1.2 二進位制日誌
1.2.1 介紹
二進位制日誌(BINLOG)記錄了所有的 DDL(資料定義語言)語句和 DML(資料操縱語言)語句,但不包括資料查詢(SELECT、SHOW)語句。
作用:
①. 災難時的資料恢復;
②. MySQL的主從複製。在MySQL8版本中,預設二進位制日誌是開啟著的,涉及到的引數如下:show variables like '%log_bin%';
引數說明:
- log_bin_basename:當前資料庫伺服器的binlog日誌的基礎名稱(字首),具體的binlog檔名需要再該basename的基礎上加上編號(編號從000001開始)。
- log_bin_index:binlog的索引檔案,裡面記錄了當前伺服器關聯的binlog檔案有哪些。
1.2.2 格式
MySQL伺服器中提供了多種格式來記錄二進位制日誌,具體格式及特點如下:
日誌格式 | 含義 |
---|---|
STATEMENT | 基於SQL語句的日誌記錄,記錄的是SQL語句,對資料進行修改的SQL都會記錄在日誌檔案中。 |
ROW | 基於行的日誌記錄,記錄的是每一行的資料變更。(預設) |
MIXED | 混合了STATEMENT和ROW兩種格式,預設採用STATEMENT,在某些特殊情況下會自動切換為ROW進行記錄。 |
引數:show variables like '%binlog_format%';
如果我們需要配置二進位制日誌的格式,只需要在 /etc/my.cnf 中配置 binlog_format 引數即可。
1.2.3 檢視
由於日誌是以二進位制方式儲存的,不能直接讀取,需要通過二進位制日誌查詢工具 mysqlbinlog 來檢視,具體語法:
mysqlbinlog [ 引數選項 ] logfilename /** 引數選項: -d 指定資料庫名稱,只列出指定的資料庫相關操作。 -o 忽略掉日誌中的前n行命令。 -v 將行事件(資料變更)重構為SQL語句 -vv 將行事件(資料變更)重構為SQL語句,並輸出註釋資訊,這是兩個v,不是w */
1.2.4 刪除
對於比較繁忙的業務系統,每天生成的binlog資料巨大,如果長時間不清除,將會佔用大量磁碟空
間。可以通過以下幾種方式清理日誌:
指令 | 含義 |
---|---|
reset master | 刪除全部 binlog 日誌,刪除之後,日誌編號,將從 binlog.000001重新開始 |
purge master logs to 'binlog.*' | 刪除 * 編號之前的所有日誌 |
purge master logs before 'yyyy-mm-dd hh24:mi:ss' | 刪除日誌為 "yyyy-mm-dd hh24:mi:ss" 之前產生的所有日誌 |
也可以在mysql的配置檔案中配置二進位制日誌的過期時間,設定了之後,二進位制日誌過期會自動刪除。
show variables like '%binlog_expire_logs_seconds%';
1.3 查詢日誌
查詢日誌中記錄了客戶端的所有操作語句,而二進位制日誌不包含查詢資料的SQL語句。預設情況下,查詢日誌是未開啟的。
如果需要開啟查詢日誌,可以修改MySQL的配置檔案 /etc/my.cnf 檔案,新增如下內容:
#該選項用來開啟查詢日誌 , 可選值 : 0 或者 1 ; 0 代表關閉, 1 代表開啟
general_log=1
#設定日誌的檔名 , 如果沒有指定, 預設的檔名為 host_name.log
general_log_file=mysql_query.log
開啟了查詢日誌之後,在MySQL的資料存放目錄,也就是 /var/lib/mysql/ 目錄下就會出現mysql_query.log 檔案。之後所有的客戶端的增刪改查操作都會記錄在該日誌檔案之中,長時間執行後,該日誌檔案將會非常大。
1.4 慢查詢日誌
慢查詢日誌記錄了所有執行時間超過引數 long_query_time 設定值並且掃描記錄數不小於min_examined_row_limit 的所有的SQL語句的日誌,預設未開啟。long_query_time 預設為10 秒,最小為 0, 精度可以到微秒。
如果需要開啟慢查詢日誌,需要在MySQL的配置檔案 /etc/my.cnf 中配置如下引數:
#慢查詢日誌
slow_query_log=1
#執行時間引數
long_query_time=2
預設情況下,不會記錄管理語句,也不會記錄不使用索引進行查詢的查詢。可以使用log_slow_admin_statements和 更改此行為 log_queries_not_using_indexes,如下所述。
#記錄執行較慢的管理語句
log_slow_admin_statements =1
#記錄執行較慢的未使用索引的語句
log_queries_not_using_indexes = 1
上述所有的引數配置完成之後,都需要重新啟動MySQL伺服器才可以生效。
二. 主從複製
2.1 概述
主從複製是指將主資料庫的 DDL 和 DML 操作通過二進位制日誌傳到從庫伺服器中,然後在從庫上對這些日誌重新執行(也叫重做),從而使得從庫和主庫的資料保持同步。
MySQL支援一臺主庫同時向多臺從庫進行復制, 從庫同時也可以作為其他從伺服器的主庫,實現鏈狀複製。
MySQL 複製的優點主要包含以下三個方面:
- 主庫出現問題,可以快速切換到從庫提供服務。
- 實現讀寫分離,降低主庫的訪問壓力。
- 可以在從庫中執行備份,以避免備份期間影響主庫服務。
2.2 原理
MySQL主從複製的核心就是 二進位制日誌,具體的過程如下:
從上圖來看,複製分成三步:
-
- Master 主庫在事務提交時,會把資料變更記錄在二進位制日誌檔案 Binlog 中。
-
- 從庫讀取主庫的二進位制日誌檔案 Binlog ,寫入到從庫的中繼日誌 Relay Log 。
-
- slave重做中繼日誌中的事件,將改變反映它自己的資料。
2.3 搭建
2.3.1 準備
準備好兩臺伺服器之後,在上述的兩臺伺服器中分別安裝好MySQL,並完成基礎的初始化準備(安裝、密碼配置等操作)工作。 其中:
- 192.168.200.200 作為主伺服器master
- 192.168.200.201 作為從伺服器slave
2.3.2 主庫配置
- 修改配置檔案 /etc/my.cnf
#mysql 服務ID,保證整個叢集環境中唯一,取值範圍:1 – 232-1,預設為1
server-id=1
#是否只讀,1 代表只讀, 0 代表讀寫
read-only=0
#忽略的資料, 指不需要同步的資料庫
#binlog-ignore-db=mysql
#指定同步的資料庫
#binlog-do-db=db01
- 重啟MySQL伺服器
systemctl restart mysqld
- 登入mysql,建立遠端連線的賬號,並授予主從複製許可權
--建立itcast使用者,並設定密碼,該使用者可在任意主機連線該MySQL服務
CREATE USER 'itcast'@'%' IDENTIFIED WITH mysql_native_password BY 'Root@123456' ;
--為 'itcast'@'%' 使用者分配主從複製許可權
GRANT REPLICATION SLAVE ON *.* TO 'itcast'@'%';
- 通過指令,檢視二進位制日誌座標
show master status ;
欄位含義說明:
- file : 從哪個日誌檔案開始推送日誌檔案
- position : 從哪個位置開始推送日誌
- binlog_ignore_db : 指定不需要同步的資料庫
2.3.3 從庫配置
- 修改配置檔案 /etc/my.cnf
#mysql 服務ID,保證整個叢集環境中唯一,取值範圍:1 – 2^32-1,和主庫不一樣即可
server-id=2
#是否只讀,1 代表只讀, 0 代表讀寫
read-only=1
- 重新啟動MySQL服務
systemctl restart mysqld
- 登入mysql,設定從庫配置
CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.200.200', SOURCE_USER='itcast', SOURCE_PASSWORD='Root@123456', SOURCE_LOG_FILE='binlog.000004', SOURCE_LOG_POS=663;
上述是8.0.23中的語法。如果mysql是 8.0.23 之前的版本,執行如下SQL:
CHANGE MASTER TO MASTER_HOST='192.168.200.200', MASTER_USER='itcast', MASTER_PASSWORD='Root@123456', MASTER_LOG_FILE='binlog.000004', MASTER_LOG_POS=663;
引數名 | 含義 | 8.0.23之前 |
---|---|---|
SOURCE_HOST | 主庫IP地址 | MASTER_HOST |
SOURCE_USER | 連線主庫的使用者名稱 | MASTER_USER |
SOURCE_PASSWORD | 連線主庫的密碼 | MASTER_PASSWORD |
SOURCE_LOG_FILE | binlog日誌檔名 | MASTER_LOG_FILE |
SOURCE_LOG_POS | binlog日誌檔案位置 | MASTER_LOG_POS |
- 開啟同步操作
start replica ; #8.0.22之後
start slave ; #8.0.22之前
- 檢視主從同步狀態
show replica status ; #8.0.22之後
show slave status ; #8.0.22之前
2.3.4 測試
- 在主庫 192.168.200.200 上建立資料庫、表,並插入資料
create database db01;
use db01;
create table tb_user(
id int(11) primary key not null auto_increment,
name varchar(50) not null,
sex varchar(1)
)engine=innodb default charset=utf8mb4;
insert into tb_user(id,name,sex) values(null,'Tom', '1'),(null,'Trigger','0'), (null,'Dawn','1');
- 在從庫 192.168.200.201 中查詢資料,驗證主從是否同步
三 分庫分表
3.1 介紹
3.1.1 問題分析
隨著網際網路及移動網際網路的發展,應用系統的資料量也是成指數式增長,若採用單資料庫進行資料儲存,存在以下效能瓶頸:
- IO瓶頸:熱點資料太多,資料庫快取不足,產生大量磁碟IO,效率較低。 請求資料太多,頻寬不夠,網路IO瓶頸。
- CPU瓶頸:排序、分組、連線查詢、聚合統計等SQL會耗費大量的CPU資源,請求數太多,CPU出現瓶頸。
為了解決上述問題,我們需要對資料庫進行分庫分表處理。
分庫分表的中心思想都是將資料分散儲存,使得單一資料庫/表的資料量變小來緩解單一資料庫的效能問題,從而達到提升資料庫效能的目的。
3.1.2 拆分策略
分庫分表的形式,主要是兩種:垂直拆分和水平拆分。而拆分的粒度,一般又分為分庫和分表,所以組成的拆分策略最終如下:
3.1.3 垂直拆分
- 垂直分庫
垂直分庫:以表為依據,根據業務將不同表拆分到不同庫中。
特點:
- 每個庫的表結構都不一樣。
- 每個庫的資料也不一樣。
- 所有庫的並集是全量資料。
- 垂直分表
垂直分表:以欄位為依據,根據欄位屬性將不同欄位拆分到不同表中。
特點:
- 每個表的結構都不一樣。
- 每個表的資料也不一樣,一般通過一列(主鍵/外來鍵)關聯。
- 所有表的並集是全量資料。
3.1.4 水平拆分
- 水平分庫
水平分庫:以欄位為依據,按照一定策略,將一個庫的資料拆分到多個庫中。
特點:
- 每個庫的表結構都一樣。
- 每個庫的資料都不一樣。
- 所有庫的並集是全量資料。
- 水平分表
水平分表:以欄位為依據,按照一定策略,將一個表的資料拆分到多個表中。
特點:
- 每個表的表結構都一樣。
- 每個表的資料都不一樣。
- 所有表的並集是全量資料。
在業務系統中,為了緩解磁碟IO及CPU的效能瓶頸,到底是垂直拆分,還是水平拆分;具體是分庫,還是分表,都需要根據具體的業務需求具體分析。
3.1.5 實現技術
- shardingJDBC:基於AOP原理,在應用程式中對本地執行的SQL進行攔截,解析、改寫、路由處理。需要自行編碼配置實現,只支援java語言,效能較高。
- MyCat:資料庫分庫分表中介軟體,不用調整程式碼即可實現分庫分表,支援多種語言,效能不及前者。
我們選擇了是MyCat資料庫中介軟體,通過MyCat中介軟體來完成分庫分表操作。
3.2 MyCat概述 3.2.1 介紹
Mycat是開源的、活躍的、基於Java語言編寫的MySQL資料庫中介軟體。可以像使用mysql一樣來使用mycat,對於開發人員來說根本感覺不到mycat的存在。
開發人員只需要連線MyCat即可,而具體底層用到幾臺資料庫,每一臺資料庫伺服器裡面儲存了什麼資料,都無需關心。 具體的分庫分表的策略,只需要在MyCat中配置即可。
優勢:
- 效能可靠穩定
- 強大的技術團隊
- 體系完善
- 社群活躍