Проблема возникает из-за условия гонки в логике.А именно, две одновременные транзакции, сделанные разными пользователями, могут успешно выполнить проверку на этапе a
и попытаться вставить в LOCK_FILE_INFO
.Очевидно, что только один успешен, а второй потерпит неудачу.
Когда изменяется степень параллелизма (когда изменяется количество одновременно запущенных процессов), также меняются сроки отдельных событий, происходящих в запущенном процессе (ах).Таким образом, поведение таких параллельных сценариев может отличаться.
У вас есть несколько вариантов решения проблемы, с которой вы столкнулись.
Обработка нарушения первичного ключа
Вы можете поймать исключениеи показать сообщение, что файл уже заблокирован.В этом случае не имеет смысла проверять, существует ли запись блокировки.То есть вам не нужно выполнять шаг a
.Просто вставьте запись блокировки, и если есть нарушение первичного ключа - блокировка уже есть.
Блокировка с обновлением
Проблема с блокировкой с использованием вставки заключается в том, что единственная причина для обнаружения конфликта заключается в ограничениинарушение.Если вы измените стратегию блокировки, чтобы вместо нее обновить запись.
Сначала либо всегда создайте запись для файла в LOCK_FILE_INFO
при создании записи в FILE_INFO
, либо сохраните информацию о блокировке в FILE_INFO
таблица (timeOfLock
столбца должно быть достаточно, если NULL
файл не заблокирован).
Если вам нужно заблокировать, просто выполните запрос на обновление
update LOCK_FILE_INFO
set TimeOfLock = now()
where TimeOfLock is NULL
AND FILEID = some_id
Затемвам нужно проверить, была ли запись обновлена.Количество обновленных записей возвращается каждым оператором модификации.Чтобы получить это число, просто верните int
из метода вставки в mybatis mapper.Если запись была обновлена, то эта транзакция успешно получила блокировку, иначе блокировка файла не может быть получена (либо она уже заблокирована, либо файл был удален, см. Ниже).
Обратите внимание, что это зависит от того факта, что some_id
является правильным идентификатором файла.Может случиться, что файл был удален непосредственно перед выполнением оператора обновления.В этом случае это выглядит так, как будто файл заблокирован, но на самом деле его уже нет.На практике это не проблема, так как после неудачной блокировки вам обычно нужно обновить пользовательский интерфейс, чтобы отобразить обновленное состояние файла, и в этом случае вы обнаружите, что файл пропал.
Параметры, которые не работают
Синхронизация через синхронизированный
Синхронизация с использованием ключевого слова synchronized
(если все сделано правильно) будет полезна только для одного случая процесса, потому что в этом случае синхронизация выполняется с использованием внутренней блокировки процесса.Если есть несколько процессов JVM, каждый из них будет иметь свою собственную блокировку, и синхронизация не будет работать должным образом.
Сериализованный уровень изоляции
Сериализованный уровень изоляции будет работать в этом случае, потому что он не может помочь со вставками,Если вы вставите две записи с одним и тем же ключом в две транзакции, вы получите одно и то же нарушение первичного ключа независимо от уровня изоляции.