2013-05-14 2 views
19

Предполагая:Может ли операция INSERT привести к взаимоблокировке?

  • Я использую REPEATABLE_READ или SERIALIZABLE изоляции транзакций (замки получить сохраняются каждый раз, когда я получить доступ к ряду)
  • Мы говорим о нескольких потоках доступа к нескольким таблицам одновременно.

У меня есть следующие вопросы:

  1. ли возможно для INSERT операции, чтобы вызвать затор? Если да, предоставьте подробный сценарий, демонстрирующий, как может возникнуть взаимоблокировка (например, Thread 1 делает это, Thread 2 делает это, ..., deadlock).
  2. Для бонусных очков: ответьте на один и тот же вопрос для всех других операций (например, SELECT, UPDATE, DELETE).

UPDATE: 3. Для супер бонусных очков: как я могу избежать тупиковой ситуации в следующем сценарии?

Данные таблицы:

  • разрешений [id BIGINT PRIMARY KEY]
  • компании [id BIGINT PRIMARY KEY, name VARCHAR(30), permission_id BIGINT NOT NULL, FOREIGN KEY (permission_id) REFERENCES permissions(id))

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

  • INSERT INTO разрешений; - Вставляет permissions.id = 100
  • INSERT INTO компании (имя, permission_id) VALUES ('Nintendo', 100); - Вставки companies.id = 200

удалить компанию следующим образом:

  • ВЫБРАТЬ permission_id ОТ компаний WHERE ID = 200; - возвращает permission_id = 100
  • УДАЛИТЬ ОТ компаний WHERE id = 200;
  • УДАЛИТЬ ОТ разрешений WHERE id = 100;

В приведенном выше примере порядок блокировки INSERT является [разрешениями, компаниями], тогда как порядок блокировки DELETE - [компании, разрешения]. Есть ли способ исправить этот пример для изоляции REPEATABLE_READ или SERIALIZABLE?

+0

Сценарий определяется как одного пользователя (в одной транзакции) вставка, выбор и удаление не будет вызывать тупик. –

+0

@CleverIdeaWidgetry, я уточнил вопрос, чтобы отразить тот факт, что мы говорим о нескольких потоках и таблицах. – Gili

+0

Ответ на ваш основной вопрос «не так ли?» да, как говорили другие. Есть ли какое-то препятствие, препятствующее вам самому тестировать свой сценарий? –

ответ

22

Как правило, все модификации могут вызывать блокировку и выбор не будет (дойти до этого). Таким образом,

  1. Нет, вы не можете игнорировать их.
  2. Вы можете несколько игнорировать выбор в зависимости от вашей базы данных и настроек, но другие будут давать вам взаимоблокировки.

Вам даже не нужны несколько таблиц.

Лучший способ создать тупик - это сделать то же самое в другом порядке.

примеры сервера SQL:

create table A 
(
    PK int primary key 
) 

Сессия 1:

begin transaction 
insert into A values(1) 

Сессия 2:

begin transaction  
insert into A values(7) 

Сессия 1:

delete from A where PK=7 

Сессия 2:

delete from A where PK=1 

вы получите в тупик. Так что доказанные вставки & удаляет может тупик.

обновления похожи:

Сессия 1:

begin transaction  
insert into A values(1) 
insert into A values(2) 
commit 

begin transaction 
update A set PK=7 where PK=1 

Сессия 2:

begin transaction 
update A set pk=9 where pk=2  
update A set pk=8 where pk=1 

Сессия 1:

update A set pk=9 where pk=2 

Тупик!

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

SQL Server не будет блокировать SELECT, если вы используете SNAPSHOT ISOLATION. Oracle & Я думаю, Postgres никогда не будет блокировать SELECT (если у вас нет FOR UPDATE, который явно резервирует для обновления в любом случае).

Итак, в основном, я думаю, у вас есть несколько неправильных предположений.Я думаю, что я доказал:

  1. обновление может привести к тупикам
  2. Удаление может вызвать ТУПИКИ
  3. Вставка может вызвать тупики
  4. Вам не нужен больше, чем одну таблицы
  5. Вы сделать необходимости более одного сеанса

Вам просто нужно взять слово на SELECT;), но это будет зависеть от y нашей базы данных и настроек.

+0

Во-первых, благодарю вас за то, что вы порядочно ответили на вопрос правильно. Во-вторых, я добавил третий вопрос для вашего обзора. См. Обновленный вопрос. – Gili

+0

Это не похоже, что это сработает. Вы не можете удалить разрешение перед компанией, так как оно решено FK. – LoztInSpace

+0

Я исправил вопрос №3. Пожалуйста, попробуйте еще раз. – Gili

0

Предположим, у вас есть два отношения A и B и два пользователя X и Y. Таблица А WRITE Locked пользователя X и таблица B ЗАПИСИ Заблокировано Y. Тогда следующий запрос даст вам мертвую блокировку, если они используются как для пользователей X и Y.

Select * from A,B 

Так ясно Select операция может вызывают тупик, если в нем участвуют операции объединения с несколькими таблицами. Обычно операции «Вставка» и «Удалить» связаны с отдельными отношениями. Поэтому они не могут вызывать тупиков.

+0

Предположим, что все операции включают в себя несколько таблиц (как показано в примере), потому что ясно, что вы не можете получить взаимоблокировки, не делая этого. С этой целью, какие операции могут вызвать взаимоблокировки, а какие нет. Пока вы продемонстрировали, как «SELECT» ** может вызывать взаимоблокировки. Давайте обсудим все остальное. – Gili

+0

Если есть ограничение внешнего ключа между отношениями A и B, A и B блокируются пользователями X и Y соответственно, тогда вы можете получить тупик. – Deepu

+0

Вы не ответили на мой вопрос. Я спрашиваю о ** всех ** операциях SQL, а не просто 'SELECT'. Меня больше интересует 'INSERT', но я ожидаю, что вы также обсудите все другие типы операций. – Gili

1

В дополнение к ответу LoztInSpace, inserts может вызвать взаимоблокировки даже без deletes или updates. Все, что вам нужно, это уникальный индекс и порядок операций с обратными операциями.

Пример в Oracle:

create table t1 (id number); 
create unique index t1_pk on t1 (id); 

--thread 1 : 
insert into t1 values(1); 
--thread 2 
insert into t1 values(2); 
--thread 1 : 
insert into t1 values(2); 
--thread 2 
insert into t1 values(1); -- deadlock ! 
+0

А какое решение? – Akvel

+1

Я думаю, что самым простым (но не всегда возможным) решением было бы сортировать строки перед вставкой. –

+0

Почему это приведет к тупиковой ситуации, а не к ограничению ограничений и откату в потоке 2? –

Смежные вопросы