Допустим, у меня есть следующий psuedocode:
SELECT count(*) FROM users WHERE email = 'bob@gmail.com'
>>>> MARKER A
if (count > 0) return;
else INSERT INTO users VALUES ('bob@gmail.com')
Так что, по сути, вставьте письмо, только если оно еще не существует.Я понимаю, что, возможно, есть какой-то запрос INSERT IF NOT EXISTS, который я мог бы использовать, но, скажем, мы используем этот пример.
Так что, если приведенный выше код выполняется в потоке A, а поток B фактически вставляет 'bob @ gmail.com 'к пользователям на MARKER A, затем поток A имеет «устаревшие данные» и попытается вставить «bob@gmail.com», думая, что счетчик по-прежнему равен 0, но на самом деле это теперь 1. Это приведет к ошибке, так как мыимеют уникальный индекс в электронном письме.
Какой инструмент я должен использовать, чтобы предотвратить эту проблему? Из моего прочтения о транзакциях они в основном делают набор операций атомарным, поэтому кодвыше будет выполнено полностью или не выполнено вообще.Это НЕ гарантирует, что таблица пользователей заблокирована от обновлений правильно?Поэтому я не могу просто обернуть приведенный выше код в транзакцию и сделать его поточно-ориентированным?
Должен ли я реализовать блокировку на уровне приложения?Должен ли я гарантировать, что при выполнении этой операции она должна получить блокировку для доступа к таблице пользователей, чтобы никакой другой поток не мог внести в нее изменения?Я чувствую, что блокировка всей таблицы - это снижение производительности, которого я хочу избежать.