Будет ли транзакция видеть вставки из другой параллельной транзакции, если они находятся на уровне изоляции Repeatable Read в Postgresql?

[Д2] 1. ОПРЕДЕЛЕНИЕ ПРОБЛЕМЫ РАСПРЕДЕЛЕНИЯ

Если D - производный класс базового класса B, то вы можете назначить объект типа Derived переменной (или параметру) типа Base.

ПРИМЕР

class Pet
{
 public:
    string name;
};
class Dog : public Pet
{
public:
    string breed;
};

int main()
{   
    Dog dog;
    Pet pet;

    dog.name = "Tommy";
    dog.breed = "Kangal Dog";
    pet = dog;
    cout << pet.breed; //ERROR

Хотя указанное назначение разрешено, значение, присвоенное переменной pet, теряет поле породы. Это называется проблемой нарезки.

2. КАК ИЗМЕНИТЬ ПРОБЛЕМУ СЦЕПЛЕНИЯ

Чтобы устранить проблему, мы используем указатели на динамические переменные.

ПРИМЕР

Pet *ptrP;
Dog *ptrD;
ptrD = new Dog;         
ptrD->name = "Tommy";
ptrD->breed = "Kangal Dog";
ptrP = ptrD;
cout << ((Dog *)ptrP)->breed; 

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

2
задан netok 24 March 2019 в 10:55
поделиться

1 ответ

Транзакция A не завершится неудачей . Он не увидит данные, вставленные транзакцией B .

Демонстрация:

create table accounts (id bigserial primary key, balance bigint);
insert into accounts(balance) values (50), (100), (200);

Транзакция A :

begin transaction isolation level repeatable read;

select * from accounts where balance >= 100;
 id | balance 
----+---------
  2 |     100
  3 |     200
(2 rows)

Транзакция B :

begin;
insert into accounts(balance) values (300);
INSERT 0 1
commit;

Транзакция A :

select * from accounts where balance >= 100;
 id | balance 
----+---------
  2 |     100
  3 |     200
(2 rows)

Нет (4, 300) строки.

(протестировано на PostgreSQL 11.2)

Обратите внимание, что PostgreSQL имеет более строгие гарантии на REPEATABLE READ уровне изоляции. Это предотвращает фантомное чтение .

Из документации :

Уровень изоляции повторяемого чтения только видит данные, зафиксированные до начала транзакции; он никогда не видит ни незафиксированные данные, ни изменения, зафиксированные во время выполнения транзакций параллельными транзакциями (Тем не менее, запрос видит результаты предыдущих обновлений, выполненных в его собственной транзакции, даже если они еще не зафиксированы.) Это более надежная гарантия, чем требуется стандартом SQL для этого уровня изоляции [ 1132]

Из таблицы 13.1. Уровни изоляции транзакции :

Фантомное чтение разрешено , разрешено на REPEATABLE READ уровне изоляции , но не в PG

См. Также :

Обновление

Если утверждение [ 1137]

update accounts set balance = balance + 30 where balance >= 100;

выдается как последний оператор транзакции A будут обновлены только 2 строки, потому что с точки зрения транзакции A есть только две строки, удовлетворяющие предикат balance >= 100:

update accounts set balance = balance + 30 where balance >= 100;
UPDATE 2

После фиксации:

commit;
COMMIT
select * from accounts;
 id | balance 
----+---------
  1 |      50
  4 |     300
  2 |     130
  3 |     230
(4 rows)

Обновляются только строки, возвращаемые этим оператором

select * from accounts where balance >= 100;

(исключая вставленную строку по транзакции B )

Обратите внимание, что транзакция A завершится с ошибкой , если попытается update изменить строку с помощью другой зафиксированной параллельной транзакции:

A

begin transaction isolation level repeatable read;
BEGIN
select * from accounts where id = 1;
 id | balance 
----+---------
  1 |      50
(1 row)

B

begin;
BEGIN
update accounts set balance = balance + 10;
UPDATE 3
commit;

A :

[ 1110]

Ошибка ожидается. Из документации:

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

ERROR: could not serialize access due to concurrent update потому что повторяемая транзакция чтения не может изменять или блокировать строки, измененные другими транзакциями после начала повторяемой транзакции чтения.

Ожидается, что приложения будут повторять неудачные транзакции:

Когда приложение получает это сообщение об ошибке, оно должно прервать текущую транзакцию и повторить всю транзакцию с самого начала. [ 1150]

0
ответ дан caco3 24 March 2019 в 10:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: