Вышел Firebird 4.0

firebird-logo

Сегодня, 1 июня 2021 года, выпущен Firebird 4.0 — седьмой основной выпуск СУБД Firebird, разработка которого началась в 2016 году. Ключевой задачей при разработке Firebird 4.0 было повышение доступности баз данных (синхронная и асинхронная логическая репликация).

Одно из важнейших улучшений в Firebird 4.0 — изменение подхода к созданию согласованного представления о состоянии базы данных, видимом для выполняющихся транзакций. Новый подход позволил решить проблему согласованного чтения на уровне запроса в транзакциях Read Committed Read Consistency, а также ввести так называемую промежуточную сборку мусора. Промежуточная сборка мусора позволяет дополнительно сокращать длины цепочек версий при наличии долгих активных транзакций.

Полный список изменений доступен в Release Notes

Также доступна документация по языку SQL Firebird 4.0 на русском и английском языках.

Для того чтобы администраторы и разработчики могли как можно скорее перейти на новую версию подготовлено краткое руководство по миграции на Firebird 4.0 на русском и английском языках.

Бинарные комплекты для платформ Windows, Linux и Android (как 32-битные, так и 64-битные) доступны для загрузки.

Далее кратко описаны нововведения в Firebird 4.0

Среди важных улучшений также можно отметить поддержку чисел с точностью более 18 цифр, улучшение точности вычислений для более коротких чисел, поддержка часовых поясов, увеличение длины имён метаданных до 63 символов, улучшение подсистемы безопасности, копии постоянной готовности (physical standby) на основе nbackup, таймауты простоя соединения и выполнения SQL запроса, Batch API, а также множество новых возможностей языка SQL.

Далее мы перечислим ключевые улучшения, сделанные в Firebird 4.0, и их краткое описание. Подробное описание всех изменений можно прочитать в «Firebird 4.0 Release Notes».


Логическая репликация

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

Репликация отслеживает следующие события:


  • добавление, обновление и удаление записей в таблицах
  • изменение последовательностей (генераторов)
  • DDL операторы

Поддерживается синхронный и асинхронный режимы.

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

При асинхронной репликации изменения записываются в файлы локального журнала, передаются по сети и применяются к реплике базы данных. Влияние на производительность намного меньше, но вызывает задержку (отставание репликации) пока изменения ожидают применения к реплике базы данных, т.е. реплика базы данных всегда «догоняет» основную базу данных.


Копии постоянной готовности (nbackup physical standby)

Утилита nBackup в Firebird 4 может выполнять физическое резервное копирование, которое использует GUID (UUID) самой последней резервной копии базы данных, доступной только для чтения. Изменения (дельты) из исходной базы данных можно последовательно (по одной)
применять к резервной базе данных, без необходимости сохранять и применять (сразу) все дельты с момента последней полной резервной копии.

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


Пул внешних подключений

Чтобы избежать задержек при создании внешних подключений, подсистема внешних источников
данных (EXECUTE STATEMENT ... ON EXTERNAL DATA SOURCE) была дополнена пулом подключений. Пул, в течение некоторого времени, сохраняет бездействующие внешние подключения, чтобы уменьшить накладные расходы для клиентов с одинаковыми строками подключений.


Тайм-ауты

В Firebird 4.0 добавлены настраиваемые тай-ауты:


  • тайм-аут простоя соединения (сеанса)
  • тайм-аут выполнения SQL запроса

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

Тайм-аут выполнения SQL запроса, позволяет автоматически останавливать выполнение запроса, если он выполняется дольше заданного периода тайм-аута.


Слепки состояния базы данных (database snapshots) на основе порядка фиксации

В Firebird 4.0 кардинально переработана концепция создания слепков состояния базы данных (database snapshot). Ранее для создания слепков (snapshot) требовалось создать копию TIP (transaction inventory page), в Firebird 4 достаточно просто запомнить номер фиксации (Commit Number). Таким образом, процесс создания слепка в Firebird 4 требует значительно меньше ресурсов, чем ранее.


Режим изолированности READ COMMITTED READ CONSISTENCY

