Mysql

將 MySQL 錯誤和慢日誌重定向到另一個數據庫

  • December 23, 2019

我正在執行多個 MySQL 伺服器作為從屬伺服器和主伺服器。在每台伺服器中查找緩慢的日誌和錯誤非常煩人,因此我想將所有錯誤記錄到外部數據庫中。

   DB1    DB2    DBn ...
     \      |      /
      \     |     /          <-- error logs and slow logs
       \    |    /
[MySQL error & slow log database]

有一些簡單的方法嗎?

或者我確實需要寫一些腳本和東西?

PS 我希望你欣賞我精湛的 ASCII 繪圖技巧

你有沒有考慮過將慢日誌轉換成 MyISAM 表?

對於 MySQL 5.1.30,您可以通過log_output選項選擇慢日誌和普通日誌的格式為 TABLE 或 FILE。它在 MySQL 5.5 中也可用

為了支持 log_output 的 TABLE 選項,MySQL 提供了兩個表:

  • mysql.slow_log
  • mysql.general_log

為了這個問題,我只討論mysql.slow_log

預設情況下,這是mysql.slow_log

mysql> show create table mysql.slow_log\G
*************************** 1. row ***************************
      Table: slow_log
Create Table: CREATE TABLE `slow_log` (
 `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 `user_host` mediumtext NOT NULL,
 `query_time` time NOT NULL,
 `lock_time` time NOT NULL,
 `rows_sent` int(11) NOT NULL,
 `rows_examined` int(11) NOT NULL,
 `db` varchar(512) NOT NULL,
 `last_insert_id` int(11) NOT NULL,
 `insert_id` int(11) NOT NULL,
 `server_id` int(10) unsigned NOT NULL,
 `sql_text` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
1 row in set (0.10 sec)

mysql>

slow_log 表使用 CSV 儲存引擎。請注意,CSV 表不能被索引。這對於按日期和時間進行分析不是很有用。好消息:您可以將其轉換為 MyISAM 表。

為了促進基於 MyISAM 的慢日誌,請執行以下操作:

Step01) 將 mysql.slow_log 設為 MyISAM 表

ALTER TABLE mysql.slow_log ENGINE-MyISAM;

Step02) 呼叫時間戳列的索引start_time

ALTER TABLE mysql.slow_log ADD INDEX (start_time);

Step03) 將以下行添加到 my.cnf (或 my.ini)

[mysqld]
slow-query-log
log-output=TABLE

Step04) 重啟 MySQL

對於 Linux

service mysql restart

或對於 Windows

net stop mysql
net start mysql

Step05) 在 MySQL 中執行以下命令

mysql> SHOW VARIABLES LIKE 'long_query_time';

預設情況下long_query_time是 10 秒

Step06) 執行此命令

mysql> SELECT SLEEP(15);

如果 long_query_time 是 10 秒,這個 SELECT 應該故意放在 mysql.slow_log 中。

Step07) 執行此命令

mysql> SELECT sql_text FROM mysql.slow_log;

如果您在表格中看到任何帶有 的行SELECT SLEEP(15);,恭喜!

您現在可以執行 SELECT 查詢mysql.slow_log以將部分或全部行複製到其他表或其他數據庫。

我已經發布了與該主題相關的過去答案:

更新 2012-11-12 17:00 EDT

平心而論,這個問題確實詢問了錯誤日誌。我沒有明確包括任何關於它的內容。我將包含一些程式碼來解決如何

假設錯誤日誌在任何數據庫伺服器上定義如下:

[mysqld]
log-error=/var/log/mysqld.log

您可以創建這樣的腳本:

ERROR_LOG=/var/log/mysqld.log
LOG_LINES=/tmp/general-log-lines.txt
ERROR_FOLDER=<folder where to copy logs>
ERROR_TARGET=${ERROR_FOLDER}/`hostname`-DB-Errors.txt
NEWCOUNT=`wc -l < ${ERROR_LOG}`
if [ -f ${LOG_LINES} ]
then
   OLDCOUNT=`cat ${LOG_LINES} | awk '{print $1}'`
   if [ ${OLDCOUNT} -lt ${NEWCOUNT} ]
   then
       (( DIFF = NEWCOUNT - OLDCOUNT ))
       tail -${DIFF} < ${ERROR_LOG} >> ${ERROR_TARGET}
       echo ${NEWCOUNT} > ${LOG_LINES}
   fi
fi

或者,如果您想在不重啟 mysql 的情況下收集和重置錯誤日誌(僅限 Linux),您可以使用此方法(此技術在 Windows 中永遠無法完成,因為 Windows 作業系統會鎖定錯誤日誌文件以防止外部寫入):

ERROR_LOG=/var/log/mysqld.log
LOG_LINES=/tmp/general-log-lines.txt
ERROR_FOLDER=<folder where to copy logs>
ERROR_TARGET=${ERROR_FOLDER}/`hostname`-DB-Errors.txt
NEWCOUNT=`wc -l < ${ERROR_LOG}`
if [ -f ${LOG_LINES} ]
then
   OLDCOUNT=`cat ${LOG_LINES} | awk '{print $1}'`
   if [ ${OLDCOUNT} -lt ${NEWCOUNT} ]
   then
       (( DIFF = NEWCOUNT - OLDCOUNT ))
       tail -${DIFF} < ${ERROR_LOG} >> ${ERROR_TARGET}
       echo -n > ${ERROR_LOG}
       echo 0 > ${LOG_LINES}
   fi
fi

將此腳本放在每個數據庫伺服器上。為該腳本設置一個 crontab,使其每 5 分鐘關閉一次。確保ERROR_FOLDER設置為公共共享文件夾。

更新 2012-11-12 17:24 EDT

為了澄清,執行 MySQLFLUSH LOGS;是不夠的,因為……

  • 對於所有基於文本的日誌,FLUSH LOGS;關閉並重新打開。mysqld 不提供輪換

  • 對於二進制日誌,FLUSH LOGS;將…

    • 關閉目前二進制日誌
    • 輪換到新的二進制日誌
    • 打開新的二進制日誌
  • 對於 MySQL 5.5,FLUSH ERROR LOGS;關閉並重新打開錯誤日誌。不提供旋轉

這就是為什麼一些腳本是必要的

引用自:https://dba.stackexchange.com/questions/28416