2014-09-24 4 views
1

Я пытаюсь выяснить, является ли это проблемой изоляции и как я могу ее решить. Предположим, у меня есть база данных с двумя параллельными соединениями:Уровень изоляции транзакций InnoDB в параллельных соединениях

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 
7. TX2 performs INSERT VALUE 10 since TX1 hasn't committed yet 
8. COMMIT TX2 
9. COMMIT TX1 

Текущий уровень изоляции повторяется. Могу ли я решить эту проблему, перейдя на другой уровень изоляции? если да, то это будет? читать uncommitted?

+1

Является ли значение уникальным ключом? Попробуйте «выбрать VALUE FROM TABLE * FOR UPDATE *», чтобы заблокировать результаты, полученные вами по запросу выбора, см. Https://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html. – MrTux

+0

Почему вы используете 2 ссылки? Связаны ли они с отдельными серверами (ведущий/ведомый)? – Jaydee

+0

@MrTux да, значение является уникальным ключом. Поблагодарите. –

ответ

2

Я стараюсь сформулировать свой комментарий как более длинное объяснение. Предпосылки: InnoDB и VALUE имеют уникальный ключ или первичный ключ.

Начиная с примера OPS

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 
7. TX2 performs INSERT VALUE 10 since TX1 hasn't committed yet 
    TX2 will block here until TX1 finishes, if TX1 rolls back this step succeedes, 
    if TX1 commits, you get an error here. 

Для предотвращения этой ситуации использовать FOR UPDATE суффикса для SELECT запроса:

0. BEGIN transaction TX1 
1. TX1 performs SELECT VALUE 10 FOR UPDATE 
2. TX1 performs INSERT VALUE 10 since it does not exist 
3. TX1 performs SELECT VALUE 20 FOR UPDATE 
4. TX1 performs INSERT VALUE 20 since it does not exist 
5. BEGIN transaction TX2 in a different session, using a different connection 
6. TX2 performs SELECT VALUE 10 FOR UPDATE 
    based on the `FOR UPDATE` condition, TX2 will block here until TX1 finishes. 
    If TX1 commits, the result will be the row TX1 committed, if TX1 rolls back, 
    this query returns an empty result. 

Используя FOR UPDATE ключевые слова, вы можете избежать этого TX2 не удается, и всегда использует самые последние данные - он вызывает создание блокировок строк (поэтому, используйте с осторожностью). Однако, будьте в курсе тупиков (Database Deadlock in SELECT FOR UPDATE; всегда «блокировка» в том же порядке)

+0

Несмотря на то, что процесс select/insert существенно замедляется при открытии нескольких подключений (с использованием ~ 20 клиентских подключений), он устраняет проблему. Любые альтернативы этому? Благодарю. –

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