2006年9月30日土曜日

MT3.3でBerkeley DBからPostgreSQLへの移行する際の注意点

MTのエントリが多くなりすぎて、再構築ができなくなったと友達から連絡をもらい、確認したところ、DBにBerkeleyDBを使っていたので、それを改善すべくDBをBerkeleyDBからPostgreSQLに移行してみました。
その際、MTのマニュアルにしたがってやってみたところ、そのままではうまくいかなかったので、行った作業をメモ的に残しておきます。

* PostgreSQLの設定

まず、マニュアルをみてPostgreSQLの設定をしました。

基本マニュアルどおりに進めて、mt-config.cgiの設定を変更し、
データベースの作成をおこないました。
DBの文字コードはUTF-8だったので、DB作成の際、文字コードを指定しました。
>

createdb -E UNICODE --owner xxxxx
<

* 移行スクリプトを実行

次にマニュアルどおりMT付属の移行スクリプトを実行したところ、DBの文字コードと違う文字コードのデータを入れようとした旨のエラーメッセージが出て、移行スクリプトを完了できませんでした。
文字コードの違うデータというのは、トラックバックPingのデータで、トラックバック元のブログの文字コードがUTF-8ではないものがエラーではじかれているようでした。
これは、文字コードが違うPingを探し出して削除するのは面倒くさかったので、移行スクリプトのほうを修正して、インサートに失敗しても処理を続行するようにして、回避しました。
修正点は以下のとおり。saveに失敗してもdieしないようにしただけです。MTの方で、DBへのアクセスが高度に抽象化されているので、修正は非常に簡単です。
>

--- ./mt-db2sql.cgi.org Sat Sep 30 00:54:15 2006
+++ ./mt-db2sql.cgi Sat Sep 9 20:09:45 2006
@@ -141,8 +141,8 @@
$obj->allow_comments(0)
if defined $obj->allow_comments && $obj->allow_comments eq '';
}
- $obj->save
- or die $obj->errstr;
+ $obj->save;
+ # or die $obj->errstr;
}

# fix up the category parents
<

この修正版のスクリプトを再度実行したところ、今度は問題なく、データの移行が完了しました。

* シーケンスの作成、更新

これで万事OKかと思ったんですが、この状態でエントリを作成しようとすると、以下のようなエラーがでて、作成できなくなってしまいました。

>

Saving entry failed: ERROR: ExecInsert: Fail to add null value in not null attribute entry_id
<

このエラーでググッてみると、どうやらDB内にシーケンスがないためのようです。
先ほどの移行用スクリプトだと、テーブルは作成されてもシーケンスは作成してくれないみたいです。
そうとわかれば、後はシーケンスを手動で作成するだけです。
以下のSQLを実行し、シーケンスを作成し、格納されている値を現在の最大値にセットしたところ、問題なく動くようになりました。

>

CREATE SEQUENCE mt_author_id;
CREATE SEQUENCE mt_blog_id;
CREATE SEQUENCE mt_category_id;
CREATE SEQUENCE mt_comment_id;
CREATE SEQUENCE mt_config_id;
CREATE SEQUENCE mt_entry_id;
CREATE SEQUENCE mt_fileinfo_id;
CREATE SEQUENCE mt_ipbanlist_id;
CREATE SEQUENCE mt_log_id;
CREATE SEQUENCE mt_notification_id;
CREATE SEQUENCE mt_objecttag_id;
CREATE SEQUENCE mt_permission_id;
CREATE SEQUENCE mt_placement_id;
CREATE SEQUENCE mt_plugindata_id;
CREATE SEQUENCE mt_tag_id;
CREATE SEQUENCE mt_tbping_id;
CREATE SEQUENCE mt_template_id;
CREATE SEQUENCE mt_templatemap_id;
CREATE SEQUENCE mt_trackback_id;

select setval('mt_author_id',(select max(author_id) from mt_author));
select setval('mt_blog_id',(select max(blog_id) from mt_blog));
select setval('mt_category_id',(select max(category_id) from mt_category));
select setval('mt_comment_id',(select max(comment_id) from mt_comment));
select setval('mt_config_id',(select max(config_id) from mt_config));
select setval('mt_entry_id',(select max(entry_id) from mt_entry));
select setval('mt_fileinfo_id',(select max(fileinfo_id) from mt_fileinfo));
select setval('mt_ipbanlist_id',(select max(ipbanlist_id) from mt_ipbanlist));
select setval('mt_log_id',(select max(log_id) from mt_log));
select setval('mt_notification_id',(select max(notification_id) from mt_notification));
select setval('mt_objecttag_id',(select max(objecttag_id) from mt_objecttag));
select setval('mt_permission_id',(select max(permission_id) from mt_permission));
select setval('mt_placement_id',(select max(placement_id) from mt_placement));
select setval('mt_plugindata_id',(select max(plugindata_id) from mt_plugindata));
select setval('mt_tag_id',(select max(tag_id) from mt_tag));
select setval('mt_tbping_id',(select max(tbping_id) from mt_tbping));
select setval('mt_template_id',(select max(template_id) from mt_template));
select setval('mt_templatemap_id',(select max(templatemap_id) from mt_templatemap));
select setval('mt_trackback_id',(select max(trackback_id) from mt_trackback));
<

以上BerkeleyDBからPostgreSQLへの移行の際の注意点をまとめると、

- 文字コードの問題でエラーがでるため、移行スクリプトを修正して、エラーを無視するようにする。
- シーケンスは作成されないので手動で作成する。

の2つを注意しないといけないようです。

4 件のコメント:

  1. DB移行ありがとう!!!!

    返信削除
  2. はじめまして。
    MovableTypeを使っているもので、DBはPostgreSQLを使用しています。
    先日管理画面からプラグイン関係の「変更を保存」を押したら、
    SQLエラーが発生しました: ERROR: null value in column "plugindata_id" violates not-null constraint
    というエラーが出ました。その後、コマンドラインから以下のように実行すると
    => select nextval('mt_plugindata_id');
    ERROR: relation "mt_plugindata_id" does not exist
    という結果が返ってきました。こちらの記事にあるようにシーケンスがつくられていないか失われたかが原因なのでしょうか。
    まだDBのことがよく分かっていないので、よかったら教えてください。

    返信削除
  3. 同じ問題に行き当たり、上記SQL文で解決しました。ありがとう!

    返信削除
  4. はじめまして。同様のエラーが発生していましたが、上記の SQL で解決できました。本当にありがとうございます。

    返信削除