This is a translation of the original English documentation page. Help us make it better.

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';

使用可能なディスク容量が懸念される場合は、ダウンタイムなしで主キーを変更する の手順に従ってください。 その他のオプションもご利用いただけます。

  • MySQLパラメータsort_buffer_sizeを増やすと、手動でインデックスを再構築する際のディスク容量使用量を削減できる場合があります。 ただし、この変数を変更すると、データベース全体のメモリ使用量に影響する可能性があります。
  • 不要な可能性のあるデータを削除して、容量を解放することを検討してください。
  • ハウスキーピングを実行する前に、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;

リソースの過剰な使用を避けるため、この操作は複数の INSERT INTO 文(必要に応じて WHERE clock 句を含む)で実行できます。

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 を設定することで、一時オブジェクト用に別のテーブルスペースを指定できます。
  • 不要な可能性のあるデータを削除して、容量を解放することを検討してください。
  • ハウスキーパーを実行する前に、データ保存期間 ハウスキーパー パラメータを減らすことを検討してください。
ダウンタイムを伴う主キーの変更

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;

過剰なリソース使用を避けるため、この操作は複数の INSERT INTO 文(必要に応じて WHERE clock 句を含む)で実行できます。

4. 古いテーブルを削除します。

DROP TABLE auditlog_old;

Oracle

インデックスの再構築に関する重要な注意事項

Oracle は、ALTER TABLE 操作中に主キーのインデックスを自動的に再構築します。

ただし、データベースのパフォーマンスを最適化するには、ALTER INDEX <index> REBUILD PARALLEL 文を使用して手動でインデックスを再構築することを強くお勧めします。

インデックスの再構築には、一時的に大量のディスク容量が必要になる場合があります。

使用可能なディスク容量が懸念される場合は、ダウンタイムなしで主キーを変更する の手順に従ってください。

その他のオプションも利用可能です。

  • Oracle パラメータの SORT_AREA_SIZE を増やすと、手動でインデックスを再構築する際のディスク容量使用量を削減できる場合があります。

ただし、この変数を変更すると、データベース全体のメモリ使用量に影響します。 - PARALLEL句を使用して並列度を設定できます。例:ALTER INDEX auditlog_1 REBUILD PARALLEL 4 - 不要な可能性のあるデータを削除して、スペースを解放することを検討してください。 - ハウスキーパーを実行する前に、データ保存期間 housekeeper パラメータを減らすことを検討してください。

ダウンタイムを伴う主キーの変更

1. 制約名を取得します。

SELECT CONSTRAINT_NAME FROM all_constraints WHERE TABLE_NAME = 'AUDITLOG' AND CONSTRAINT_TYPE = 'P';

2. 現在の auditlog テーブルの主キーを削除し、新しい主キーを追加します。

ALTER TABLE auditlog DROP CONSTRAINT <constraint_name>;
       ALTER TABLE auditlog ADD CONSTRAINT auditlog_pk PRIMARY KEY (auditid, clock);

3. インデックスを再構築します(オプションですが、強く推奨されます。インデックスの再構築に関する重要な注意事項を参照してください)。

3.1. インデックス名を取得します。

SELECT index_name FROM user_indexes WHERE table_name='AUDITLOG';

3.2. 各インデックスを再構築します。

ALTER INDEX auditlog_pk REBUILD PARALLEL;
       ALTER INDEX auditlog_1 REBUILD PARALLEL;
       ALTER INDEX auditlog_2 REBUILD PARALLEL;
       ALTER INDEX auditlog_3 REBUILD PARALLEL;
ダウンタイムなしで主キーを変更する

1. 新しい主キーを持つ新しいテーブルを作成し、インデックスを作成します。

CREATE TABLE auditlog_new (
         auditid              nvarchar2(25)                             ,
         userid               number(20)                                NULL,
         username             nvarchar2(100)  DEFAULT ''                ,
         clock                number(10)      DEFAULT '0'               NOT NULL,
         ip                   nvarchar2(39)   DEFAULT ''                ,
         action               number(10)      DEFAULT '0'               NOT NULL,
         resourcetype         number(10)      DEFAULT '0'               NOT NULL,
         resourceid           number(20)                                NULL,
         resource_cuid        nvarchar2(25)                             ,
         resourcename         nvarchar2(255)  DEFAULT ''                ,
         recordsetid          nvarchar2(25)                             ,
         details              nclob           DEFAULT ''                ,
         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;

過剰なリソース使用を避けるため、この操作は複数の INSERT INTO 文(必要に応じて WHERE clock 句を含む)で実行できます。

4. 古いテーブルを削除します。

DROP TABLE auditlog_old;

参照