このすみノート

Webエンジニアが技術や趣味を書くブログです。

続・PHPのpg_queryは、複数のSQLをひとつのトランザクションにまとめて実行する

PHPには、pg_queryという関数があります。 その名の通り、PostgreSQLでクエリーを実行する関数です。

気になっている記述は以下で、複数のSQL文をひとつのトランザクションにまとめて実行すると書いてあります。

query
実行する 1 つまたは複数の SQL 文。複数の文が関数に渡された場合は、 明示的に BEGIN/COMMIT コマンドを指定していない限りはそれらの文は ひとつのトランザクションとして実行されます。 しかし、1 回のコールで 複数のトランザクションを実行することは推奨されません。 https://www.php.net/manual/ja/function.pg-query.php

複数のSQLがひとつのトランザクションになるとは

PHPのpg_queryに、複数のSQL文が入ったクエリー文字列を渡します。

UPDATE a SET b = c WHERE id = 1;
UPDATE d SET e = f WHERE id = 2;
UPDATE g SET h = i WHERE id = 3;

このときpg_queryが、自動で一つのトランザクションにとりまとめて、SQLを実行するのではないかという話です。

BEGIN;
UPDATE a SET b = c WHERE id = 1;
UPDATE d SET e = f WHERE id = 2;
UPDATE g SET h = i WHERE id = 3;
COMMIT;

実際にどうだったのか

自動で一つのトランザクションにまとめるのか半信半疑だったのですが、どうやら本当にそうみたいです。

とあるプロジェクトでデッドロックが散見されていたのですが、複数SQLを一度にpg_queryへ渡している処理をリファクタリングしたら、デッドロックが起きなくなりました。

あとがき

前回の記事でも書きましたが、そもそもpg_queryに複数SQLを渡すなと言われればその通りであり、本件のトラブルに遭遇する人は意外と少ないのかもしれません。