Поскольку процесс создания слепка состояния базы данных в Firebird 4, обходится значительно дешевле чем ранее. Это позволяет создавать такие слепки не только в момент старта транзакции SNAPSHOT, но и для каждого SQL запроса и открытого курсора в новом режиме изолированности транзакции READ COMMITTED READ CONSISTENCY. В режиме изолированности READ COMMITTED READ CONSISTENCY запросы всегда читают согласованное состояние базы данных на момент старта запроса.


Промежуточная сборка мусора

Ранее ненужные версии записей (мусор) могли быть удалены только для версий, созданных транзакцией, номер которой меньше чем OST (Oldest Snapshot Transaction). То есть мусор можно было удалить только из конца цепочки версий. Новая концепция создания слепков состояния базы данных (database snapshot) позволила удалять мусор в цепочке версий между активными версиями записи (версий для которых есть активный слепок состояния). Это позволяет значительно сократить длину цепочки версий при наличии длительных активных транзакций и сократить их негативное влияние на производительность.


Совместное использование SNAPSHOT транзакций

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


Поддержка международных часовых поясов

В Firebird 4.0 введены новые типы данных TIME WITH TIME ZONE и TIMESTAMP WITH TIME ZONE для поддержки даты и времени с часовыми поясами, а также типы TIME WITHOUT TIME ZONE и TIMESTAMP WITHOUT TIME ZONE как псевдонимы существующих типов TIME и TIMESTAMP.

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


Повышенная точность хранения и вычисления для типов NUMERIC и DECIMAL

Типы NUMERIC и DECIMAL теперь могут хранить числа с точностью до 38 цифр. Для хранения чисел с точностью более 18 цифр Firebird 4.0 использует тип INT128 (128 битное целое). Кроме того улучшена обработка промежуточных результатов вычислений с типами данных NUMERIC и DECIMAL. В предыдущих версиях Firebird числа, внутренне представленные типом данных
BIGINT (то есть с точностью от 10 до 18 десятичных цифр), умножались/делились с использованием того же типа данных BIGINT для промежуточных вычислений, что могло вызвать ошибки переполнения из-за ограничения доступной точности. В Firebird 4 такие вычисления выполняются с использованием 128-битных целых чисел, что снижает вероятность неожиданных переполнений.

Тип INT128 также доступен для использования.


Тип данных DECFLOAT

DECFLOAT — это числовой тип, соответствующий стандарту SQL:2016, который точно хранит числа с плавающей запятой (десятичный тип с плавающей запятой), в отличие от FLOAT или DOUBLE PRECISION, обеспечивающие двоичное приближение предполагаемой точности. Firebird 4 соответствует типам Decimal64 и Decimal128 из стандарта IEEE 754–1985, обеспечивая для этого типа как 16-значную, так и 34-значную точность.

Все промежуточные вычисления производятся с 34-значными значениями.


Поддержка пакетных операций для параметризованных запросов в API

OO-API в Firebird 4 поддерживает пакетное выполнение SQL операторов (с одним и более наборов параметров). Batch API позволяет производить операции импорта данных по сети более эффективно, поскольку значительно снижается количество сетевых пакетов.

Batch API теперь используется в gbak при восстановлении базы данных из резервной копии. Таким образом процесс восстановления с использованием сетевых протоколов происходит быстрее.


Виртуальная таблица RDB$CONFIG

Добавлена новая виртуальная таблица RDB$CONFIG. В этой таблице перечислены параметры конфигурации, актуальные для текущей базы данных. Таблица RDB$CONFIG заполняется из структур в памяти по запросу, и ее экземпляр сохраняется на время существования SQL запроса.


Улучшение производительности сортировок

Исторически сложилось, что когда выполняется внешняя сортировка, Firebird записывает в блоки сортировки как ключевые поля (перечислены в предложениях ORDER BY или GROUP BY), так и не ключевые (все остальные) поля запроса. После завершения сортировки (все) поля запроса вычитываются из блоков сортировки, находящихся в памяти или/и во (временных) файлах. Этот подход обычно считается более быстрым, поскольку записи читаются в порядке хранения вместо случайной выборки страниц данных, соответствующих отсортированным записям. Однако, если не ключевые поля велики (например, задействованы длинные VARCHAR), то они увеличивают размер блоков сортировки, провоцируя их вытеснение на диск и более интенсивный ввод-вывод для временных файлов. Firebird 4 предоставляет альтернативный подход, когда только ключевые поля и записи DBKEY хранятся внутри блоков сортировки, а не ключевые поля повторно выбираются со страниц данных после сортировки. Это улучшает производительность сортировки в случае длинных не ключевых полей.


