DBD::SQLite 1.38_01

細かいことについてはYAPC::Asiaの発表が済んでからまたあらためて記事を書くつもりでいますが、多くの方に関係のありそうな部分だけ先に書いておきます。

デフォルトのトランザクションモードをdeferredからimmediateにしました

DBD::SQLite 1.30_02以降、sqlite_use_immediate_transactionというアトリビュートを使えばトランザクションのモードを(デフォルトの)deferredからimmediateに変更できるようにしてありましたが、今回このimmediateの方の挙動をデフォルトとしました。deferredの挙動が必要な方は明示的にsqlite_use_immediate_transactionアトリビュートをfalseにしてください。

といってもわかりづらいと思うのでもう少し平易に言い換えると、今回の変更で(おもに書き込み用の)トランザクションを開始するべく$dbh->begin_workを発行したら、きちんとそのタイミングで最初のクエリを発行した時点でデータベースが書き込み用のロックを準備するようになります(SQLite標準のdeferredトランザクションでは読み込みの並列性を高めるため、実際に更新が必要なクエリを発行するまで書き込みロックを取得しません)。

そのため、deferredトランザクションを前提としてものすごく大きなブロック単位でトランザクションを行っているようなアプリケーションの場合、必要以上のロックが発生して並列読み込みの性能に問題が生じるおそれがあります。

DBD::SQLiteの用途を考えると、一般的にはロックのタイミングが直感的にもわかりやすくなるメリットや、早い段階で書き込み用のロックを取得するため、(複数のクライアントが読み込みロックを持ったままほぼ同時に書き込みロックを取得しようとして生じる)デッドロックの問題が生じなくなるメリットの方が大きいと判断した結果ですが、組み込み系などで素のSQLiteを使っている方はまた異なる意見を持たれることもあろうかと思います。ご意見ありましたらYAPCの際にでもお知らせいただければ幸いです。

バインドパラメータの扱いについて

詳細は省略しますが、最近のperlでこんな感じのコードが正しく動いていなかった件が修正されました。

my $sth = $dbh->prepare("UPDATE test SET a = ?, b = ? WHERE id = ?");
my @values = ("hello","world",5);
for (my $i=0;$i<3;$i++) {
  # $sth->bind_param($i+1, $values[$i]); # work as expected
  $sth->bind_param($i+1, "$values[$i]"); # this not work!!
}
$sth->execute();

https://rt.cpan.org/Ticket/Display.html?id=79576

その他

ほかにも情報取得系のメソッドをいくつか追加・修正したほか、JAMADAMさんのパッチのおかげで、sqlite_unicodeアトリビュートが真で、カラム名UTF-8を使っている場合、カラム名も「文字列」としてデコードされるように修正されています。

YAPC::Asiaでのセッションについて

せっかくDBIの作者とDBD::SQLiteチームが一堂に会するのですから、私自身もどこかで時間を見つけてDBI側の仕様とずれているところのすりあわせをしたり、実装上の問題について助言を求めようと思っていますが、ここをご覧のみなさんのなかで、もし特にDBIやDBD::SQLiteにまつわる話題でTim Bunce氏やAdam Kennedy氏に聞いてみたいことがある方がいるようでしたら、YAPCのセッション中でも、その後の懇親会やら何やらの席ででも、可能な範囲でお手伝いしますのでお声をおかけくださいまし。

あと、今年は時間の都合などもあって海外勢のスライドの日本語訳はいっさい行っていません(ktatさんなどほかの翻訳好きな方々がどうされたかまでは承知していません)。あしからずご了承ください。