Добавляет ли столбец "null" в таблицу postgres, вызывает блокировку?

Я думаю, что где-то читал, что запуск ALTER TABLE foo ADD COLUMN baz text в базе данных postgres не приведет к блокировке чтения или записи. Установка значения по умолчанию вызывает блокировку, но разрешение нулевого значения по умолчанию предотвращает блокировку.

Я не могу найти это в документации. Может ли кто-нибудь указать на место, которое говорит, окончательно, если это правда или нет?

Ответ 1

Различные типы блокировок и когда они используются, упоминаются в документе в Блокировки на уровне таблиц. О ALTER TABLE, он говорит только, что он может получить блокировку SHARE UPDATE EXCLUSIVE или ACCESS EXCLUSIVE.

Но на самом деле, текущие версии postgres используют Access Exclusive Locks для всех вариантов этой команды, поэтому не так, что одновременные чтения могут происходить одновременно в определенных случаях.

Легко проверить исходный код, потому что в разных случаях существует функция, предназначенная для установления уровня блокировки, необходимого для этой команды. См. Комментарии в src/backend/commands/tablecmds.c:

/*
 * AlterTableGetLockLevel
 *
 * Sets the overall lock level required for the supplied list of subcommands.
 * Policy for doing this set according to needs of AlterTable(), see
 * comments there for overall explanation.
 *
 * Function is called before and after parsing, so it must give same
 * answer each time it is called. Some subcommands are transformed
 * into other subcommand types, so the transform must never be made to a
 * lower lock level than previously assigned. All transforms are noted below.
 *
 * Since this is called before we lock the table we cannot use table metadata
 * to influence the type of lock we acquire.
 *
 * There should be no lockmodes hardcoded into the subcommand functions. All
 * lockmode decisions for ALTER TABLE are made here only. The one exception is
 * ALTER TABLE RENAME which is treated as a different statement type T_RenameStmt
 * and does not travel through this section of code and cannot be combined with
 * any of the subcommands given here.
 */

LOCKMODE
AlterTableGetLockLevel(List *cmds)
{
    /*
     * Late in 9.1 dev cycle a number of issues were uncovered with access to
     * catalog relations, leading to the decision to re-enforce all DDL at
     * AccessExclusiveLock level by default.

Функция имеет некоторую логику, чтобы принимать более слабые блокировки, но она отключена в текущей форме, чтобы возвращать AccessExclusiveLock во всех случаях.

Ответ 2

Добавление нового столбца null заблокирует таблицу в течение очень короткого времени, так как нет необходимости переписывать все данные на диске. Добавляя столбец со значением по умолчанию, PostgreSQL должен создавать новые версии всех строк и хранить их на диске. И за это время таблица будет заблокирована.

Поэтому, когда вам нужно добавить столбец со значением по умолчанию в большую таблицу, рекомендуется сначала добавить нулевое значение, а затем обновить все строки небольшими порциями. Таким образом, вы избегаете высокой нагрузки на диск и позволяете autovacuum выполнять эту работу, чтобы вы не удвоили размер таблицы.

Ответ 3

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

"Добавление столбца с ненулевым значением по умолчанию или изменение типа существующего столбца потребует перезаписи всей таблицы и индексов."

Таким образом, документация указывает только, когда таблица не переписана. Всегда будет блокировка, но она будет очень коротка, если таблица не будет перезаписана.