Что такое код pg_update


Содержание

FPublisher

Web-технологии: База знаний

Документация PHP

pg_update

(PHP 4 >= 4.3.0, PHP 5)

pg_update — Update table

Описание

mixed pg_update ( resource $connection , string $table_name , array $data , array $condition [, int $options ] )

pg_update() updates records that matches condition with data. If options is specified, pg_convert() is applied to data with specified options.

Эта функция является ЭКСПЕРИМЕНТАЛЬНОЙ. Поведение этой функции, ее имя и относящаяся к ней документация могут измениться в последующих версиях PHP без уведомления. Используйте эту функцию на свой страх и риск.

Список параметров

PostgreSQL database connection resource.

Name of the table into which to update rows.

An array whose keys are field names in the table table_name , and whose values are what matched rows are to be updated to.

An array whose keys are field names in the table table_name , and whose values are the conditions that a row must meet to be updated.

Any number of PGSQL_CONV_OPTS, PGSQL_DML_NO_CONV, PGSQL_DML_EXEC or PGSQL_DML_STRING combined. If PGSQL_DML_STRING is part of the options then query string is returned.

Возвращаемые значения

Возвращает TRUE в случае успешного завершения или FALSE в случае возникновения ошибки. Returns string if PGSQL_DML_STRING is passed via options .

Примеры

Пример #1 pg_update() example

= pg_connect ( ‘dbname=foo’ );
$data = array( ‘field1’ => ‘AA’ , ‘field2’ => ‘BB’ );

// This is safe, since $_POST is converted automatically
$res = pg_update ( $db , ‘post_log’ , $_POST , $data );
if ( $res ) <
echo «Data is updated: $res\n» ;
> else <
echo «User must have sent wrong inputs\n» ;
>
?>

Что такое код pg_update

(только PHP 4 CVS)

pg_update — обновляет таблицу.

Описание

long pg_update (resource connection, string table_name, array condition, array data [, int options])

pg_update() обновляет записи, соответствующие условию condition , данными data . Если options спепцифицирован, pg_convert() приемняется к assoc_array со специфицированными опциями.

Пример 1. pg_update

‘AA’, ‘field2’=>’BB’); // Это безопасно, поскольку $_POST конвертируется автоматически $res = pg_update($db, ‘post_log’, $_POST, $data); if ($res) < echo "Data is updated: $res\n"; >else < echo "User must have sent wrong inputs\n"; >?>

Примечание: эта функция является экспериментальной.

Обновление PostgreSQL 9.5 > 9.6

В данном примере будем обновлять версию Postgres 9.5 до 9.6 в Centos.
Не забываем заглядывать в документацию по продукту на сайте postgresql.org
Данное руководство может быть применено и для других версий Postgres 9.x / RHEL

Перед началом любых работ, убедитесь, что имеете актуальные резервные копии данных с которыми собираетесь работать. Это могут быть файлы конфигурации /var/lib/pgsql/9.5/data/postgresql.conf, /var/lib/pgsql/9.5/data/pg_hba.conf, а также сама база данных.


Для начала нам нужно установить PostgreSQL 9.6 или версию на которую мы собираемся произвести обновление/upgrade.

Вы можете установить несколько версий PostgreSQL на одной операционной системе. Процесс установки хорошо описан на официальном сайте postgresql.org, там-же вы можете найти репозиторий для установки на ваш дистрибутив.

Репозиторий CentOS по-умолчанию содержит пакеты Postgres, поэтому можно установить его с помощью пакетного менеджера YUM.

После установки PostgreSQL версии 9.6 в вашей системе появиться новый каталог , в нашем случае это /var/lib/pgsql/9.6 Так-же у нас останеться каталог с предыдущей версией Postgresql /var/lib/pgsql/9.5

Для проверки возможности обновления используйте pg_upgrade. Ключ —check позволит произвести проверку без изменения существующих данных.

По-умолчанию работа с PostgreSQL ведется от пользователя postgres, не запускайте pg_upgrade под пользователем root. Сначала перейдите в сессию юзера postgres.

В результате проверки / check. Вы увидите сообщение: Clusters are compatible, если получаем ошибку вида: Performing Consistency Checks on Old Live Server — это может означать, что сервер postgresql не был до конца остановлен, необходимо проверить статус сервиса при помощи команд ps или service из под пользователя (!) root.

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

Процесс обновления (pg_upgrade) не займет много времени (в зависимости от размеров базы данных и отзывчивости диска). В среднем это 5 минут для базы данных объемом 50 Гб и хороших показателя производительности.

Теперь нам нужно перенести файлы конфигураций нашей старой версии на новую.
Достаточно просто скопировать файл.

Если в ваших конфигурационных файлах используются пути до старой версии (в нашем случае это 9.5), то их необходимо исправить. Для быстрой замены можно воспользоваться инструментом SED.

После исправления конфигурации, запускаем сервис postgresql-9.6 и отключаем старую версию из автозапуска.

Убедитесь в том, что база данных работает, а данные в ней актуальные. Если все в порядке, вы можете удалить старую версию пакета и данные из директории с предыдущей версией.

pg_update

(только PHP 4 CVS)

pg_update — обновляет таблицу.

Описание

long pg_update (resource connection, string table_name, array condition, array data [, int options])

