web-dev-qa-db-ja.com

postgresテーブルにnull列を追加するとロックが発生しますか?

私はどこかでALTER TABLE foo ADD COLUMN baz text postgresデータベースでは、読み取りまたは書き込みロックは発生しません。デフォルト値を設定するとロックが発生しますが、デフォルト値をnullにするとロックできなくなります。

ただし、ドキュメントではこれを見つけることができません。これが真実であるかどうかにかかわらず、誰かが決定的に言っている場所を指すことができますか?

28
jpadvo

さまざまな種類のロックとそれらが使用されるタイミングについては、ドキュメントの Table-level Locks で説明しています。たとえば、Postgres 11のALTER TABLEは、SHARE UPDATE EXCLUSIVESHARE ROW EXCLUSIVE、またはACCESS EXCLUSIVEロックを取得できます。

Postgres 9.1〜9.3は、上記の3つのうち2つをサポートすると主張していますが、実際には このコマンドのすべてのバリアントに対してAccess Exclusiveを強制 です。この制限は Postgres 9.4で解除 でしたが、ADD COLUMNACCESS EXCLUSIVEのままです。

さまざまなケースでこのコマンドに必要なロックレベルの確立専用の関数があるため、ソースコードをチェックインするのは簡単です:AlterTableGetLockLevel in src/backend/commands/tablecmds.c


ロックが保持される時間について、取得後:

  • 列のデフォルト値がNULLの場合、テーブルの書き換えが必要ないため、列の追加は非常に高速になります。これは、カタログ内の更新のみです。
  • 列にNULL以外のデフォルト値がある場合、それはPostgreSQLのバージョンに依存します。バージョン11以降では、すべての行がすぐに書き換えられることはないため、NULLの場合と同じくらい高速でなければなりません。ただし、バージョン10以前では、テーブルが完全に書き換えられるため、テーブルのサイズによっては非常に高価になる場合があります。
23
Daniel Vérité

新しいnull列を追加すると、ディスク上のすべてのデータを再書き込みする必要がないため、テーブルが非常に短時間ロックされます。デフォルト値で列を追加する場合、PostgreSQLはすべての行の新しいバージョンを作成し、それらをディスクに格納する必要があります。その間、テーブルはロックされます。

したがって、デフォルト値の列を大きなテーブルに追加する必要がある場合は、最初にnull値を追加してから、すべての行を少しずつ更新することをお勧めします。これにより、ディスクへの高負荷を回避し、autovacuumがそれを実行できるようになるため、テーブルサイズが2倍になることはありません。

23
alexius

http://www.postgresql.org/docs/current/static/sql-altertable.html#AEN5729

「デフォルトがnullではない列を追加するか、既存の列のタイプを変更するには、テーブル全体とインデックスを書き換える必要があります。」

したがって、ドキュメントでは、テーブルが書き換えられない場合のみを指定しています。ロックは常に存在しますが、テーブルを書き換えない場合は非常に短くなります。

12
Leo