Обеспечение целостности данных при доступе к базе данных несколькими клиентами Java
У меня есть один экземпляр базы данных MySql с таблицей Account, которая поддерживает поле Balance. У меня есть несколько Java-приложений, каждое из которых использует Jdbc для подключения к базе данных, что потенциально может увеличить или уменьшить значение поля Balance. Как мне убедиться, что значение Balance прочитано, рассчитано и обновлено, и что этот процесс происходит изолированно и "осведомлен" о любых других процессах Java, которые могут выполнять то же самое?
3 ответа
Простой ответ - использовать транзакции: http://dev.mysql.com/doc/refman/5.0/en/commit.html
Однако в описываемом вами случае я предпочитаю не сохранять остаток на счете в виде столбца в таблице, а рассчитывать его путем суммирования стоимости транзакций, связанных с этим счетом. Он гораздо менее чувствителен к проблемам целостности, которые вы поднимаете, и у вас меньше шансов столкнуться с непонятными сценариями блокировки.
Одним из простых подходов является управление транзакциями JDBC. Увидеть java.sql.Connection.setAutoCommit()
документация. Это позволяет вам явно отключить автоматическую фиксацию операторов:
Connection c = /* retrieve connection */
c.setAutoCommit(false);
c.setTransactionIsolation(/* depends on your requirements */);
c.executeQuery(/* */);
c.executeUpdate(/* */);
c.commit(); /* or c.rollback() */
В реальном сценарии вы должны ввести finally
блокировать для фиксации или отката транзакции, в противном случае вы можете получить тупики в вашей базе данных.
Редактировать: если ваши Java-приложения являются клиентами конечных пользователей, вы всегда рискуете, чтобы пользователи напрямую подключались к базе данных (например, используя Access), минуя логику управления транзакциями. Это одна из причин, по которой мы начали размещать серверы приложений между ними. Решением также может быть реализация хранимой процедуры, чтобы клиенты вообще не взаимодействовали с таблицами.
Если вы используете движок InnoDB, то вы можете использовать блокировку уровня записи MySQL, чтобы заблокировать конкретную запись учетной записи для обновлений от других клиентов.
ОБНОВЛЕНИЕ: Альтернативно вы можете блокировки уровня приложения, описанные здесь.