pg_update() обновляет записи, соответствующие условию condition, данными data. Если options специфицирован, pg_convert() применяется к assoc_array со специфицированными опциями.

Пример 1. pg_update

Примечание: эта функция является экспериментальной.

Updater: что это за программа в общем смысле?

В современном компьютерном мире ни дня не обходится без программ, названия которых в общем обозначаются как Updater. Что это такое, большинство пользователей представляет себе достаточно четко. А вот для начинающих юзеров, работающих в автоматическом или ручном режиме, нужно дать отдельное пояснение. Начнем с самого главного – рассмотрения вопроса, связанного с тем, что это за апплеты, зачем они нужны.

Программы типа Updater: что это такое?

На самом деле, вникнуть в суть термина не так уж и сложно. Для этого достаточно просто перевести с английского языка это слово.

Update означает «обновление». Соответственно, термин Updater есть не что иное, как какой-то инструмент установки обновлений. Но каких именно? Тут следует различать несколько кардинальных решений, поскольку в плане установки апдейтов, приложения можно разделить на несколько категорий:

  • средства обновления операционных систем;
  • программы для обновления драйверов;
  • апплеты для обновления приложений.

Driver Updater

Что касается обновления драйверов, то собственных автоматизированных средств в системах Windows не предусмотрено.

Единственный инструмент – «Диспетчер устройств». В нем придется выбирать строку поиска и установки обновлений через меню ПКМ или через вкладку драйвера. Однако не факт, что Updater Windows произведет поиск именно того драйвера, который требуется для корректной работы выбранного устройства из собственной базы данных.

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

Но и это не всегда дает ожидаемый эффект. Тут проблема в том, что для нестандартных устройств в установочном файле драйвера (EXE или INF) может отсутствовать так называемая цифровая подпись или сертификат, подтверждающий легитимность (легальность) устанавливаемого ПО. Поэтому апдейтер такие обращения будет игнорировать.


И что делать? Выход прост. В «Диспетчере устройств» через свойства выбранного объекта необходимо перейти к вкладке сведений, в выпадающем списке установить показ ИД оборудования. В специальном поле ниже будет отображено несколько строк, в которых содержатся идентификаторы VEN и DEV. Первый соответствует коду производителя (Vendor), второй – типу устройства (Device). Но наиболее полную информацию об устройстве содержит самая длинная строка. Ее нужно просто скопировать, перейти на сайт производителя, если устройство определяется, или на ресурс, содержащий базы данных драйверов. После задать поиск по исходному коду. Такой вариант приемлем и в том случае, если устройство в системе помечается как неизвестное.

Обновление Windows

Теперь несколько слов о средстве обновления Windows, которое условно тоже можно характеризовать как Updater. Что это такое применительно к операционной системе?

Это всем известный «Центр обновления», активация которого установлена по умолчанию. Если по каким-то причинам пользователь автоматический апдейт отключил, задать поиск доступных пакетов всегда можно вручную, используя для этого соответствующую кнопку или ссылку. Найденные пакеты можно установить, исключив из списка те, которые не нужны (например, пакеты обновлений для офисных продуктов Microsoft). Но вот критически важные апдейты игнорировать не стоит, поскольку они содержат инструменты исправления багов в системе безопасности, обновления для сборок самих ОС и необходимых для их корректной работы платформ, вроде DirectX, .NET Framework, MS Visual C++ и других.

Автоматизированные апдейтеры других программ

Апдейтеры могут представлять собой и отдельно взятые клиенты, которые инсталлируются вместе с программами и постоянно находятся в автозагрузке системы, следя за выходом новых версий соответствующего ПО.

Илон Маск рекомендует:  Что такое код dbplus_undo

Самый простой пример – появление напоминания о необходимости установки свежей версии расширения Flash Player. Точно такой же пример может быть связан с установленными антивирусами, которые своевременно сигнализируют об установке новейших баз сигнатур вирусов или обновлений, связанных с компонентами самих программ. Таких примеров можно встретить много. Любые современные программы имеют собственные средства по слежению за обновлениями, правда, только при условии постоянного наличия подключения к Интернету.

Проблемы с обновлением и пути их решения

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

Если пользователь получает сообщение со строкой Update Failed, это означает только то, что найденное обновление не смогло установиться правильно. Рассматривать все причины не стоит, поскольку это может занять длительное время. Вполне возможно, что при установке неофициальной взломанной версии программы адрес ее официального ресурса, на котором производится проверка подлинности, был внесен в список запретов файла hosts. Проверьте его настройки. Редко, но можно встретить проблемы, связанные с тем, что использование программы в определенном регионе запрещено или блокируется. В этом случае включите VPN-клиент и попробуйте произвести апдейт заново. Конечно, это не все, что может быть, но принимать решение необходимо в каждом конкретном случае, исходя из кода ошибки.

Напоследок обратите внимание на то, что здесь были затронуты вопросы исключительно официальных инструментов и средств, а вирусы с одноименными названиями не рассматривались в принципе.

Обновление postgre с версии 9.2 на 10

Пытаюсь сделать upgrade постгри с версии 9.2 на 10ую (система win7) через консоль утилитой pg_upgrade.

Но столкнулся с такой проблемой, во время переноса на новую версию, почему то вылезает ошибка, мол нет соединения с базой,
проверяю и вижу что служба postgre 10 остановленна, пытаюсь запустить — ошибка запуска, в логе пишется следующая информация:

