ВЫБРАТЬ ДЛЯ ОБНОВЛЕНИЯ проблемы в приложении Spring JDB C - PullRequest
0 голосов
/ 26 января 2020

Я использую оператор SELECT ... FOR UPDATE для достижения блокировки на уровне строк в моем приложении SpringBoot. База данных: MySQL 5.7.28, коннектор - MariaDb java клиент 2.5.2, пул соединений HikariCP 2.7.9, версия с весенней загрузкой - выпуск 2.0.3.

Постоянство обеспечивается Spring JDB C Шаблон не по JPA. Я использую управление Spring Transaction, основанное на аннотациях путем добавления аннотации @Transactional к моим методам DAO. Транзакционные прокси генерируются путём компоновки во время компиляции AspectJ (@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)). Я уверен, что менеджер транзакций настроен правильно.

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

Теперь тесты работают в 95% случаев, однако есть один тест, который не выполняется, когда выполняется определенная последовательность IT.

Я уверен, что при сбое теста блокировка строки не налагается.

Я включил журнал запросов MySql на сервере, чтобы помочь с устранением неполадок.

Вот что я вижу, когда Первый поток выполняет оператор SELECT ... FOR UPDATE:

2020-01-26T12:54:06.681319Z  1219 Query set autocommit=0
2020-01-26T12:54:36.616097Z  1209 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19qix6lvsfx') FOR UPDATE

Кажется, что автоматическая фиксация установлена ​​на неправильном объекте соединения. Я правильно прочитал? Что это за цифры 1219 и 1209?

Когда все работает правильно, журнал выглядит так:

2020-01-26T13:24:22.940787Z  1243 Query set autocommit=0
2020-01-26T13:24:36.515016Z  1243 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19xbs7vv53r') FOR UPDATE

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 02 февраля 2020

Мне не нравится autocommit=0, потому что в конечном итоге я могу забыть COMMIT.

SELECT ... FOR UPDATE применяется только в том случае, если вы находитесь в транзакции (autocommit = 0 означает, что вы всегда в транзакции).

Ваш фрагмент общего журнала подразумевает, что все соединения устанавливают это значение, возможно, многократно. Нет, на каждое соединение не влияют настройки для других соединений.

Видите ли вы какие-либо COMMIT в журнале? Вы когда-нибудь выпускали ROLLBACK?

...