Powered by SmartDoc

PostgreSQLのラージオブジェクトの扱い

2000年10月9日
at
PostgreSQLでラージオブジェクトを利用する際のメモです。まだ書きかけです。内容については保証できません。詳細内容は参考文献を参照してください。

ラージオブジェクトの使用方法

コマンドライン(psql)よりラージオブジェクトを作成する

postgresqlに付属のドキュメントより

Can not access : import.console

プログラム(libpq)よりラージオブジェクトを作成する

postgresqlに付属のドキュメントより

Oid
importFile(
	PGconn *conn,	// (I/ ):postgresql 接続子
	char *filename,	// (I/ ):読込み対象ファイル
	char *errTxt	// ( /O):エラー時の内容が格納される。
)
{
	Oid lobjId;
	int lobj_fd;
	char buf[BUFSIZE];
	int nbytes, tmp;
	FILE *fd;

	/*
	 * open the file to be read in
	 */
	// オープン:バイナリ読込
	fd = fopen(filename,"rb");
	if (fd == NULL)  {   /* error */
		sprintf(errTxt," importFile[can't open file] ");
		return(0);
	}

	// 読書可能で作成:ラージオブジェクト
	lobjId = lo_creat(conn, INV_READ|INV_WRITE);
	if (lobjId == 0) {
		sprintf(errTxt," importFile[can't create large object] ");
		return(0);
	}

	// 指定したファイルより読込
	// 作成したラージオブジェクトへ書込
	lobj_fd = lo_open(conn, lobjId, INV_WRITE);
	while ((nbytes = fread(buf,1,BUFSIZE, fd)) > 0) {
		tmp = lo_write(conn, lobj_fd, buf, nbytes);
		if (tmp < nbytes) {
			sprintf(errTxt," importFile[error while reading] ");
		}
	}

	// クローズ:ファイル
	(void) fclose(fd);
	// クローズ:ラージオブジェクト
	(void) lo_close(conn, lobj_fd);

	return lobjId;
}

ラージオブジェクトの回収、バックアップ、リストア

回収:vacuumloを使用する

vacuumを実行しても、既に使用していないラージオブジェクトでも削除されません。

削除する場合、un_link関数を使用して削除するか、ラージオブジェクト自身がテーブルなのでDrop Tableという手もありますが、消していくためのプログラムが必要になってきます。

簡単にラージオブジェクトを削除方法として、contribにvacuumloというプログラムがあります。

注意点は、削除したくない、ラージオブジェクトのOidを同じDB内のテーブルに確保しておく必要があります。確保していない場合、全てのラージオブジェクトが削除されます。

バックアップ:保存ルールを決める

保存ルールで決めることは、下記2つです。

リストア:バックアップ保存ルールよりリストアする

リストア動作としては、

PostgreSQL についてよくある質問(FAQ) からラージオブジェクト関係を抜粋

PostgreSQL についてよくある質問(FAQ)から抜粋です。

OID とは何ですか? TID とは何ですか?

4.17) OID とは何ですか? TID とは何ですか?

OID とは一意の行 ID に対する PostgreSQL の答えです。PostgreSQL の中でつくられるすべての行は一意の OID を得ます。initdb で(backend/access/transam.h から)発生される OID はすべて 16384より小さな値です。initdb 後のすべての OID (ユーザ作成)はそれ以上の値になります。既定では、これらすべての OID はテーブル内やデータベース内に留まらず、PostgreSQL のそのインストレーション全体内で一意であります。 PostgreSQL はテーブル間の行を結びつけるために、そのシステムテーブル内に OID を使います。この OID は特定のユーザの行を識別するためや結合の中で使われることができます。OID の値を保存するためには OID 型を列に使うことを奨めます。より速くアクセスするために OID フィールドに索引を作ることができます。 OID は、全てのデータベースから使われる中央領域から、全ての新しい行に割り当てられます。OID を他の何かに変えたい、もしくは元の OID でテーブルをコピーしたいのなら、そうできない理由はありません。

        CREATE TABLE new_table(old_oid oid, mycol int);
        SELECT old_oid, mycol INTO new FROM old;
        COPY new TO '/tmp/pgtable';
        DELETE FROM new;
        COPY new WITH OIDS FROM '/tmp/pgtable';

OID は、4バイトの整数として保存されているので、40億を越えると溢れてしまうでしょう。誰もこれが起きたと報告してくる人はいませんでしたが、そうなる前にこの制限を取り除くことを計画しています。 TID は特定の物理行をそのブロックとオフセット値で識別するために使われます。TID は行が修正されたり再ロードされると変わります。それらの TID は、物理行を指すために索引記載で使われます。

ラージ・オブジェクトの操作でinvalid large obj descriptor を受け取りました。なぜでしょうか?

ラージ・オブジェクトの操作でinvalid large obj descriptor を受け取りました。なぜでしょうか?

ラージ・オブジェクト操作をするときは、前後にBEGIN WORKとCOMMITを付ける必要があります。すなわち、lo_open ... lo_closeをはさみ込みます。 現在は、PostgreSQLのトランザクションのコミット時にラージ・オブジェクト・ハンドルを閉じることにより、lo_openコマンドが完了した直後に強制的にルールを実行します。このため、最初にハンドルに対して何かをしようとすると、invalid large obj descriptor(巨大オブジェクトの記述子が不正)となります。それで、もし、トランザクションを使うのを忘れると、(少なくともほとんどの時間)働いていたコードがエラーメッセージを出すのです。 もし、ODBCのようなクライアントインターフェースをお使いなら、auto-commit offを設定する必要があるかもしれません。