上篇回顧:http://www.javashuo.com/article/p-xmusedzr-q.htmlhtml
本文的測試環境:MySQL5.7.26
、MariaDB5.5.60
、MySQL8.0.16
mysql
PS:版本查詢
select version();
git
服務器層日誌(存儲引擎層有本身的日誌)程序員
日誌類型 | 描述 |
---|---|
error_log (錯誤日誌) |
記錄MySQL啓動、運行或中止時出現的問題 |
general_log (常規日誌) |
記錄全部發送給MySQL的請求(耗性能) |
slow_query_log (慢查日誌) |
記錄符合條件的查詢(eg:超過10s、沒有使用索引等) |
binary_log (二進制日誌) |
記錄所有有效的數據修改日誌(老版本數據庫不會開啓) |
relay_log (中繼日誌) |
用於主從複製,臨時存儲主從同步的二進制日誌(增量複製) |
知識擴展:https://blog.csdn.net/zhang123456456/article/details/72811875github
實時查看文件:tail -f /var/log/mysqld.log
sql
tail -f 用於監視文件增加(默認是末尾10行)shell
通常記錄MySQL運行錯誤
和和未受權的訪問
數據庫
- 老版:
log_error
+log_warnings
- 經常使用:
log_error
+log_error_verbosity
- 新版:
log_error
+log_error_verbosity
+log_error_services
查詢MySQL配置:show variables like '%log_error%';
json
SQL查詢能夠這麼幹:ubuntu
-- Ubuntu下默認是:`/var/log/mysql/error.log` -- CentOS下默認是:`/var/log/mysqld.log` | `/var/log/mariadb/mariadb.log` select @@log_error; -- 儘量和Data分開存儲 -- 0:不記錄警告信息,1:告警信息寫入錯誤日誌,2:各種告警信息都寫入(eg:網絡故障和重連信息) select @@log_warnings; -- MySQL8中已經移除(MySQL5.7默認是2,MariaDB5.5.60默認是1) -- 錯誤級別(1:Error,2:Error、Warning,3:Error、Warning、Info select @@log_error_verbosity; -- MySQL8默認是2,MySQL5.7默認是3 -- PS:從MySQL 5.7.2開始,首選`log_error_verbosity`系統變量 -- 默認是`log_filter_internal; log_sink_internal` select @@log_error_services; -- MySQL8.0中新增
PS:其實MySQL在市面上有不少成熟解決方案(基本上都是基於5.六、5.7的)
這也是爲何我開篇主推
MySQL5.7
系列和MariaDB5.5.60
(不少時候不是不用最新DB,而是架構依賴作不到啊)
知識拓展:http://www.javashuo.com/article/p-acredmax-m.html
PS:SQLServer的ErrorLog也是差很少的
日誌服務組件:
日誌服務組件名 | 描述 |
---|---|
log_sink_internal |
默認的日誌輸出組件(依賴log_error ) |
log_filter_internal |
默認的日誌過濾組件(依賴log_error_verbosity ) |
log_sink_json |
將錯誤日誌輸出到json 文件 |
log_sink_syseventlog |
將錯誤日誌輸出到系統日誌文件 |
PS:log_filter_internal
:過濾錯誤信息(達不到級別的不記錄)
日記格式通常是這樣的:UTC時間戳 進程id [日誌級別] [錯誤代碼] [由什麼產生的日誌(Server or Client)] 詳細信息
eg:
2019-05-19T09:54:11.590474Z 8 [Warning] [MY-010055] [Server] IP address '192.168.36.144' could not be resolved: Name or service not known
通常log_sink_json
用的比較多:
官方文檔參考:https://dev.mysql.com/doc/refman/8.0/en/error-log-json.html
PS:第一次使用須要安裝一下json組件:install component 'file://component_log_sink_json';
經常使用設置:
set persist log_error_services='log_filter_internal;log_sink_json';
上面的時間默認是UTC的時間戳,和咱們是有時差的,這個時間戳能夠經過設置log_timestamps
來本地化:
-- 查詢 select @@log_timestamps; -- MySQL5.7新增 -- 從8開始,可經過SET PERSIST命令將全局變量的修改持久化到配置文件中 set persist log_timestamps='SYSTEM'; -- 須要root權限
PS:set persist
生成的配置文件路徑在:/var/lib/mysql/mysqld-auto.cnf
之前開發調試的時候基本上都是會開啓的,上線後關閉(系統V1初期的時候也會開啓一段時間)
如今開發可使用go-sniffer來抓包查看客戶端執行的SQL
-- 是否打開常規日誌(0不打開,1打開) -- 通常不打開(性能) select @@general_log; -- 默認爲0 -- Ubuntu默認:/var/lib/mysql/ubuntuserver.log -- CentOS默認:/var/lib/mysql/localhost.log select @@general_log_file; -- 常規日誌的路徑 -- 日誌的存儲方式(FILE | TABLE | NONE) select @@log_output; -- 默認是文件存儲
簡單看一下常規日誌在數據庫中的結構:
臨時開啓參考:
# 開啓 set global general_log = 1; # set [global | persist] general_log_file = '日誌路徑'; set global log_output = 'TABLE';
slow_query_log
(慢查詢日誌)這個是最經常使用
的,把符合條件的查詢語句記錄在日誌中,通常都是些須要優化的SQL
PS:出現性能瓶頸的時候,或者爲了優化SQL會開啓一段時間(小項目推薦直接開啓)
先看下默認值:show variables like '%slow%';
、show variables like 'long%';
SQL查詢:
-- 是否開啓 select @@slow_query_log; -- 默認是關閉 -- CentOS:/var/lib/mysql/localhost-slow.log -- Ubuntu:/var/lib/mysql/ubuntuserver-slow.log select @@slow_query_log_file; -- 條件:設置超過多少秒爲慢查詢(通常設置1s) select @@long_query_time; -- 默認是10s(支持小數:0.003) -- PS:設置爲0就會記錄全部SQL(不推薦這麼幹) -- 條件:沒有使用索引的查詢記錄到日誌中 select @@log_queries_not_using_indexes; -- 默認是0(不開啓) -- 記錄optimize table、analyze table和alter table的管理語句 select @@log_slow_admin_statements; -- 默認是0(不開啓) -- 記錄由Slave所產生的慢查詢 select @@log_slow_slave_statements;
經常使用設置:
PS:高併發下的互聯網項目,對SQL執行時間的容忍度通常都是低於
300~500ms
的(long_query_time=0.05
)
# 經常使用以下:(須要MySQL的root權限) set global slow_query_log = 1; # 開啓慢查詢日誌 set global long_query_time = 1; # 記錄大於1s的SQL set global log_slow_admin_statements = 1; # 記錄管理語句 set global log_queries_not_using_indexes = 1; # 記錄沒有使用索引的SQL # set [global | persist] slow_query_log_file = '路徑'; # 設置log路徑
設置long_query_time
時,須要從新鏈接才能生效(不須要重啓DB)
PS:當前會話不生效,以後的會話就生效了(不想重連能夠再設置下當前會話的
long_query_time
)
知識拓展:(chown mysql:mysql /work/log/xxx.log
)
先簡單分析下慢查詢日誌:
# Time: 2019-05-22T21:16:28.759491+08:00 # User@Host: root[root] @ localhost [] Id: 11 # Query_time: 0.000818 Lock_time: 0.000449 Rows_sent: 5 Rows_examined: 5 SET timestamp=1558530988; select * from mysql.user order by host; # SQL語句
Time
:查詢的執行時間(start_time
)User@Host: root[root] @ localhost [] Id:11
:執行 sql 的主機信息Query_time
:SQL查詢
所耗的時間Lock_time
:鎖定時間Rows_sent
:所發送的行數Rows_examined
:鎖掃描的行數SET timestamp=1558530988;
:SQL執行時間如今能夠說說工具了,推薦兩款:
mysqldumpslow
percona-toolkit
)中的pt-query-digest
查詢最慢的10條SQL:mysqldumpslow -s t -t 10 /var/lib/mysql/localhost-slow.log
-s 按照那種方式排序 t: 查詢時間 c:訪問計數 l:鎖定時間 r:返回記錄 al:平均鎖定時間 ar:平均訪問記錄數 at:平均查詢時間 -t 返回多少條數據(能夠理解爲top n) -g 能夠跟上正則匹配模式,大小寫不敏感。
PS:使用mysqldumpslow的分析結果不會顯示具體完整的sql語句:
select * from tb_table where uid=20 group by createtime limit 10000, 1000;
==> select * from tb_table where uid=N group by createtime limit N, N;
官方文檔:https://www.percona.com/doc/percona-toolkit/3.0/pt-query-digest.html
分析慢查詢日誌:
pt-query-digest /var/lib/mysql/localhost-slow.log
tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
pt-query-digest --type tcpdump mysql.tcp.txt
pt-query-digest --processlist h=ip
安裝能夠參考:https://github.com/lotapp/awesome-tools/blob/master/README.md#4%E8%BF%90%E7%BB%B4
PS:percona-toolkit的經常使用工具我也在裏面簡單說了下,對應文檔也貼了
PS:還有一款mysqlsla
我沒用過,因此貼個參考文章,感興趣的同志本身研究下
知識拓展:http://www.javashuo.com/article/p-pczgzxqq-bd.html
上節主要說了通用日誌和慢查日誌,今天說下二進制日誌:
二進制日誌算是最經常使用的了,主要就是記錄對數據庫的修改
,而後就是主從複製
用的比較多(好比增量備份)
PS:記錄了修改操做,那麼衍生出的場景就是:
增量備份和恢復
(基於時間點的備份和恢復)
PS:MySQL日誌主要分爲這兩類:(互不干擾)
服務層
日誌(和使用存儲引擎無關)
存儲引擎層
日誌
redo log
)和回滾日誌(undo log
)Q:那什麼樣的修改會記錄下來呢?
A:記錄全部對MySQL數據庫的修改事件(包括增刪改查事件和對錶結構修改的事件),並且只記錄已經成功執行的事件(失敗的不會記錄)
這麼說可能有點抽象,熟悉SQLServer的同志看個圖就秒懂:
參數 | 說明 |
---|---|
STATEMENT |
基於段的格式,記錄執行數據修改時候所執行的SQL語句 |
ROW |
基於行的格式,記錄增刪改查操做所修改行的信息(每修改一行就會有一條信息) |
MIXED |
基於行和端的混合格式,根據SQL語句由系統決定是基於段仍是基於行的日誌格式記錄 |
查看方式:show variables like 'binlog_format';
statement
:基於段的記錄格式(老版本的默認值)
uuid()
、user()
等結果非肯定的函數,可能會形成MySQL主從不一致mysqlbinlog /var/lib/mysql/binlog.0000xx | more
(不用指定參數)row
:基於行的記錄格式(5.7之後的默認值)
binlog_row_image=[full|minimal|noblob]
mysqlbinlog -vv /var/lib/mysql/binlog.0000xx | more
mixed
:基於行和端的混合格式(推薦
)
PS:DDL操做(create、drop、alter)的時候都是基於段方式來記錄log
若是一條一條記錄,表有上億數據,我就修改某列的狀態值,那不得瘋?
對binlog_row_image=[FULL|MINIMAL|NOBLOB]
的補充說明:
PS:查看方式:
show variables like 'binlog_row_image'
full
:完整
noblob
:就是在full記錄的基礎上對大文本列的優化
minimal
:簡單記錄,只記錄修改的那一列
通常使用binlog_format=mixed
混合格式 or binlog_format=row
+ binlog_row_image=minimal
PS:若是對安全性要求特別高,推薦使用
binlog_format=row
+binlog_row_image=full
(不怕誤操做)
這個和SQLServer的日誌恢復模式有點相似,我貼下圖大家能夠對比參考:
上面雖說完了二進制日誌的經常使用3種格式,但老版本默認都是不啓用二進制日誌的,咋辦?
PS:若是是MariaDB能夠去示例配置中查看:
ls /usr/share/mysql/ |grep .cnf
(CentOS)
驗證下:
MySQL8以前:cat /etc/mysql/mysql.conf.d/mysqld.cnf
(UbuntuServer)
MySQL8:cat /etc/my.cnf |grep log
(CentOS)
Q:有些人可能疑惑了,爲何用show variables like 'log_bin';
查詢出來的結果和配置文件中不大同樣啊?
PS:通常配置項中的參數均可以使用
show variables like 'xx'
來查詢對應的值
A:那是由於5.7以後版本分紅了兩個參數:log_bin
和log_bin_basename
:
PS:配置文件的
log_bin=xxx
至關於命令中的log_bin
和log_bin_basename
mysql> show variables like 'log_bin%'; +---------------------------------+-----------------------------+ | Variable_name | Value | +---------------------------------+-----------------------------+ | log_bin | ON | | log_bin_basename | /var/lib/mysql/binlog | | log_bin_index | /var/lib/mysql/binlog.index | | log_bin_trust_function_creators | OFF | | log_bin_use_v1_row_events | OFF | +---------------------------------+-----------------------------+ 5 rows in set (0.00 sec)
MariaDB開啓binlog圖示:(CentOS)
MySQL5.7演示:(UbuntuServer)
配置文件中修改:(show variables like 'binlog_format';
:查看當前binlog基於什麼格式)
# 服務器標識 server-id=1 # 單機MariaDB可不開啓 # 開啓binlog並設置路徑 # 不指定路徑則默認在數據目錄下 log_bin=binlog # 這個表明以binlog開頭的文件 # binlog採用ROW|MIXED格式 # binlog_format=MIXED # 5.7默認是ROW
先看下文件前綴(log_bin=binlog
)的概念,一張圖就懂:
PS:若是log_bin只是指定一個名字,那麼默認路徑通常都是在數據文件的文件夾中
配置文件通常都會寫,eg:
datadir=/var/lib/mysql
,或者經過show variables like 'datadir';
也能夠查詢到
雖然和SQLServer文件組不是一個概念,但有些類似 ==> log能夠多個也能夠動態調整
Q:雖然ROW記錄能保證主從數據安全,但咱們排查問題的時候每每須要知道SQL,而用段的記錄方式又不合適,咋辦?
A:有個新參數能夠解決:binlog_rows_query_log_events
,開啓後就能夠記錄sql了
查看方式:show variables like 'binlog_row%';
mysql> show variables like 'binlog_row%'; +------------------------------+-------+ | Variable_name | Value | +------------------------------+-------+ | binlog_row_image | FULL | | binlog_rows_query_log_events | OFF | +------------------------------+-------+ 2 rows in set (0.01 sec)
顯示binlog列表:show binary logs;
刷新一份新的binlog:flush logs;
(如今開始的二進制日誌就記錄在這個新文件中)
binlog如今是空的:(-vv
:把二進制格式的日誌顯示爲能讀懂的字符串)
mysqlbinlog --no-defaults -vv --base64-output=DECODE-ROWS /var/lib/mysql/binlog.000006
如今簡單摸擬幾個SQL操做,而後看看binlog:
查看下binlog日誌:(線上開發通常都是FULL模式,主要是防止程序員修改SQL的時候不加條件等誤操做)
FULL模式就是這樣,該行數據所有記錄(修改部分其實就綠色框的地方)
想要binlog中記錄SQL就開啓binlog_rows_query_log_events
:
PS:像這種操做,若是模式選混合模式,binlog中會記錄SQL的
臨時開啓下binlog_rows_query_log_events
(若是你有須要能夠配置文件設置一下)
PS:MySQL8可經過
set persist
命令將全局變量的修改持久化到配置文件中
效果以下:
expire_logs_days = 30
purge binary logs to 'binlog.000006';
purge binary logs before '2019-06-15 14:14:00';
已經23:23了,咱們快速演示下:
MySQL命令行中執行命令:
文件列表:
這個把運維篇講完會繼續說,運維篇結束後會有個高級篇(架構),這邊就簡單提下二進制格式對主從複製的影響
:
statement
格式(5.7前的默認)貼個課後拓展文章:http://www.javashuo.com/article/p-xqqwxjcp-bk.html
下級預估:備份與恢復、監控