4 監査ログテーブルのパーティション化の準備
概要
一部のデータベース(MySQL など)では、パーティション列をテーブルの一意制約の一部にする必要があります。
したがって、auditlog テーブルを時間でパーティション分割するには、主キーを auditid から複合キー auditid + clock に変更する必要があります。
このセクションでは、auditlog テーブルの主キーを変更する手順について説明します。
::: 重要
このページに記載されている手順は、上級ユーザー向けに設計されています。
これらの手順は、お客様の構成に合わせて調整する必要がある場合があります。
主キーの変更は、将来のアップグレードパッチと互換性がなくなる可能性があるため、手動でのアップグレードが必要になる場合があります。
主キーの変更は、auditlog テーブルのサイズによっては、多くのリソースを消費し、多くの時間を要する操作となる場合があります。
変更中は、Zabbix サーバーを停止し、Zabbix フロントエンドを メンテナンスモード に切り替えることをお勧めします。
ただし、どうしても必要な場合は、ダウンタイムなしで主キーを変更する方法があります(下記参照)
:::
auditlog テーブルをパーティション分割すると、例えば大規模なシステムにおけるハウスキーピング機能の向上につながります。
Zabbix の housekeeping は現在、パーティション分割されたテーブルを利用できません(TimescaleDB を除く)が、スクリプトを使用して Zabbix ハウスキーピングを無効化し、パーティションを削除することができます。
Zabbix 7.0 以降、TimescaleDB の auditlog テーブルはハイパーテーブルに変換され、ハウスキーパーがデータをチャンク単位で削除できるようになりました。
既存の auditlog テーブルをハイパーテーブルにアップグレードするには、TimescaleDB スキーマのアップグレード を参照してください。
MySQL
インデックス再構築に関する重要な注意事項
MySQL は、ALTER TABLE 操作中に主キーのインデックスを自動的に再構築します。
ただし、データベースの最適なパフォーマンスを確保するために、OPTIMIZE TABLE 文を使用してインデックスも手動で再構築することを強く推奨します。
インデックスの再構築では、一時的にテーブル自体が使用している容量と同程度の追加ディスク領域が必要になる場合があります。 現在のデータおよびインデックスのサイズを取得するには、次の文を実行できます。
ANALYZE TABLE auditlog;
SHOW TABLE STATUS LIKE 'auditlog';
使用可能なディスク領域が懸念される場合は、ダウンタイムなしでの主キー変更 の手順に従ってください。 そのほかにも、次のような方法があります。
sort_buffer_sizeMySQL パラメータを増やすことで、インデックスを手動で再構築する際のディスク使用量を削減できる場合があります。 ただし、この変数を変更すると、データベース全体のメモリ使用量に影響する可能性があります。- 不要な可能性のあるデータを削除して、空き領域を確保することを検討してください。
- housekeeper を実行する前に、housekeeper の データ保存期間 パラメータを短くすることを検討してください。
ダウンタイムを伴う主キーの変更
1. 現在の auditlog テーブルの主キーを削除し、新しい主キーを追加します。
ALTER TABLE Auditlog DROP PRIMARY KEY, ADD PRIMARY KEY (auditid, clock);
2. インデックスを再構築します(オプション設定ですが、強く推奨します。インデックスの再構築に関する重要な注意事項を参照してください)
OPTIMIZE TABLE Auditlog;
ダウンタイムなしでの主キーの変更
主キーを手動で変更する方法をここで説明します。
または、Percona の pt-online-schema-change ツールキットを使用することもできます。
このツールキットは、auditlog テーブルの変更に使用する領域を最小限に抑えながら、以下の操作を自動的に実行します。
1. 新しい主キーを持つ新しいテーブルを作成し、インデックスを作成します。
CREATE TABLE `auditlog_new` (
`auditid` varchar(25) NOT NULL,
`userid` bigint unsigned NULL,
`username` varchar(100) DEFAULT '' NOT NULL,
`clock` integer DEFAULT '0' NOT NULL,
`ip` varchar(39) DEFAULT '' NOT NULL,
`action` integer DEFAULT '0' NOT NULL,
`resourcetype` integer DEFAULT '0' NOT NULL,
`resourceid` bigint unsigned NULL,
`resource_cuid` varchar(25) NULL,
`resourcename` varchar(255) DEFAULT '' NOT NULL,
`recordsetid` varchar(25) NOT NULL,
`details` longtext NOT NULL,
PRIMARY KEY (auditid,clock)
) ENGINE=InnoDB;
CREATE INDEX `auditlog_1` ON `auditlog_new` (`userid`,`clock`);
CREATE INDEX `auditlog_2` ON `auditlog_new` (`clock`);
CREATE INDEX `auditlog_3` ON `auditlog_new` (`resourcetype`,`resourceid`);
2. テーブルを入れ替えます。
RENAME TABLE auditlog TO auditlog_old, auditlog_new TO auditlog;
3. 古いテーブルから新しいテーブルへデータをコピーします。
INSERT INTO auditlog SELECT * FROM auditlog_old;
過剰なリソース使用を避けるため、これはチャンク単位(必要に応じて WHERE clock 句を含む複数の INSERT INTO 文)で実行できます。
4. 古いテーブルを削除します。
DROP TABLE auditlog_old;
PostgreSQL
インデックス再構築に関する重要な注意事項
PostgreSQL は、ALTER TABLE 操作中に主キーのインデックスを自動的に再構築します。
ただし、データベースのパフォーマンスを最適な状態に保つため、REINDEX TABLE CONCURRENTLY 文を使用してインデックスも手動で再構築することを強く推奨します。
インデックスの再構築では、一時的に現在インデックスが使用しているディスク容量の最大 3 倍が必要になる場合があります。 現在のインデックスサイズを確認するには、次のクエリを実行できます。
SELECT pg_size_pretty(pg_indexes_size('auditlog'));
使用可能なディスク容量が懸念される場合は、ダウンタイムなしで主キーを変更する の手順に従ってください。 そのほかにも、次のような方法があります。
- PostgreSQL パラメータ
maintenance_work_memを増やすことで、インデックスを手動で再構築する際のディスク使用量を削減できる場合があります。 ただし、この変数を変更すると、データベース全体のメモリ使用量に影響する可能性があります。 - より多くの空き容量がある別のディスクまたはテーブルスペースがある場合は、インデックス再構築用の一時保存場所を変更することを検討してください。
一時オブジェクト用に別のテーブルスペースを指定するには、PostgreSQL パラメータ
temp_tablespacesを設定できます。 - 不要な可能性のあるデータを削除して、空き容量を確保することを検討してください。
- housekeeper を実行する前に、housekeeper の データ保存期間 パラメータを短くすることを検討してください。
ダウンタイムを伴う主キーの変更
1. 現在の auditlog テーブルの主キーを削除し、新しい主キーを追加します。
ALTER TABLE Auditlog DROP CONSTRAINT Auditlog_pkey;
ALTER TABLE Auditlog ADD PRIMARY KEY (auditid,clock);
2. インデックスを再構築します(オプション作業ですが、強く推奨します。インデックスの再構築に関する重要な注意事項を参照してください)
REINDEX TABLE CONCURRENTLY Auditlog;
ダウンタイムなしでの主キーの変更
主キーを手動で変更する方法をここで説明します。
または、新しいテーブルの作成、データのコピー、テーブルの入れ替えのために、pg_repack 拡張機能を検討することもできます。
1. 新しい主キーを持つ新しいテーブルを作成し、インデックスを作成します。
CREATE TABLE auditlog_new (
auditid varchar(25) NOT NULL,
userid bigint NULL,
username varchar(100) DEFAULT '' NOT NULL,
clock integer DEFAULT '0' NOT NULL,
ip varchar(39) DEFAULT '' NOT NULL,
action integer DEFAULT '0' NOT NULL,
resourcetype integer DEFAULT '0' NOT NULL,
resourceid bigint NULL,
resource_cuid varchar(25) NULL,
resourcename varchar(255) DEFAULT '' NOT NULL,
recordsetid varchar(25) NOT NULL,
details text DEFAULT '' NOT NULL,
PRIMARY KEY (auditid,clock)
);
CREATE INDEX auditlog_new_1 ON auditlog_new (userid,clock);
CREATE INDEX auditlog_new_2 ON auditlog_new (clock);
CREATE INDEX auditlog_new_3 ON auditlog_new (resourcetype,resourceid);
2. テーブルを入れ替えます。
ALTER TABLE auditlog RENAME TO auditlog_old;
ALTER TABLE auditlog_new RENAME TO auditlog;
3. 古いテーブルから新しいテーブルへデータをコピーします。
INSERT INTO auditlog SELECT * FROM auditlog_old;
過剰なリソース使用を避けるため、これはチャンク単位で実行できます(必要に応じて WHERE clock 句を付けた複数の INSERT INTO 文)。
4. 古いテーブルを削除します。
DROP TABLE auditlog_old;