2020-04-12 10:13:29.614 MSK [1560] СООБЩЕНИЕ: система БД была выключена в процессе восстановления: 2020-04-12 10:10:58 MSK
2020-04-12 10:13:29.614 MSK [1560] СООБЩЕНИЕ: неверная длина записи по смещению 0/163FC70: ожидалось 24, получено 0
2020-04-12 10:13:29.614 MSK [1560] СООБЩЕНИЕ: неверная запись первичной контрольной точки
2020-04-12 10:13:29.614 MSK [1560] СООБЩЕНИЕ: неверный ID менеджера ресурсов в записи вторичной контрольной точки
2020-04-12 10:13:29.614 MSK [1560] ПАНИКА: не удалось считать правильную запись контрольной точки
2020-04-12 10:13:29.614 MSK [2328] СООБЩЕНИЕ: выключение при достижении цели восстановления
2020-04-12 10:13:29.629 MSK [3684] СООБЩЕНИЕ: выключение
2020-04-12 10:13:29.629 MSK [2328] СООБЩЕНИЕ: система БД выключена

гугл полезной информации мне не дал, но есть такое предположение, что бинарная совместимость отсутствует между 9Х и 10Х версиями.

Возможно есть предположения по этой теме, буду признателен если поможете дельным советом

p.s сильно не критикуйте если вопрос глуп и очевиден, заранее благодарен)

12.04.2020, 14:03

Обновление версии php
Добрый день. Помогите пожалуйста в следующем вопросе. Для установки фреймворка Symfony нужна.

Версии VBScript и их обновление
Добрый день! Насколько я понимаю разные программы поддерживают разные VBScript. Например IE 6.0 -.

Обновление версии php
Добрый день! Прошу помочь в следующем вопросе. Недавно начал осваивать Линукс, поэтому есть.

Mediawiki, обновление до версии 1.24.1
Помогите пожалуйста. Обновил mediawiki с версии 1.21.3 до 1.24.1. После этого страницы пустые.

Обновление версии PHP
Ребят, подскажите, пожалуйста, как обновиться и что для этого надо? Спасибо.

Как пользоваться командой gpupdate?

Команда gpupdate является заменой команды secedit /refreshpolicy, которая использовалась в операционной системе Windows 2000 для ручного запуска процесса обновления объектов групповой политики.

Хотя все политики обновляются автоматически, использование этой команды позволяет выполнить немедленное обновление объекта групповой политики. Часто это оказывается необходимо после внесения изменений в объект групповой политики.

Таким образом, можно убедиться в правильности изменений в объекте групповой политики. В отличие от команды secedit /refreshpolicy команда gpupdate по умолчанию выполняет обновление параметров политики пользователя и политики компьютера. При использовании утилиты secedit приходилось запускать две отдельные команды.

Команда gpupdate имеет следующий синтаксис:

Параметры команды gpupdate рассматриваются в следующей таблице.

Параметры команды gpupdate

Заставляет команду выполнять обновление только параметров компьютера или только параметров пользователя в объекте групповой политики. По умолчанию обновляются параметры компьютера и пользователя

Игнорирует все оптимизации обработки объектов групповой политики, например, обнаружение медленных связей, и повторно применяет все параметры


Позволяет указать количество секунд, за которое должна завершиться обработка политики. По умолчанию используется значение 600 (10 минут). Значение означает отсутствие ожидания, а значение -1 означает неограниченное ожидание

Завершает сеанс работы пользователя после применения параметров объекта групповой политики. Завершение сеанса работы пользователя требуется для обновления многих параметров политики, например, параметров рабочего стола, поэтому процесс завершения сеанса стоит автоматизировать

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

Приводит к синхронному применению параметров объекта групповой политики к компьютерам в процессе загрузки и к пользователям в процессе регистрации. Такое поведение по умолчанию принято в операционной системе Windows 2000. Это приводит к применению всех политик в процессе регистрации. В операционных системах Windows XP и Windows Server 2003 политики, принятые по умолчанию, применяются асинхронно. При этом некоторые пользователи будут регистрироваться на основании кэшированных данных и не получат обновленные параметры групповой политики

Предположим, что в параметры политики пользователя были внесены изменения.

Для проверки изменений можно запустить команду gpupdate /target:user /logoff. Эта команда выполняет обновление пользовательской части объекта групповой политики и автоматически завершает сеанс работы пользователя после окончания обновления. Как только пользователь зарегистрируется в системе повторно, он заметит внесенные изменения.

Вы можете задать вопрос по статье специалисту.

Как откатить UPDATE в PostgreSQL через pg_xlog?

Вчера с одной из моих баз приключилась печалька — в таблицу «payments» попал запрос

Обратите внимание на точку с запятой посредине — все данные стали равны нулю водночасье.

По неудачному стечению обстоятельств бэкапов нет.

Погуглив на эту тему я нашел что есть небольшой шанс восстановить данные из файлов, находящихся в директории pg_xlog. Обратите внимание, PITR я не использую. Заглянув в эту папку я нашел там файлик с датой изменения равной дате факапа размером аж 16 мегабайт. Внутри он бинарный.

