it技術:データベース:postgresql:pg_repack
差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
| it技術:データベース:postgresql:pg_repack [2025/07/04 11:11] – [調査] yajuadmin | it技術:データベース:postgresql:pg_repack [2025/07/08 16:50] (現在) – [ビルドできても例外エラー] yajuadmin | ||
|---|---|---|---|
| 行 9: | 行 9: | ||
| * [[https:// | * [[https:// | ||
| - | ==== 調査 ==== | + | <wrap em> |
| + | ===== 調査 | ||
| pg_repack のデバッグでは、set_pglocale_pgservice(argv[0], | pg_repack のデバッグでは、set_pglocale_pgservice(argv[0], | ||
| vaccumedb のデバッグでは、set_pglocale_pgservice(argv[0], | vaccumedb のデバッグでは、set_pglocale_pgservice(argv[0], | ||
| 行 40: | 行 41: | ||
| </ | </ | ||
| - | === select関数の参照先の違い === | + | ==== 必要なobjファイルだけをリンク ==== |
| - | pg_repack の select関数 は、win32_port.h → socket.c の pgwin32_select関数 を参照している。\\ | + | socket.obj、singal.obj をリンクすると、7つの未解決エラーが出る。 |
| - | pgbench や pg_recvlogical の select関数 は、winSock2.h の select関数 を参照している。 | + | < |
| + | 1> | ||
| + | 1> | ||
| + | 1> | ||
| + | 1> | ||
| + | 1> | ||
| + | 1> | ||
| + | 1> | ||
| + | </ | ||
| + | |||
| + | このぐらいならと elog.obj を追加すると多くの未解決エラーが出る。同じように追加するとどんどん別のobjファイルから未解決エラーが出る。postgres.libとリンクするのと変わらなくなるため、この方法での解決はやめた。 | ||
| + | |||
| + | ^関数名^モジュール名^オブジェクト名| | ||
| + | |ExceptionalCondition|asset.c|assert.obj| | ||
| + | |pg_codepage_to_encoding|chklocale.c|chklocale.obj| | ||
| + | |MemoryContextStrdup|mcxt.c|mcxt.obj| | ||
| + | |GetTopTransactionIdIfAny|xact.c|xact.obj| | ||
| + | |GetMessageEncoding|mbutils.c|mbutils.obj| | ||
| + | |pgwin32_message_to_UTF16|mbutils.c|mbutils.obj| | ||
| + | |pq_putmessage_v2|pqcomm.c|pqcomm.obj| | ||
| + | |pq_beginmessage|pdformat.c|pdformat.obj| | ||
| + | |pq_endmessage|pqformat.c|pqformat.obj| | ||
| + | |pq_sendstring|pqformat.c|pqformat.obj| | ||
| + | |pq_send_ascii_string|pdformat.c|pdformat.obj| | ||
| + | |pg_localtime|localtime.c|localtime.obj| | ||
| + | |pg_strftime|strftime.c|strftime.obj| | ||
| + | |ProcessInterrupts|postgres, | ||
| + | |GetBackendTypeDesc|miscinit.c|miscinit.obj| | ||
| + | |pgstat_get_my_query_id|backend_status.c|backend_status.obj| | ||
| + | |write_syslogger_file|syslogger.c|syslogger.obj| | ||
| + | |proc_exit|ipc.c|ipc.obj| | ||
| + | |MemoryContextReset|mcxt.c|mcxt.obj| | ||
| + | |get_ps_display|ps_status.c|ps_status.obj| | ||
| + | |||
| + | ==== 必要な関数だけを作成 ==== | ||
| + | socket.c と signal.c の必要関数を抜き出し、新しい socket.c を作成して、pg_repack に socket.c を追加 | ||
| + | |||
| + | 次項目の winSock2.h にある Select関数を使用して問題ないなら、新しい socket.c は使用しない方針とする。 | ||
| + | |||
| + | ==== select関数の参照先の違い | ||
| + | pg_repack の select関数 は、win32_port.h → socket.c の pgwin32_select関数を参照している。\\ | ||
| + | pgbench や pg_recvlogical の select関数 は、winSock2.h の select関数を参照している。 | ||
| select関数 を win32_port.h か winSock2.h を参照させる違いはどこにあるのか? | select関数 を win32_port.h か winSock2.h を参照させる違いはどこにあるのか? | ||
| + | put.h にある #include " | ||
| + | pgbench.c には、bool型とselect関数があるが、参照エラーになっていない。 | ||
| + | |||
| + | put.h にある、# | ||
| + | |||
| + | ==== versionの指定 ==== | ||
| + | 「pg_repack --version」を実行したら、unknown となった。 | ||
| + | |||
| + | Makefileでは、コンパイル時にREPACK_VERSIONにバージョン番号をセットしているが、Windowsでは REPACK_VERSION を指定していないため、プロジェクトのプロパティ C/ | ||
| + | lib側も同様に設定すること | ||
| + | |||
| + | <code c pg_repack.c> | ||
| + | #ifdef REPACK_VERSION | ||
| + | /* macro trick to stringify a macro expansion */ | ||
| + | #define xstr(s) str(s) | ||
| + | #define str(s) #s | ||
| + | const char *PROGRAM_VERSION = xstr(REPACK_VERSION); | ||
| + | #else | ||
| + | const char *PROGRAM_VERSION = " | ||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | ==== EnterCriticalSectionで例外エラー ==== | ||
| + | 0x00007FFB838949E6 (ntdll.dll) で例外がスローされました (pg_repack.exe 内): 0xC0000005: 場所 0x0000000000000024 への書き込み中にアクセス違反が発生しました | ||
| + | |||
| + | > | ||
| + | > | ||
| + | > InitializeCriticalSection() しましたか? | ||
| + | |||
| + | 調査すると、InitializeCriticalSection()を参照している init_cancel_handler関数が、コメントアウトされており呼ばれていない。 | ||
| + | |||
| + | on_before_exec関数と on_after_exec関数の2ヶ所をinit_cancel_handler関数を追記して修正すると例外エラーが発生しなくなった。 | ||
| + | |||
| + | <code c> | ||
| + | #ifdef WIN32 | ||
| + | init_cancel_handler(); | ||
| + | EnterCriticalSection(& | ||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== relhasoids列がないエラー ==== | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | <code sql> | ||
| + | SELECT * FROM repack.tables | ||
| + | SQL: column " | ||
| + | </ | ||
| + | relhasoidsは、PostgreSQLのシステムカタログに存在するカラムであり、バージョン11までは存在していたが、バージョン12からは削除されている。 | ||
| + | |||
| + | pg_repack.sql.in ファイルには、get_storage_param 関数内で relhasoids を使用している。 | ||
| + | |||
| + | <code sql pg_repack.sql.in> | ||
| + | get_storage_param | ||
| + | |||
| + | -- table oid | ||
| + | SELECT 'oids = ' || | ||
| + | CASE WHEN relhasoids | ||
| + | THEN ' | ||
| + | ELSE ' | ||
| + | END | ||
| + | FROM pg_class | ||
| + | </ | ||
| + | |||
| + | Makefileファイル内にて PostgreSQL12以降は relhasoids を false に書き換えている。 | ||
| + | <code text Makefile> | ||
| + | # It is not possible to create tables with OIDs on PostgreSQL 12 or later | ||
| + | ifeq ($(shell echo $$(($(INTVERSION) < 1200))),1) | ||
| + | RELHASOIDS := relhasoids | ||
| + | else | ||
| + | RELHASOIDS := false | ||
| + | endif | ||
| + | |||
| + | pg_repack--$(REPACK_VERSION).sql: | ||
| + | sed ' | ||
| + | | sed ' | ||
| + | </ | ||
| + | |||
| + | PostgreSQL 12以降は最終的には下記に書き換わる。\\ | ||
| + | <wrap em> | ||
| + | |||
| + | <code sql pg_repack.sql> | ||
| + | get_storage_param | ||
| + | |||
| + | -- table oid | ||
| + | SELECT 'oids = ' || | ||
| + | CASE WHEN false | ||
| + | THEN ' | ||
| + | ELSE ' | ||
| + | END | ||
| + | FROM pg_class | ||
| + | </ | ||
| + | |||
| + | ===== 簡易テスト ===== | ||
| + | ようやく動作させることが出来るようになったので、簡易テスト | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | <code sql テストデータ作成> | ||
| + | CREATE TABLE t1 (id int primary key, val text); | ||
| + | |||
| + | SELECT pg_size_pretty(pg_total_relation_size(' | ||
| + | |||
| + | INSERT INTO t1 VALUES(generate_series(1, | ||
| + | |||
| + | SELECT pg_size_pretty(pg_total_relation_size(' | ||
| + | |||
| + | -- 5回ほど実行 | ||
| + | UPDATE t1 SET VAL = ' | ||
| + | UPDATE t1 SET VAL = ' | ||
| + | UPDATE t1 SET VAL = ' | ||
| + | UPDATE t1 SET VAL = ' | ||
| + | UPDATE t1 SET VAL = ' | ||
| + | |||
| + | SELECT pg_size_pretty(pg_total_relation_size(' | ||
| + | -- 2736 kB | ||
| + | |||
| + | -- バキュームしてもサイズは小さくならないことを確認 | ||
| + | VACUUM t1; | ||
| + | |||
| + | SELECT pg_size_pretty(pg_total_relation_size(' | ||
| + | -- 2736 kB | ||
| + | </ | ||
| + | |||
| + | DB: | ||
| + | また、-e オプション(--echo)で、サーバに送信するSQLを表示するようにしておきます。 | ||
| + | |||
| + | [[https:// | ||
| + | < | ||
| + | pg_repack -n -t wh_test.t1 -d wh_test -U wh_test -e | ||
| + | |||
| + | LOG: (query) SET search_path TO pg_catalog, pg_temp, public | ||
| + | LOG: (query) SET search_path TO pg_catalog, pg_temp, public | ||
| + | LOG: (query) select repack.version(), | ||
| + | LOG: (query) SET statement_timeout = 0 | ||
| + | LOG: (query) SET search_path = pg_catalog, pg_temp, public | ||
| + | LOG: (query) SET client_min_messages = warning | ||
| + | LOG: (query) SELECT r FROM (VALUES ($1)) AS given_t(r) WHERE NOT EXISTS( | ||
| + | LOG: (param:0) = wh_test.t1 | ||
| + | LOG: (query) SELECT t.*, coalesce(v.tablespace, | ||
| + | LOG: (param:0) = (null) | ||
| + | LOG: (param:1) = wh_test.t1 | ||
| + | INFO: repacking table " | ||
| + | LOG: (query) SELECT pg_try_advisory_lock($1, | ||
| + | LOG: (param:0) = 16185446 | ||
| + | LOG: (param:1) = 16738 | ||
| + | LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED | ||
| + | LOG: (query) SET LOCAL statement_timeout = 100 | ||
| + | LOG: (query) LOCK TABLE wh_test.t1 IN ACCESS EXCLUSIVE MODE | ||
| + | LOG: (query) RESET statement_timeout | ||
| + | LOG: (query) SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = $1 AND NOT indisvalid | ||
| + | LOG: (param:0) = 16738 | ||
| + | LOG: (query) SELECT indexrelid, repack.repack_indexdef(indexrelid, | ||
| + | LOG: (param:0) = 16738 | ||
| + | LOG: (param:1) = (null) | ||
| + | LOG: (query) SELECT repack.conflicted_triggers($1) | ||
| + | LOG: (param:0) = 16738 | ||
| + | LOG: (query) CREATE TYPE repack.pk_16738 AS (id integer) | ||
| + | LOG: (query) CREATE TABLE repack.log_16738 (id bigserial PRIMARY KEY, pk repack.pk_16738, | ||
| + | LOG: (query) CREATE TRIGGER repack_trigger AFTER INSERT OR DELETE OR UPDATE ON wh_test.t1 FOR EACH ROW EXECUTE PROCEDURE repack.repack_trigger(' | ||
| + | LOG: (query) ALTER TABLE wh_test.t1 ENABLE ALWAYS TRIGGER repack_trigger | ||
| + | LOG: (query) SELECT repack.disable_autovacuum(' | ||
| + | LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED | ||
| + | LOG: (query) SELECT pg_backend_pid() | ||
| + | LOG: (query) SELECT pid FROM pg_locks WHERE locktype = ' | ||
| + | LOG: (query) COMMIT | ||
| + | LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE | ||
| + | LOG: (query) SELECT set_config(' | ||
| + | LOG: (query) SET LOCAL synchronize_seqscans = off | ||
| + | LOG: (query) SELECT coalesce(array_agg(l.virtualtransaction), | ||
| + | LOG: (param:0) = 6804 | ||
| + | LOG: (param:1) = pg_repack | ||
| + | LOG: (query) DELETE FROM repack.log_16738 | ||
| + | LOG: (query) SELECT pid FROM pg_locks WHERE locktype = ' | ||
| + | LOG: (query) SET LOCAL statement_timeout = 100 | ||
| + | LOG: (query) LOCK TABLE wh_test.t1 IN ACCESS SHARE MODE | ||
| + | LOG: (query) RESET statement_timeout | ||
| + | LOG: (query) CREATE TABLE repack.table_16738 WITH (oids = false) TABLESPACE pg_default AS SELECT id,val FROM ONLY wh_test.t1 WITH NO DATA | ||
| + | LOG: (query) INSERT INTO repack.table_16738 SELECT id,val FROM ONLY wh_test.t1 | ||
| + | LOG: (query) SELECT repack.disable_autovacuum(' | ||
| + | LOG: (query) COMMIT | ||
| + | LOG: (query) CREATE UNIQUE INDEX index_16743 ON repack.table_16738 USING btree (id) | ||
| + | LOG: (query) SELECT repack.repack_apply($1, | ||
| + | LOG: (param:0) = SELECT * FROM repack.log_16738 ORDER BY id LIMIT $1 | ||
| + | LOG: (param:1) = INSERT INTO repack.table_16738 VALUES ($1.*) | ||
| + | LOG: (param:2) = DELETE FROM repack.table_16738 WHERE (id) = ($1.id) | ||
| + | LOG: (param:3) = UPDATE repack.table_16738 SET (id, val) = ($2.id, $2.val) WHERE (id) = ($1.id) | ||
| + | LOG: (param:4) = DELETE FROM repack.log_16738 WHERE id IN ( | ||
| + | LOG: (param:5) = 1000 | ||
| + | LOG: (query) SELECT pid FROM pg_locks WHERE locktype = ' | ||
| + | LOG: (param:0) = {} | ||
| + | LOG: (query) SAVEPOINT repack_sp1 | ||
| + | LOG: (query) SET LOCAL statement_timeout = 100 | ||
| + | LOG: (query) LOCK TABLE wh_test.t1 IN ACCESS EXCLUSIVE MODE | ||
| + | LOG: (query) RESET statement_timeout | ||
| + | LOG: (query) SELECT repack.repack_apply($1, | ||
| + | LOG: (param:0) = SELECT * FROM repack.log_16738 ORDER BY id LIMIT $1 | ||
| + | LOG: (param:1) = INSERT INTO repack.table_16738 VALUES ($1.*) | ||
| + | LOG: (param:2) = DELETE FROM repack.table_16738 WHERE (id) = ($1.id) | ||
| + | LOG: (param:3) = UPDATE repack.table_16738 SET (id, val) = ($2.id, $2.val) WHERE (id) = ($1.id) | ||
| + | LOG: (param:4) = DELETE FROM repack.log_16738 WHERE id IN ( | ||
| + | LOG: (param:5) = 0 | ||
| + | LOG: (query) SELECT repack.repack_swap($1) | ||
| + | LOG: (param:0) = 16738 | ||
| + | LOG: (query) COMMIT | ||
| + | LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED | ||
| + | LOG: (query) SAVEPOINT repack_sp1 | ||
| + | LOG: (query) SET LOCAL statement_timeout = 100 | ||
| + | LOG: (query) LOCK TABLE wh_test.t1 IN ACCESS EXCLUSIVE MODE | ||
| + | LOG: (query) RESET statement_timeout | ||
| + | LOG: (query) SELECT repack.repack_drop($1, | ||
| + | LOG: (param:0) = 16738 | ||
| + | LOG: (param:1) = 4 | ||
| + | LOG: (query) COMMIT | ||
| + | LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED | ||
| + | LOG: (query) ANALYZE wh_test.t1 | ||
| + | LOG: (query) COMMIT | ||
| + | LOG: (query) SELECT pg_advisory_unlock($1, | ||
| + | LOG: (param:0) = 16185446 | ||
| + | LOG: (param:1) = 16738 | ||
| + | </ | ||
| + | |||
| + | 2736 kB から 632 kBまでサイズが小さくなった。 | ||
| + | |||
| + | <code sql 結果> | ||
| + | SELECT pg_size_pretty(pg_total_relation_size(' | ||
| + | -- 632 kB | ||
| + | </ | ||
it技術/データベース/postgresql/pg_repack.1751595101.txt.gz · 最終更新: 2025/07/04 11:11 by yajuadmin
