Как реализуется lock на уровне JDBC и транзакций
Что проверяют
Понимаете ли вы, что блокировки ставит база, а JDBC лишь управляет границами транзакции и уровнем изоляции. Следом обычно спрашивают, чем пессимистическая блокировка отличается от оптимистической и что делать при дедлоке.
Как отвечать
Транзакция в JDBC держится на трёх вещах:
setAutoCommit(false): без этого каждый запрос сам себе транзакция, и любая блокировка снимается сразу после него;commit()иrollback(): откат вcatch, соединение через try-with-resources, чтобы в пул оно вернулось в чистом состоянии;setTransactionIsolation:TRANSACTION_READ_COMMITTED,TRANSACTION_REPEATABLE_READ,TRANSACTION_SERIALIZABLE. По умолчанию в PostgreSQL это Read Committed, в MySQL InnoDB Repeatable Read.
Пессимистическая блокировка: SELECT ... FOR UPDATE держит выбранные строки до конца транзакции. Есть NOWAIT (сразу ошибка) и SKIP LOCKED (пропустить занятые строки, удобно для очередей задач). Ожидание ограничивают Statement.setQueryTimeout или настройкой базы, в PostgreSQL это lock_timeout.
Оптимистическая блокировка: колонка version и UPDATE ... SET version = version + 1 WHERE id = ? AND version = ?. Если executeUpdate() вернул 0, запись уже изменил кто-то другой, и вы повторяете операцию или отдаёте конфликт. В JPA это @Version и OptimisticLockException, пессимистический вариант LockModeType.PESSIMISTIC_WRITE. В Spring границы задаёт @Transactional, соединение привязано к потоку.
Дедлок база находит сама и откатывает одну из транзакций, в PostgreSQL это SQLState 40P01. Приложение должно уметь повторить транзакцию целиком, а вероятность дедлока снижает единый порядок захвата строк.
Где спотыкаются
Делают FOR UPDATE при включённом автокоммите и уверены, что строка заблокирована. Блокировка живёт ровно один запрос.
Заменяют блокировку в базе на synchronized или ReentrantLock. При двух экземплярах приложения это не защищает ни от чего.
Держат транзакцию с блокировкой открытой во время HTTP-вызова во внешний сервис. Строки висят заблокированными секундами, и очередь ожидающих растёт.