После этого я нагуглил, что эти файлики можно поглядеть через xlogdump. Он мне показал что-то типа такого:

[cur:0/5770E87C, xid:355075, rmid:10(Heap), len:88/116, prev:0/5770E840] update: s/d/r:1663/90693/107093 block 1 off 36 to block 107 off 30
[cur:0/5770E8F0, xid:355075, rmid:11(Btree), len:34/62, prev:0/5770E87C] insert_leaf: s/d/r:1663/90693/107099 tid 20/101
[cur:0/5770E930, xid:355075, rmid:11(Btree), len:38/66, prev:0/5770E8F0] insert_leaf: s/d/r:1663/90693/107100 tid 42/146
[cur:0/5770E974, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770E930] insert_leaf: s/d/r:1663/90693/107101 tid 21/97
[cur:0/5770E9B0, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770E974] insert_leaf: s/d/r:1663/90693/107102 tid 28/7
[cur:0/5770E9EC, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770E9B0] insert_leaf: s/d/r:1663/90693/107103 tid 33/2
[cur:0/5770EA28, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770E9EC] insert_leaf: s/d/r:1663/90693/107104 tid 18/232
[cur:0/5770EA64, xid:355075, rmid:11(Btree), len:54/82, prev:0/5770EA28] insert_leaf: s/d/r:1663/90693/107105 tid 46/109
[cur:0/5770EAB8, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EA64] insert_leaf: s/d/r:1663/90693/107106 tid 17/99
[cur:0/5770EAF4, xid:355075, rmid:10(Heap), len:84/112, prev:0/5770EAB8] update: s/d/r:1663/90693/107093 block 1 off 37 to block 107 off 31
[cur:0/5770EB64, xid:355075, rmid:11(Btree), len:34/62, prev:0/5770EAF4] insert_leaf: s/d/r:1663/90693/107099 tid 20/143
[cur:0/5770EBA4, xid:355075, rmid:11(Btree), len:34/62, prev:0/5770EB64] insert_leaf: s/d/r:1663/90693/107100 tid 30/80
[cur:0/5770EBE4, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EBA4] insert_leaf: s/d/r:1663/90693/107101 tid 21/132
[cur:0/5770EC20, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EBE4] insert_leaf: s/d/r:1663/90693/107102 tid 28/7
[cur:0/5770EC5C, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EC20] insert_leaf: s/d/r:1663/90693/107103 tid 33/2
[cur:0/5770EC98, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EC5C] insert_leaf: s/d/r:1663/90693/107104 tid 18/232
[cur:0/5770ECD4, xid:355075, rmid:11(Btree), len:50/78, prev:0/5770EC98] insert_leaf: s/d/r:1663/90693/107105 tid 40/100
[cur:0/5770ED24, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770ECD4] insert_leaf: s/d/r:1663/90693/107106 tid 30/137
[cur:0/5770ED60, xid:355075, rmid:10(Heap), len:84/112, prev:0/5770ED24] update: s/d/r:1663/90693/107093 block 1 off 38 to block 107 off 32
[cur:0/5770EDD0, xid:355075, rmid:11(Btree), len:34/62, prev:0/5770ED60] insert_leaf: s/d/r:1663/90693/107099 tid 20/187
[cur:0/5770EE10, xid:355075, rmid:11(Btree), len:34/62, prev:0/5770EDD0] insert_leaf: s/d/r:1663/90693/107100 tid 31/43
[cur:0/5770EE50, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EE10] insert_leaf: s/d/r:1663/90693/107101 tid 21/152
[cur:0/5770EE8C, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EE50] insert_leaf: s/d/r:1663/90693/107102 tid 28/7
[cur:0/5770EEC8, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EE8C] insert_leaf: s/d/r:1663/90693/107103 tid 33/2
[cur:0/5770EF04, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EEC8] insert_leaf: s/d/r:1663/90693/107104 tid 18/232
[cur:0/5770EF40, xid:355075, rmid:11(Btree), len:50/78, prev:0/5770EF04] insert_leaf: s/d/r:1663/90693/107105 tid 56/107
[cur:0/5770EF90, xid:355075, rmid:11(Btree), len:30/58, prev:0/5770EF40] insert_leaf: s/d/r:1663/90693/107106 tid 18/28

Можно ли из этого что-то вернуть? autovacuum не был включен, полная копия папки PGDATA есть. Postgresql запущен, веб-сервер остановлен. PostgreSQL 8.4

Что такое код pg_update

Для обновления данных в базе данных PostgreSQL применяется команда UPDATE . Она имеет следующий общий формальный синтаксис:

Например, увеличим у всех товаров цену на 3000:

В данном случае обновление касается всех строк. С помощью выражения WHERE можно с помощью условию конкретизировать обновляемые строки — если строка соответствует условию, то она будет обновляться. Например, изменим название производителя с «Samsung» на «Samsung Inc.»:

Также можно обновлять сразу несколько столбцов:

Меняем схему базы данных в PostrgreSQL, не останавливая работу приложения

Эта статья описывает опыт Braintree Payments, подразделения PayPal, и рассказывает о том, как им удаётся обновлять схему баз данных PostgreSQL в условиях, когда приостановка работы API для подобных технических работ недопустима — даже если речь идёт о минутах.

В этой статье будут рассмотрены следующие темы:

