2012-05-29 2 views
0

OK вот основная идея о том, что происходит:MySQL одновременно и идентичные операции неприятности

begin transaction 
some_data=select something from some_table where some_condition; 
if some_data does not exists or some_data is outdated 
    new_data = insert a_new_entry to some_table 
    commit transaction 
    return new_data 
else 
    return some_data 
end 

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

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

PS: База данных MySQL, таблица двигатель InnoDB, а уровень изоляции Многократное чтение

ответ

0

В вашей начальной SELECT используйте SELECT ... FOR UPDATE.

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

Обратите внимание, что вам необходимо будет выполнить операцию else, иначе блокировка продолжит блокировку до тех пор, пока соединение не будет сброшено.

+0

Да, это частично решает проблему. Но что, если some_data не существует? Что произойдет, если SELECT ... FOR UPDATE фактически ничего не возвращает? –

+0

@DeanWinchester: Хорошая точка. Один из вариантов - использовать [named locks] (http://dev.mysql.com/doc/en/miscellaneous-functions.html); другой должен был бы определить соответствующий «UNIQUE» ключ, а затем просто попытаться «INSERT IGNORE» и, если он не сработает, «SELECT» - старые данные - транзакции вообще не требуется. – eggyal

+0

Названный замок кажется идеальным решением для моего дела. Круто! –

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