web-dev-qa-db-ja.com

MySQL-すべての接続をログに記録する

MySQL 5.0.77サーバーを監視し、すべての着信接続を1日記録したいと思います。誰がデータベースに接続しているかを知る必要があります。

一般的なログを試しましたが、ログが多すぎます多すぎます十分な長さを維持できず、ログファイルの成長が速すぎます。

それを行う方法はありますか?ありがとう

3
Bastien974

一般的なログは、テキストファイルとしてではなく、MySQLテーブルとして使用する必要があります。

General_logをテーブルとして作成するのはなぜですか?

  • あなたはそれに対してSQLを実行することができます。
  • 非常に簡単に回転できます。

どのように構成しますか?

MySQL 5.1以降、次のオプションが導入されました: log-output

  • log-outputFILE(デフォルト)に設定すると、ログエントリがテキストファイルに書き込まれます。
  • log-outputTABLEに設定すると、ログエントリがmysql.general_logに書き込まれます。
  • log-outputTABLE,FILEに設定すると、ログエントリがmysql.general_logとテキストファイルに書き込まれます。

変更しなければならない重要なことが1つあります。

標準のmysql.general_logテーブルを見てみましょう。

mysql> show create table mysql.general_log\G 
*************************** 1. row *************************** 
       Table: general_log 
Create Table: CREATE TABLE `general_log` ( 
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
      ON UPDATE CURRENT_TIMESTAMP, 
  `user_Host` mediumtext NOT NULL, 
  `thread_id` int(11) NOT NULL, 
  `server_id` int(10) unsigned NOT NULL, 
  `command_type` varchar(64) NOT NULL, 
  `argument` mediumtext NOT NULL 
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' 
1 row in set (0.09 sec) 

それはCSVファイルですか?わーい!!!誰がそのための時間を持っていますか?心配しないで、MyISAMテーブルに変えてください

ALTER TABLE mysql.general_log ENGINE = MyISAM; 
ALTER TABLE mysql.general_log ADD INDEX (event_time); 

すでにMySQLを起動している場合は、代わりに次のようにしてください。

SET @old_log_state = @@global.general_log; 
SET GLOBAL general_log = 'OFF'; 
ALTER TABLE mysql.general_log ENGINE = MyISAM; 
ALTER TABLE mysql.general_log ADD INDEX (event_time); 
SET GLOBAL general_log = @old_log_state; 

これで、一般的なログテーブルは次のようになります。

mysql> show create table general_log\G
*************************** 1. row ***************************
       Table: general_log
Create Table: CREATE TABLE `general_log` (
  `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
      ON UPDATE CURRENT_TIMESTAMP,
  `user_Host` mediumtext NOT NULL,
  `thread_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumtext NOT NULL,
  KEY `event_time` (`event_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'
1 row in set (0.00 sec)

MyISAMテーブルの場合、一般ログをどのようにローテーションしますか?

mysql.general_logを空白にする方法の例を次に示します。

SET @old_log_state = @@global.general_log; 
SET GLOBAL general_log = 'OFF'; 
CREATE TABLE mysql.general_log_new LIKE mysql.general_log; 
DROP TABLE mysql.general_log; 
ALTER TABLE mysql.general_log_new RENAME mysql.general_log; 
SET GLOBAL general_log = @old_log_state; 

過去3日間のエントリを保持する方法の例を次に示します。

SET @old_log_state = @@global.general_log; 
SET GLOBAL general_log = 'OFF'; 
CREATE TABLE mysql.general_log_new LIKE mysql.general_log; 
INSERT INTO mysql.general_log_new 
SELECT * FROM mysql.general_log WHERE event_time > NOW() - INTERVAL 3 DAY; 
DROP TABLE mysql.general_log; 
ALTER TABLE mysql.general_log_new RENAME mysql.general_log; 
SET GLOBAL general_log = @old_log_state; 

警告

この機能は、MySQL 5.1/5、5/5.6で使用できます。 MySQL 5.0.77から最新にアップグレードする必要があります

エピローグ

私はここでもっとたくさん書くことができましたが、これはDBAStackExchangeで何度も議論しました。これがこのテーマに関する私の投稿の一部です:

4
RolandoMySQLDBA

これがアイデアですが、うまくいかないかもしれません。
a FIFOパイプを/var/log/mysql/named_pipeに作成します。一方の端では、MySQLにそれを一般的なログファイルのファイル名として使用させます。

反対側では、次のようなものを設定します

grep "login" < /var/log/mysql/named_pipe > /var/log/mysql/logins

ログから出た後の行を正確にgrepする必要があります。

それはmight動作します。動作しない場合があります。

0
Tom O'Connor

同じことをする必要がありました。 MySQL5.6およびMySQL5.7には、必要な情報を取得してテーブルに格納する方法があります。これがMySQL 5.0または5.5で可能かどうかはわかりません。これが私がしたことです:

  1. 必要なテーブルを含むデータベースを作成しました。
  2. 必要なテーブルを作成しました
  3. 情報を取得してテーブルに挿入する手順を作成しました
  4. すべての接続がストアドプロシージャを実行するようにMySQL構成ファイルを変更しました
  5. すべてのユーザーにストアドプロシージャの実行権限を与えます。

注:ユーザーがスーパーまたはルートのような特権で接続している場合、これは情報をキャプチャしません。

MySQL構成ファイルのmysqldセクションに、次のように追加しました:# ***以下のパラメーターは、ユーザー接続をログに記録します

init_connect='CALL connectionlogging.usp_InsertUserConnection'

取得する必要がある情報は、ユーザーID、接続要求の送信元のホスト、ユーザーが接続しているデータベース、接続に関する情報、およびタイムスタンプです。

この情報を使用して、暗号化された接続を使用しているユーザー、接続しているデータベース、およびユーザーがいつ接続するかを判別します。

0
jprichart