Изоляция транзакций ~~~~~~~~~~~~~~~~~~~ Создаем базу данных и открываем два сеанса | => create database db2; | CREATE DATABASE | => \c db2 | You are now connected to database "db2" as user "postgres". || => \c db2 || You are now connected to database "db2" as user "postgres". 1.Изоляция и системный каталог ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Создаем функцию, возвращающую 1 | => create or replace function f() returns int \ | as $$ select 1; $$ language sql; | CREATE FUNCTION | => select f(); | f | --- | 1 | (1 row) | Во втором сеансе, внутри транзакции меняем функцию || => begin; || BEGIN || => create or replace function f() returns int \ || as $$ select 2; $$ language sql; || CREATE FUNCTION || => select f(); || f || --- || 2 || (1 row) || Не закрывая транзакцию во 2-м сеансе, вызываем функцию в 1-м сеансе | => select f(); | f | --- | 1 | (1 row) | Фиксируем изменения и еще раз смотрим результат || => commit; || COMMIT | => select f(); | f | --- | 2 | (1 row) | Многоверсионность в PostgreSQL распространяется на таблицы системного каталога. В том числе и на pg_proc, где хранится исходный код функций. Поэтому разные транзакции могут видеть и вызывать разные экземпляры одной и той же функции. 2.Момент создания снимка ~~~~~~~~~~~~~~~~~~~~~~~~ | => create table t (id int); | CREATE TABLE Открываем транзакцию, но запросов к БД пока нет | => begin isolation level repeatable read; | BEGIN Во втором сеансе добавляем строку в таблицу || => insert into t values (1); || INSERT 0 1 Проверяем содержимое таблицы в 1-м сеансе | => select * from t; | id | ---- | 1 | (1 row) | | => commit; | COMMIT Первая выполненная команда видит изменения, сделанные после старта транзакции. Это происходит потому, что для REPEATABLE READ и SERIALIZABLE транзакций, снимок данных создается не при открытии транзакции, а при выполнении первого запроса к БД. | => \q || => \q