Илон Маск рекомендует:  Ip адрес, подсети, маски

Немного основ

Ко всему коду и ко всем изменениям баз данных в Braintree выдвигаются следующие требования:

  • Актуальный код и схемы БД должны иметь прямую совместимость с новым кодом и новыми схемами. Это позволяет вносить изменения постепенно, а не сразу на всех используемых серверах.
  • Новый код и новые схемы должны быть обратно совместимы с актуальным кодом и схемами. Это позволяет без особых проблем отменить любые изменения, в случае возникновения непредвиденных ошибок.

Для всех DDL операций важно, чтобы:

  • Любые блокировки таблиц или индексов держались не более двух секунд.
  • Способы отмены вносимых изменений не требовали откатывать схему базы данных к предыдущей версии.

Транзакционный DDL

PostgreSQL поддерживает транзакции при выполнении DDL операций. В большинстве случаев вы можете выполнять несколько DDL запросов внутри одной транзакции и придерживаться стратегии «всё или ничего». К сожалению, у такого подхода есть существенный недостаток: если вы меняете несколько объектов, вам придётся заблокировать их все. Блокировка нескольких таблиц, во-первых, создаёт вероятность взаимной блокировки (deadlock), а, во-вторых, вынуждает пользователей ждать выполнения всей транзакции. Поэтому для каждого запроса рекомендуется использовать отдельную транзакцию.

Заметьте: параллельное создание индексов — это особый случай. PostgreSQL запрещает выполнять CREATE INDEX CONCURRENTLY внутри явно описанной транзакции; вместо этого PostgreSQL самостоятельно создаёт транзакции и управляет ими. Если по каким-то причинам построение индекса прерывается до успешного завершения, то может потребоваться вручную удалить его, прежде чем пробовать ещё раз. Впрочем, такой индекс всё равно никогда не будет использоваться для обслуживания запросов.

Блокирование строк


У PostgreSQL множество разных уровней блокировки. Нас интересуют в основном блокировки уровня таблицы (потому что DDL обычно оперирует на этом уровне):

  • ACCESS EXCLUSIVE : запрещено любое использование заблокированной таблицы.
  • SHARE ROW EXCLUSIVE : запрещены команды DDL, выполняющиеся параллельно, а также модификация строк (чтение разрешено).
  • SHARE UPDATE EXCLUSIVE : запрещены только команды DDL, выполняющиеся параллельно.

Заметьте: Понятие “команды DDL, выполняющиеся параллельно” в данном контексте включают в себя операции VACUUM и ANALYZE .

Все операции DDL обязательно блокируют таблицу одним из этих способов. К примеру, если вы выполните:

ALTER TABLE foos ADD COLUMN bar INTEGER; PostgreSQL попытается получить блокировку уровня ACCESS EXCLUSIVE на всей таблице foos .

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

Основные подходы

Вместо того чтобы полагаться на PostrgeSQL, осуществляйте явную блокировку самостоятельно. Это позволяет аккуратно контролировать время, на которое запросы откладываются в очередь. Если у вас не получается осуществить блокировку в течение нескольких секунд, рекомендуется добавить небольшую задержку перед следующей попыткой. Таким образом вы позволите отложенным запросам выполниться и не создавать слишком большую нагрузку в будущем. И, наконец, прежде чем пытаться осуществить блокировку, запросите из pg_locks 1 список долго выполняющихся запросов. Это позволит избежать постановки в очередь команд, которые, скорее всего, не выполнятся.

Начиная с PostgreSQL 9.3, вы можете настроить параметр lock_timeout , чтобы контролировать то, насколько долго PostgreSQL будет ожидать получения контроля над таблицей. Если вы вдруг используете версию 9.2 или более раннюю (они, к слову, не поддерживаются, вам стоит обновиться!), вы можете добиться того же результата, используя параметр statement_timeout с явным выражением LOCK

.

Зачастую блокировка уровня ACCESS EXCLUSIVE действительно необходима только на очень короткий период, который требуется PostgreSQL, чтобы обновить его catalog tables (таблицы с метаинформацией). Ниже мы рассмотрим случаи, когда достаточно более слабой блокировки или когда можно применить альтернативные подходы, чтобы избежать длительной приостановки SELECT/INSERT/UPDATE/DELETE .

Обратите внимание: иногда удержание блокировки уровня ACCESS EXCLUSIVE для чего-то большего, чем обновление каталога (или перезаписи) может быть оправдано. Например, если размер таблицы относительно мал. Рекомендуется проверять конкретные случаи использования на реалистичных размерах данных и оборудовании, чтобы увидеть, является ли операция достаточно быстрой. Если вы используете хорошее оборудование, и ваша таблица легко помещается в память, то полное сканирование таблицы или перезапись тысяч строк всё ещё могут быть достаточно быстрыми.

Операции над таблицей

Создание таблицы

В общем случае добавление таблицы — одна немногих операций, о которых не стоит слишком заботиться. Ведь объект, который мы «изменяем», просто технически не может использоваться в этот момент.

Большинство параметров создания таблицы никак не влияют на другие объекты базы данных. Добавление внешнего ключа при определении таблицы заставит PostgreSQL получить блокировку уровня SHARE ROW EXCLUSIVE на упомянутой таблице. Это остановит все DDL запросы, направленные к ней, и модификации строк. Несмотря на то что эта блокировка не должна быть слишком долгой, о ней стоит помнить, как и о любой другой операции, вызывающей блокировку. Рекомендуется разделять эти две операции: создайте таблицу, и только потом добавьте внешний ключ.