Улучшения SQL


Улучшения DDL


  • Увеличена максимальная длина идентификаторов до 63 символов. Метаданные теперь хранятся в кодировке UTF-8 вместо устаревшей кодировки UNICODE_FSS (ранняя версия реализации UNICODE).


  • Новые типы данных: INT128, DECFLOAT, TIME WITH TIME ZONE и TIMESTAMP WITH TIME ZONE.


  • Добавлены псевдонимы для бинарных строковых типов BINARY (n) и VARBINARY (n). Эти типы данных эквивалентны [VAR]CHAR(n) CHARACTER SET OCTETS.


  • Расширены опции IDENTITY столбцов. Теперь IDENTITY столбцы могут быть объявлены в двух вариантах: GENERATED ALWAYS AS IDENTITY и GENERATED BY DEFAULT AS IDENTITY. Ранее существовал только вариант GENERATED BY DEFAULT AS IDENTITY.


  • Добавлены операторы для настройки набора таблиц, которые включены в публикацию. Публикация — набор таблиц, включенных в процесс репликации.



Улучшения DML


  • Добавлена поддержка LATERAL производных таблиц. Производная таблица, определенная с помощью ключевого слова LATERAL, называется боковой производной таблицей. Если производная таблица определена как боковая, то в этом же предложении FROM разрешено ссылаться на другие таблицы, но только на те, которые были объявлены перед ней в предложении FROM.
SELECT
  HORSE.NAME,
  M.BYDATE,
  M.HEIGHT_HORSE,
  M.LENGTH_HORSE
FROM HORSE
CROSS JOIN LATERAL (
  SELECT 
    MEASURE.BYDATE,
    MEASURE.HEIGHT_HORSE,
    MEASURE.LENGTH_HORSE  
  FROM MEASURE
  WHERE MEASURE.CODE_HORSE = HORSE.CODE_HORSE
  ORDER BY MEASURE.BYDATE DESC
  FETCH FIRST ROW ONLY) M

  • Добавлена поддержка контекстного значения DEFAULT в операторах INSERT, UPDATE, MERGE, UPDATE OR INSERT.
UPDATE cars
SET BYYEAR = DEFAULT
WHERE ID = 1;

  • Добавлена возможность использовать предложение OVERRIDING для IDENTITY полей.


  • Добавлена поддержка предложения кадра (frames) для оконных функций. Кадром называется набор строк внутри секции которым оперирует оконная функция.


 ::=
  {RANGE | ROWS} 

 ::=
  { | }

 ::=
  {UNBOUNDED PRECEDING |  PRECEDING | CURRENT ROW}

 ::=
  BETWEEN  AND 

 ::=
  {UNBOUNDED PRECEDING |  PRECEDING |  FOLLOWING | CURRENT ROW}

 ::=
  {UNBOUNDED FOLLOWING |  PRECEDING |  FOLLOWING | CURRENT ROW}

Пример использования кадров (рамки окна):

