2017-01-11 2 views
0

Я создал кластер mariadb, и я пытаюсь заставить приложение Java иметь возможность перехода на другой компьютер, когда один из них умирает.Использование galera mariadb с jdbc

Я создал приложение, которое создает соединение с "jdbc:mysql:sequential://host1,host2,host3/database?socketTimeout=2000&autoReconnect=true". Приложение делает запрос в цикле каждую секунду. Если я убью узел, в котором приложение выполняет запрос (Statement.executeQuery()), я получаю SQLException из-за таймаута. Я могу поймать исключение и повторно выполнить оператор, и я вижу, что запрос отправляется на другой сервер, поэтому переход на другой ресурс в этом случае работает нормально. Но я ожидал, что execQuery() не будет генерировать исключение и тихо повторить попытку другого сервера автоматически.

Я ошибаюсь, полагая, что мне не нужно обрабатывать исключение и явно повторять запрос? Есть ли что-то еще, что мне нужно для настройки, чтобы это произошло?

ответ

2

Это опасно для автоматического повторного подключения по следующей причине. Предположим, у вас есть этот код:

BEGIN; 
SELECT ... FROM tbl WHERE ... FOR UPDATE; 
(line 3) 
UPDATE tbl ... WHERE ...; 
COMMIT; 

Теперь предположим, что сервер аварийно завершает работу (строка 3). Сделка будет отменена. В моем сфабрикованном примере это включает только освобождение блокировки на tbl.

Теперь предположим, что какое-либо другое соединение удастся выполнить ту же транзакцию в строке той же строки, пока вы автоматически подключаетесь.

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

Вам нужно получить исключение, чтобы вы могли вернуться к BEGIN, чтобы вы могли быть «безопасным транзакцией».

Вам все равно нужно - с Galera и нет аварий, похоже, что может случиться. Два потока, выполняющие эту транзакцию на двух разных узлах в , равны времени ... Каждый преуспевает до тех пор, пока не дойдет до COMMIT, после чего произойдет магизация Galera, и один из COMMITs будет терпеть неудачу. «Правильный» ответ воспроизводит всю транзакцию на сервере, которая была выбрана для отказа.

Обратите внимание, что Galera, в отличие от не-Galera, требует проверки ошибок на COMMIT.

Более Galera tips (с целью дэвов и АБДА мигрирующих из неживой Галеры)

+0

Спасибо. Я не знал об этом. Хотя эта информация очень полезна для меня, она не полностью отвечает на мой вопрос. Знаете ли вы, возможно ли повторное подключение драйвера к сбоям во время запроса (в отличие от генерирования исключения, а затем для повторного подключения). У меня есть очень простые запросы, поэтому я думаю, что могу рискнуть. Но ваш ответ определенно будет полезен мне в будущем. – ps197xv

+0

Извините, я мало знаю о соединителе Java. –

0

отказоустойчивые не означает, что приложение не обрабатывать исключения.

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

Если драйвер не подключится к другому серверу, будет выведено исключение SQLNonTransientConnectionException, пулы автоматически отбросят это соединение.

Если соединение восстановлено, есть случаи, когда перезапуск запроса безопасен: когда запрос не находится в транзакции, а соединение в настоящее время находится в read-only mode (например, с использованием Spring @Transactional (readOnly = false)). Для случаев thoses, соединение Java-соединения MariaDb автоматически перезапустит запрос. В этих конкретных случаях исключение не будет выбрано, а переход на другой ресурс прозрачен.

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

Затем драйвер отправит SQLException (с SQLState, начинающимся с «25» = INVALID_TRANSACTION_STATE), и дело касается приложения для обработки этих случаев.