Удаление таблицы

Удаление таблицы по понятным причинам требует блокировки уровня ACCESS EXCLUSIVE . Если таблица уже не используется, вы можете спокойно её удалить. Но прежде чем на самом деле выполнить DROP TABLE . вам следует проверить документацию и код, чтобы удостовериться, что все упоминания о ней на самом деле стёрты. Чтобы перепроверить это, вы можете запросить у PostgreSQL статистику использования таблицы (используя представление pg_stat_user_tables 2 ).

Переименование таблицы

Вероятно, ни для кого не станет открытием, что переименование таблицы требует ACCESS EXCLUSIVE . Очень маловероятно, что ваш код сможет безопасно обработать переименование таблицы прямо налету — это возможно только если в таблицу никто не пишет и не берёт из неё данные.

Рекомендуется избегать переименований таблиц везде, где это возможно. Но если переименование действительно необходимо, то для безопасности:

  • Создайте новую таблицу с такой же схемой, как предыдущая.
  • Скопируйте данные из старой таблицы в новую.
  • Создайте триггеры на INSERT и UPDATE к старой таблице, чтобы при её использовании поддерживалось актуальное состояние новой таблицы.
  • Начните использовать новую таблицу.

Другие подходы, основанные на использовании представлений (views) и/или правил (RULE), также могут вам подойти, всё зависит от производительности, которая вам необходима.

Операции над столбцами

Обратите внимание: установка ограничений, накладываемых на столбцы (например NOT NULL ), и прочих ограничений (например EXCLUDES ) описана в отдельной части статьи.

Добавить столбец

Добавление столбца в существующую таблицу обычно требует короткой блокировки уровня ACCESS EXCLUSIVE на таблице на то время, пока обновляются системные таблицы каталогов (catalog tables).

Значения по умолчанию. Установка значения по умолчанию одновременно с созданием столбца заблокирует таблицу на время установки значений. Вместо этого следует:

  • Добавить новый столбец (без значений по умолчанию).
  • Назначить столбцу значение по умолчанию.
  • Заполнить этим значением уже существующие строки по отдельности.

Обратите внимание: В недавно выпущенном PostgreSQL 11 эти советы больше не актуальны для неволатильных значений по умолчанию. Теперь добавление столбца со значением по умолчанию требует только обновления таблиц каталогов, а все обращения к строкам без значения будут магическим образом возвращать нужное значение.

Ограничения not null. Добавление столбца с ограничением NOT NULL возможно только в двух случаях: если в таблице нет строк или если был указан DEFAULT . Первый случай тривиален — потребуется только изменение каталога. Во втором же случае следует проделать все описанные выше действия для значений по умолчанию.


Заметьте: После добавления нового столбца все запросы вида SELECT * FROM . начнут возвращать новый столбец. Важно, чтобы код, который будет работать с этой таблицей, мог безопасно обработать новый столбец. Лучше просто не использовать * , всегда указывая столбцы явно.

Изменить тип столбца

Обычно изменение типа столбца приводит к полной блокировке всей таблицы до тех пор, пока все строки не будут обновлены в соответствии с новым типом. Однако есть несколько исключений:

  • Приведение VARCHAR к типу TEXT (начиная с версии 9.1); а точнее всегда, когда старый тип бинарно совместим с новым типом и для преобразования не требуется никаких фактических операций.
  • Старый тип является частным случаем нового (начиная с версии 9.1).
  • Когда увеличивается или удаляется заданное ограничение на длину или точность: например VARCHAR(5) → VARCHAR(10) и VARCHAR(5) → VARCHAR (начиная с версии 9.2).

Обратите внимание: Несмотря на то что некоторые из исключений выше были введены ещё в версии 9.1, изменение типа индексируемого столбца в этой версии всегда приводит к переписыванию индекса. Начиная с версии 9.2, индекс не переписывается, если не переписывалось содержимое таблицы. Если вы хотите удостовериться, что ваше изменение не инициирует перезапись, вы можете сделать запрос к pg_class 3 и проверить, что столбец relfilenode не изменился.

Если вам требуется изменить тип столбца, и описанные выше исключения к вашему случаю не относятся, то:

  • Добавьте новый столбец new_ .
  • Осуществляйте запись одновременно в оба столбца (например, с помощью триггеров BEFORE INSERT/UPDATE ).
  • Заполните новый столбец копиями значений из старого.
  • Переименуйте в old_ , а new_ , соответственно, в ; делайте это внутри единой транзакции и явного выражения LOCK