SELECT
  id,
  salary,
  SUM(salary) OVER() AS s1,
  SUM(salary) OVER(ORDER BY salary) AS s2,
  SUM(salary) OVER(ORDER BY salary ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS s3,
  SUM(salary) OVER(ORDER BY salary ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS s4,
  SUM(salary) OVER(ORDER BY salary ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS s5,
  SUM(salary) OVER(ORDER BY salary ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS s6,
  SUM(salary) OVER(ORDER BY salary ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS s7,
  SUM(salary) OVER(ORDER BY salary ROWS 1 PRECEDING) AS s8
FROM
employee

  • Именованные окна. Как видно из предыдущего примера, определения окон может быть довольно большим, кроме того для нескольких оконных функций может быть указанно одно и то же окно. Чтобы избежать дублирование описания окна, в Firebird 4.0 вы можете воспользоваться предложением WINDOW, которое определяет именованные окна. Именованные окна поддерживают наследование атрибутов, то есть одно именованное окно может ссылаться на другое именованное окно.
SELECT
  id,
  department,
  salary,
  count(*) OVER w1,
  first_value(salary) OVER w2,
  last_value(salary) OVER w2,
  sum(salary) over (w2 ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS s
FROM employee
WINDOW 
  w1 AS (PARTITION BY department),
  w2 AS (w1 ORDER BY salary)
ORDER BY department, salary;

  • Поддержка предложения FILTER для агрегатных функций
SELECT
  invoice_year,
  SUM(revenue) FILTER (WHERE invoice_month = 1) AS jan_revenue,
  SUM(revenue) FILTER (WHERE invoice_month= 2) AS feb_revenue,
...
  SUM(revenue) FILTER (WHERE invoice_month = 12) AS dec_revenue
FROM (
  SELECT
    EXTRACT(YEAR FROM invoices.invoice_date) AS invoice_year,
    EXTRACT(MONTH FROM invoices.invoice_date) AS invoice_month,
    invoices.revenue AS revenue
  FROM invoices
)
GROUP BY invoice_year

Улучшения PSQL


  • Добавлена поддержка «лишних» параметров в EXECUTE STATEMENT. Входные параметры команды EXECUTE STATEMENT могут начинаться с ключевого слова EXCESS. Если указано EXCESS, то данный параметр может быть опущен в тексте запроса.
CREATE PROCEDURE P_EXCESS (A_ID INT, A_TRAN INT = NULL, A_CONN INT = NULL)
  RETURNS (ID INT, TRAN INT, CONN INT)
AS
  DECLARE S VARCHAR(255);
  DECLARE W VARCHAR(255) = '';
BEGIN
  S = 'SELECT * FROM TTT WHERE ID = :ID';

  IF (A_TRAN IS NOT NULL)
  THEN W = W || ' AND TRAN = :a';

  IF (A_CONN IS NOT NULL)
  THEN W = W || ' AND CONN = :b';

  IF (W <> '')
  THEN S = S || W;

  -- будет сгенерипрована ошибка есть A_TRAN или A_CONN равно null
  -- FOR EXECUTE STATEMENT (:S) (a := :A_TRAN, b := A_CONN, id := A_ID)

  -- Следующий код отработает в любом случае
  FOR EXECUTE STATEMENT (:S) (EXCESS a := :A_TRAN, EXCESS b := A_CONN, id := A_ID)
  INTO :ID, :TRAN, :CONN
  DO SUSPEND;
END

  • Добавлена поддержка рекурсивных подпроцедур и подфункций.
execute block returns (i integer, o integer)
as
  declare function fibonacci(n integer) returns integer
  as
  begin
    if (n = 0 or n = 1) then
      return n;
    else
      return fibonacci(n - 1) + fibonacci(n - 2);
  end
begin
  i = 0;
  while (i < 10)
  do
  begin
    o = fibonacci(i);
    suspend;
    i = i + 1;
  end
end

  • Добавлена возможность получить текст ошибки и имя исключения в блоке обработки ошибок. Для этого введена новая системная функция RDB$ERROR.
BEGIN
...
WHEN ANY DO
  EXECUTE PROCEDURE P_LOG_EXCEPTION(RDB$ERROR(MESSAGE));
END

  • В PSQL блоках кода разрешено использовать операторы управления сеансовым окружением.

Операторы управления сеансовым окружением

В Firebird 4.0 появился новый класс SQL операторов — так называемые операторы управления сеансовым окружением. Обычно такие операторы начинаются с глагола SET, некоторые из них начинаются с ключевого слова ALTER.

Данные SQL операторы работают вне механизма транзакций, и выполненные ими изменения вступают в силу немедленно.

Операторы управления сеансовым окружением доступны, в том числе и в PSQL коде. Они особенно полезны в ON CONNECT триггерах.

Операторы управления сеансовым окружением разбиты на следующие группы:


  • управления тайм-аутами (SET STATEMENT TIMEOUT и SET SESSION IDLE TIMEOUT);
  • управление пулом внешних соединений (ALTER EXTERNAL CONNECTIONS POOL ...);
  • изменение текущей роли (SET ROLE и SET TRUSTED ROLE);
  • управление обработкой типа DECFLOAT (SET DECFLOAT ROUND и SET DECFLOAT TRAPS TO);
  • управление часовым поясом (SET TIME ZONE);
  • управление привязкой типов (SET BIND OF);
  • сброс сеансового окружения (ALTER SESSION RESET).

Улучшение безопасности


Системные привилегии

Эта функция позволяет предоставлять и отменять некоторые специальные привилегии обычным пользователям для выполнения задач, которые исторически ограничивались только SYSDBA, например: запуск утилит gbak, gfix, nbackup, доступ к таблицам мониторинга, запуск пользовательской трассировки и т.д.

Набор системных привилегий может быть указан при создании/изменении роли.

CREATE ROLE SYS_UTILS
SET SYSTEM PRIVILEGES TO USE_GBAK_UTILITY, USE_GSTAT_UTILITY, IGNORE_DB_TRIGGERS;

Выдача ролей другой роли

Firebird 4.0 позволяет назначать роль другой роли. Это явление получило название «Кумулятивные роли». Этот термин относится к ролям, встроенным в другие роли посредством оператора GRANT ROLE a TO ROLE b. Оператор GRANT ROLE расширен до следующего синтаксиса

GRANT [DEFAULT] role_name 
TO [USER user_name | ROLE role_name] [WITH ADMIN OPTION];

REVOKE [DEFAULT] role_name 
FROM [USER user_name | ROLE role_name] [WITH ADMIN OPTION];

Ключевое слово DEFAULT в операторах GRANT и REVOKE

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


SQL SECURITY

Все объекты метаданных, содержащие DML или PSQL код, могут выполнятся в одном из следующих режимов:


  • С привилегиями вызывающего пользователя (привилегии CURRENT_USER);
  • С привилегиями определяющего пользователя (владельца объекта метаданных).

Исторически сложилось, что все PSQL модули по умолчанию выполняются с привилегиями вызывающего пользователя. Начиная с Firebird 4.0 появилась возможность указывать объектам метаданных с какими привилегиями они будут выполняться: вызывающего или определяющего пользователя. Для этого используется предложение SQL SECURITY, которое можно указать для таблицы, триггера, процедуры, функции или пакета. Если выбрана опция INVOKER, то объект метаданных будет выполняться с привилегиями вызывающего пользователя. Если выбрана опция DEFINER, то объект метаданных будет выполняться с привилегиями определяющего пользователя (владельца). Эти привилегии будут дополнены привилегиями, выданными самому PSQL модулю оператором GRANT.

CREATE TABLE t (i INTEGER);

SET TERM ^;

CREATE PROCEDURE p (i INTEGER)
SQL SECURITY DEFINER
AS
BEGIN
  INSERT INTO t VALUES (:i);
END^

SET TERM ;^

GRANT EXECUTE ON PROCEDURE p TO USER joe;

COMMIT;

CONNECT 'inet://localhost:test' USER joe PASSWORD 'pas';

EXECUTE PROCEDURE p(1);

В данном случае пользователю JOE достаточно только привилегии EXECUTE на процедуру p. Если бы процедура была создана с привилегиями вызывающего пользователя (опция INVOKER), то ещё потребовалось бы выдать привилегию INSERT для процедуры p на таблицу t.


Встроенные криптографические функции

В Firebird 4.0 добавлено множество встроенные криптографических функций. Вы можете использовать их для шифрования значений отдельных столбцов в таблице или других задач.

select encrypt('897897' using sober128 key 'AbcdAbcdAbcdAbcd' iv '01234567')
from rdb$database;

Поддержка шифрования утилитой gbak

Поддержка шифрования базы данных была введена ещё в Firebird 3.0, однако шифровать/дешифровать файлы резервной копии сделанной утилитой gbak можно было только внешними инструментами. В Firebird 4.0 добавлена поддержка шифрования резервной копии с помощью того же плагина шифрования, что используется при шифровании базы данных.

Пример создания шифрованной резервной копии

gbak -b -keyholder MyKeyHolderPlugin host:dbname backup_file_name

Резервная копия шифруется с помощью того же самого плагина шифрования, с которым зашифрована база данных.

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

gbak -c -keyholder MyKeyHolderPlugin backup_file_name host:dbname

Вы также можете указать плагин шифрования отличный от умолчательного.

© Habrahabr.ru