ラベル PostgreSQL の投稿を表示しています。 すべての投稿を表示
ラベル PostgreSQL の投稿を表示しています。 すべての投稿を表示

2018年9月29日土曜日

【PostgreSQL】【pg_rman】別サーバーにリストア

pg_rmanだと設定も復旧されてしまう。そのため、別のサーバーにリストアする場合は注意が必要。設定を復旧しない方法は未調査。

2018年9月28日金曜日

【SQL】pg_dumpしたデータでリストア失敗【PostgresSQL】

[事象1]
pg_dumpコマンドで出力したデータを別のサーバーのDBにpsqlコマンドでリストアしたら重複キーエラーが発生した。

補足:実際はレコードのinsertは成功、つまり重複レコードが入ってしまった。その後の主キー制約の作成で重複キーエラーが出力されていた。
postgresのダンプデータの順序は、レコードをcopyした後に主キー制約作成(インデックス作成)という順序になっているらしく、この様な状態となった。

これだけ聞くとPostgreSQLのダンプのバグのように思えるが、実際は違うようだ。

[調査]
元のDB(pg_dumpを実行したDB)を見ると元のDBが壊れていた。
事象としては以下のselect文で結果が違うと言う不可思議な現象だった。

①whereで主キー指定したselect 文
②whereで主キー以外を指定したselect文

これらの結果は一緒になる想定だったのだが、実行すると結果が違って、②の方が数十行多く出力されていた。
このテーブルには、主キーが設定されていたにも関わらず、明らかに重複キーの状態でテーブルに登録されていた。
これによりインデックスと生テーブルに不一致が発生したと判断した。
つまり、インデックスは正しいが、テーブルには重複レコードが存在している。

因みにpostgresはupdateする際は、追記型つまり内部で行をコピー&元の行に削除フラグをたてているはず。この削除フラグの変更が失敗したのではないかと思う。

元のDBが壊れた理由は不明。訳あって調査出来ず。

[復旧]
2回ほど復旧を実施した。もとのDBは運用環境のため、触る事が出来ない。そのため、リストア先DBの復旧を行った。リストア前、リストア後の復旧を行った。とある事情により、それぞれ違う方法を使用した。

(a)ダンプデータを修正して再リストア
中途半端にリストアしたDBは破棄して、ダンプデータをviで修正(重複レコード削除)して再度リストア。
この方法はダンプデータが巨大だとかなり時間がかかる。と言うか、でかすぎるとエディタがまともに動かなくなる。一応、ダンプデータは5GB程度だったかな?なのでこれでも復旧出来た。また、バイナリダンプの場合は使用出来ない。

(b)中途半端にリストアされたDBを復旧
select row_number over partition byで重複レコードを探す。group by having countでも良い。その結果から残したい行のinsert文を作成。
で、重複レコードを二行とも削除(主キー制約作成失敗しているため、A5では片方ずつの削除が出来なかった)。
で作成したinsert文を実行。その後、失敗していた主キー制約を作成して復旧完了。こちらは復旧の仕方が正しいのか不安がある。

2018年9月21日金曜日

【SEの仕事】数十万件のテーブル作ったら…【PostgreSQL】

お客さんの依頼で数十万テーブル(数百万だったかも)作成した時の話です。動的にテーブルを選択するということです。

通常はやらないです。と言うか、普段の開発から逸脱したことはすべきではないです。

上司がその依頼を受け、私は設計後にそのプロジェクトに入ったので止めようが無かったのです。

PostgreSQLの開発者が、数十万テーブルを想定してるのか不明ですが、RDBの使い方としては誤りと言っていいと思います。リレーショナルデータベースと言うものを全く理解してません。リレーショナルデータベースをただのデータとして捉えてはいけません。

結論を言うと、create tableで躓く羽目になりました。テーブルが多くなれば多くなる程、create tableの速度が落ちて行ったのです。確か数十万だか、数百万テーブル作成するのに、1日程度掛かりました。あり得ないです。再構築が容易く出来ないです。また、運用開始後、列追加などが容易く出来るか心配です。

そもそも、create table文を自作する羽目になる(ツールでcreate table文を作成後、テーブル名に_1、_2、を足していく)わけで、これもあり得ないです。通常は、visualstudioやeclipse、そのほかのツールで自動生成し、速攻DBに投入します。(初回起動時に生成する方法もあります。)

これでは、通常通りの開発が出来なくなります。元々、そのプロジェクトは破綻してましたので、どれ程の遅延を招いたか定かでは有りませんが、確実に開発速度を落としていました。

この話に限らず、通常の開発から逸脱したことは避けるべきです。