FirebirdSQL logo
 COMMENTSОператоры процедурного SQL (PSQL) 

Как сервер работает с WITH LOCK

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

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

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

Note

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

Сервер блокирует строки по мере их выборки.Это имеет важные последствия, если вы блокируете сразу несколько строк.Многие методы доступа к базам данных Firebird по умолчанию используют для выборки данных пакеты из нескольких сотен строк (так называемый "буфер выборки"). Большинство компонентов доступа к данным не выделяют строки, содержащиеся в последнем принятом пакете, и для которых произошёл конфликт обновления.

Предостережения при использовании WITH LOCK

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

  • Хотя явные блокировки могут использоваться для предотвращения и/или обработки необычных ошибок конфликтов обновления, объем ошибок обновления (deadlock) вырастет, если вы тщательно не разработаете свою стратегию блокировки и не будете ей строго управлять;

  • Большинство приложений не требуют явной блокировки записей. Основными целями явной блокировки являются: 1) предотвращение дорогостоящей обработки ошибок конфликта обновления в сильно загруженных приложениях и 2) для поддержания целостности объектов, отображаемых из реляционной базы данных в кластеризуемой среде. Если использование вами явной блокировки не подпадает под одну из этих двух категорий, то это является неправильным способом решения задач в Firebird;

  • Явная блокировка — это расширенная функция; не злоупотребляйте её использованием! В то время как явная блокировка может быть очень важной для веб-сайтов, обрабатывающих тысячи параллельных пишущих транзакций или для систем типа ERP/CRM, работающих в крупных корпорациях, большинство прикладных программ не требуют её использования.

Примеры использования явной блокировки

Example 1. Блокировка одной записи
SELECT *
FROM DOCUMENT
WHERE DOCUMENT_ID=? WITH LOCK
Example 2. Блокировка нескольких записей с их последовательной обработкой курсором DSQL:
SELECT *
FROM DOCUMENT
WHERE PARENT_ID=?
FOR UPDATE WITH LOCK

OPTIMIZE FOR

Назначение

Изменение стратегии оптимизатора.

Синтаксис
SELECT ...
FROM [...]
[WHERE ...]
[...]
[OPTIMIZE FOR {FIRST | ALL} ROWS]

Предложение OPTIMIZE FOR позволяет изменить стратегию оптимизатора на уровне текущего SQL оператора.Оно может встречаться только в SELECT операторе верхнего уровня.

Существует две стратегии оптимизации запросов:

  • FIRST ROWS - оптимизатор строит план запроса так, чтобы наиболее быстро извлечь только первые строки запроса;

  • ALL ROWS - оптимизатор строит план запроса так, чтобы наиболее быстро извлечь все строки запроса.

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

По умолчанию используется стратегия оптимизации указанная в параметре OptimizeForFirstRows конфигурационного файлаfirebird.conf или database.conf. OptimizeForFirstRows = false соответствует стратегии ALL ROWS,OptimizeForFirstRows = true соответствует стратегии FIRST ROWS.

Стратегия оптимизации может быть также изменена на уровне сессии с помощью оператора SET OPTIMIZE.Предложение OPTIMIZE FOR указанное в SQL операторе позволяет переопределить стратегию указанную на уровне сессии.

Предложение OPTIMIZE FOR всегда указывает самым последним в SELECT запросе, но перед предложением INTO.

Note

Если в SELECT запросе встречаются предложения FIRST …​ SKIP, ROWS, OFFSET …​ FETCH, то оптимизатор неявно переключаются в режим FIRST ROWS.

INTO

Назначение

Передача результатов SELECT в переменные.

Доступно в:

PSQL

Синтаксис:
SELECT [...] <column-list>
FROM ...
[...]
[INTO <variable-list>]

<variable-list> ::= [:]psqlvar [, [:]psqlvar ...]

В PSQL (хранимых процедурах, триггерах и др.) результаты выборки команды SELECT могут быть построчно загруженыв локальные переменные (число, порядок и типы локальных переменных должны соответствовать полям SELECT). Часто такая загрузка — единственный способ что-то сделать с возвращаемыми значениями.

Простой оператор SELECT может быть использован в PSQL, только если он возвращает не более одной строки, то есть, если это запрос типа singleton (одиночка).Для запросов, возвращающих несколько строк, PSQL предлагает использовать оператор FOR SELECT.

Important

В случае, когда запрос не возвращает данных (ноль строк), значения переменных в списке INTO не изменяется.

Также, PSQL поддерживает оператор DECLARE CURSOR,который связывает именованный курсор с определенной командой SELECT — и этот курсор впоследствии может быть использован для навигации по возвращаемому набору данных.

В PSQL выражение INTO должно появляться в самом конце команды SELECT.

Important
Обратите внимание.

В PSQL двоеточие перед именами переменных является опциональным.

Примеры

В PSQL, можно присвоить значения min_amt, avg_amt и max_amt заранее объявленным переменным или выходным параметрам:

SELECT
  MIN(amount),
  AVG(CAST(amount AS float)),
  MAX(amount)
FROM orders
WHERE artno = 372218
INTO min_amt,
     avg_amt,
     max_amt;

В данном запросе CAST служит для корректного вычисления среднего значения.Если не привести значение к float, то среднее значение будет обрезано до ближайшего целого значения.

В триггере:

SELECT LIST(name, ', ')
FROM persons p
WHERE p.id IN (new.father, new.mother)
INTO new.parentnames;