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, а уровень изоляции Многократное чтение
Да, это частично решает проблему. Но что, если some_data не существует? Что произойдет, если SELECT ... FOR UPDATE фактически ничего не возвращает? –
@DeanWinchester: Хорошая точка. Один из вариантов - использовать [named locks] (http://dev.mysql.com/doc/en/miscellaneous-functions.html); другой должен был бы определить соответствующий «UNIQUE» ключ, а затем просто попытаться «INSERT IGNORE» и, если он не сработает, «SELECT» - старые данные - транзакции вообще не требуется. – eggyal
Названный замок кажется идеальным решением для моего дела. Круто! –