.
  • Удалите старый столбец.
  • Удалить столбец

    Удалять столбец нужно с крайней осторожностью. Для обновления каталога оно требует полной блокировки таблицы, но не влечёт за собой физического изменения строк. Если в настоящее время столбец не используется, вы можете безопасно удалить его. Важно, однако, проверить, что на этот столбец не ссылаются никакие зависимые объекты (которые небезопасно удалять). В частности, любые индексы, использующие столбец, должны быть удалены отдельно с использованием безопасного DROP INDEX CONCURRENTLY . В противном случае, они будут автоматически удалены вместе со столбцом, и всё это время будет действовать блокировка уровня ACCESS EXCLUSIVE . Чтобы проверить, есть ли у вас такие объекты, вы можете сделать запрос к pg_depend 4 .

    Прежде чем запускать ALTER TABLE . DROP COLUMN . на продакшне, стоит удостовериться, что все ссылки на этот столбец в документации и коде были окончательно убраны. Это позволит безопасно откатиться к релизам, выпущенным до того, как был удалён столбец.

    Заметьте: Удаление столбца потребует от вас обновления всех представлений, триггеров, функций и т. д., которые были завязаны на этот столбец.

    Операции над индексами

    Создать индекс

    Если вы просто запустите CREATE INDEX . , то получите блокировку уровня ACCESS EXCLUSIVE на всей индексируемой таблице. А вот если вы выполните CREATE INDEX CONCURRENTLY . , то блокировка будет всего лишь уровня SHARE UPDATE EXCLUSIVE . Правда, вместо одного сканирования таблицы придётся выполнить два. При уровне блокировки во втором случае будут разрешены и чтение, и запись в таблицу.

    • Несколько созданий индексов, выполняющиеся параллельно на одной таблице, не завершат выполнение ни одного из CREATE INDEX CONCURRENTLY . до тех пор, пока самый медленный из них ещё работает.
    • CREATE INDEX CONCURRENTLY . не может быть выполнен внутри транзакции, вместо этого транзакциями неявно управляет PostgreSQL. Из-за этого никакие auto-vacuum’ы не смогут очистить ненужные кортежи, которые появились после начала построения индекса, и до завершения этого процесса. Если у таблицы большой объём изменений (особенно плохо, если сама таблица при этом мала), это может привести к крайне неоптимальному времени выполнения запроса.
    • CREATE INDEX CONCURRENTLY . завершит выполнение только после того, как завершатся все транзакции, использующие таблицу.

    Удалить индекс

    Стандартное выражение DROP INDEX . получает ACCESS EXCLUSIVE на всей таблице на всё время удаления индекса. Для небольших индексов это может не быть проблемой — это должна быть весьма короткая операция. Однако для огромных индексов работа с файловой системой может занять значительное время. Нам на помощь придёт DROP INDEX CONCURRENTLY . , которая потребует блокировку уровня SHARE UPDATE EXCLUSIVE ; запись и чтение будут продолжаться, пока мы удаляем индекс.

    Подводные камни использования DROP INDEX CONCURRENTLY . :

    • Этот запрос не может быть использован для удаления индекса, который поддерживал какое-либо ограничение (например PRIMARY KEY или UNIQUE ).
    • Он не может быть использован как часть транзакции, ими управляет PostgreSQL “под капотом”. Из-за этого никакие auto-vacuum’ы не смогут очистить ненужные кортежи, которые появились после начала построения индекса, и до завершения этого процесса. Если у вас есть таблица с большим объёмом изменений (особенно плохо, если сама таблица при этом мала) это может привести к крайне неоптимальному времени выполнения запроса.
    • Запрос завершит выполнение только после того, как завершатся все транзакции, использующие таблицу.

    Обратите внимание: DROP INDEX CONCURRENTLY . был добавлен только в Postgres 9.2. Если вы всё ещё работаете с версией 9.1 или ниже, вы можете добиться примерно такого же результата, если отметите индекс как некорректный (invalid) и не готовый к записи; затем вам нужно будет сбросить буфер с помощью расширения pgfincore. После этого можно просто удалять индекс.

    Переименовать индекс

    ALTER INDEX . RENAME TO . требует блокировку уровня ACCESS EXCLUSIVE на переименовываемом индексе, блокируя чтение и запись в соответствующую таблицу. Однако коммит, который должен стать частью PostgreSQL 12 понижает это требование до SHARE UPDATE EXCLUSIVE .

    Произвести переиндексацию

    REINDEX INDEX . также требует ACCESS EXCLUSIVE на индексе. Чтобы этого не допускать, рекомендуется следующий алгоритм:

    • Создать новый индекс, как это описано выше, который повторял бы существующий.
    • Удалить старый индекс, наименее затратным способом (описан выше).
    • Переименовать новый индекс, чтобы он повторял имя старого.

    Заметьте: Если индекс, который вам необходимо перестроить, содержал ограничения, не забудьте добавить их и в новый индекс (как это сделать, мы как раз рассмотрим в следующей части).

    Ограничения

    NOT NULL


    Удаление существующего ограничения NOT NULL из столбца требует полной блокировки таблицы. Это не так существенно, так как выполняется простое обновление каталога.

    А вот добавление ограничения NOT NULL к существующему столбцу требует ACCESS EXCLUSIVE на время проведения полного скана таблицы, чтобы удостовериться, что в ней нет null -значений. Вместо этого вам следует:

    • Добавить ограничение проверки CHECK , которое бы требовало от значений столбца не быть null -ами. Сделать это можно с помощью ALTER TABLE
    ADD CONSTRAINT CHECK ( IS NOT NULL) NOT VALID; . Здесь NOT VALID сообщает PostgreSQL, что нет необходимости проводить полную проверку, чтобы удостовериться, что все строки соответствуют условию.
  • Вручную проверить, что все строки содержат значения, отличные от null .
  • Валидировать наложенное ограничение с помощью ALTER TABLE
  • VALIDATE CONSTRAINT ; . Выполнение этого выражения заблокирует получение других EXCLUSIVE блокировок таблицы, но не будет мешать записи или чтению.

    Бонус: сейчас в работе находится патч (и, возможно, он войдёт в релиз PostgreSQL 12), который позволит создавать ограничение NOT NULL без полного просмотра таблицы при ограничении CHECK вроде того, что мы создали выше.

    Внешний ключ

    ALTER TABLE . ADD FOREIGN KEY требует блокировку SHARE ROW EXCLUSIVE (по крайней мере с версии 9.5) на обеих таблицах — и на изменяемой, и на той, на которую мы ссылаемся. Такая блокировка, конечно, не будет блокировать запросы SELECT , однако длительный запрет на внесение изменений тоже неприемлем.

    Чтобы избежать длительной блокировки, можно поступить следующим образом:

    • ALTER TABLE . ADD FOREIGN KEY . NOT VALID : добавит внешний ключ и начнёт применять ограничение ко всем новым выражениям INSERT/UPDATE . При этом существующие строки не будут проверены на соответствие ограничению. Это операция тоже требует SHARE ROW EXCLUSIVE , но лишь на очень короткое время.
    • ALTER TABLE . VALIDATE CONSTRAINT проверит все существующие строки на соответствие указанному ограничению. Проверка требует только SHARE UPDATE EXCLUSIVE , поэтому может работать параллельно с чтением данных и записью.

    Ограничение проверки (CHECK)

    ALTER TABLE . ADD CONSTRAINT . CHECK (. ) требует блокировку уровня ACCESS EXCLUSIVE . Однако, как и в случае с внешними ключами, эту операцию можно разделить на две:

    • ALTER TABLE . ADD CONSTRAINT . CHECK (. ) NOT VALID добавит ограничение проверки и начнёт применять ограничение ко всем новым выражениям INSERT/UPDATE . При этом существующие строки проверяться не будут. Это операция требует ACCESS EXCLUSIVE .
    • ALTER TABLE . VALIDATE CONSTRAINT проверит все существующие строки. Проверка требует SHARE UPDATE EXCLUSIVE на таблице. Если ограничение ссылается на другую таблицу, на ней будет установлена блокировка уровня ROW SHARE . Напомним, она лишь откладывает операции, которые требуют полной блокировки таблицы.

    Ограничение уникальности (UNIQUE)

    ALTER TABLE . ADD CONSTRAINT . UNIQUE (. ) требует блокировку уровня ACCESS EXCLUSIVE . И снова делим операцию на две:

    • Конкурентно создайте индекс с ограничением на уникальность (как описано выше). Это действие само по себе будет требовать уникальности значений. Однако, если вам нужно именно ограничение в смысле constraint (или первчиный ключ), то вы можете добавить его следующим шагом.
    • ALTER TABLE . ADD CONSTRAINT . UNIQUE USING INDEX создаст ограничение, используя уже существующий индекс. Операция всё ещё требует ACCESS EXCLUSIVE , но лишь для быстрых операций над каталогом.

    Обратите внимание: если вы указываете PRIMARY KEY вместо UNIQUE , то все столбцы, которые могли содержать null ‘ы получат ограничение NOT NULL . Это потребует полного скана таблицы, и на данный момент этого никак нельзя избежать. Детали описаны в разделе про NOT NULL.

    Ограничение-исключение (EXCLUDE)

    ALTER TABLE . ADD CONSTRAINT . EXCLUDE USING . требует блокировки ACCESS EXCLUSIVE . Если вы добавите ограничение исключительности, то это потянет за собой создание индекса, и, к сожалению, не получится использовать уже сформированный индекс (как мы делали с ограничением уникальности выше).

    Перечисляемые типы

    CREATE TYPE AS (. ) и DROP TYPE (после проверки, что тип нигде не используются) могут быть безопасно выполнены без всяких блокировок.

    Изменение используемых значений

    В PostgreSQL добавили выражение ALTER TYPE RENAME VALUE

      TO . Оно не требует блокировки таблиц, которые используют перечислимый тип.

    Удаление значений

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

    Библиотека для Ruby on Rails

    Braintree Payments, в дополнение к статье, выложили исходный код своей библиотеки для Ruby on Rails — pg_ha_migrations. Этот gem позволяет безопасно использовать DDL в проектах, которые используют Ruby on Rails и/или ActiveRecord. Её основная задача — позволить явно указывать способ выполнения операции, выбирая между различными видами издержек. Подробнее можно прочитать в README проекта.

    Примечания

    1 Вы можете получить активные запросы, которые долго исполняются, выполнив следующий системный запрос:

    2 Посмотреть внутреннюю статистику PostgrSQL об использовании заданной таблицы можно, выполнив следующий запрос:

    3 Если вы хотите узнать, вызывает ли DDL перезапись связанных объектов, вам стоит посмотреть меняются ли значения relfilenode после выполнения следующего выражения:

    4 Следующее выражение поможет вам найти любые зависимые от столбца объекты (в частности, индексы):

    Илон Маск рекомендует:  Как заставить chttpfile принудительно передавать файлы в бинарном виде
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL