Как имитировать отказ базы данных для проверки двухфазной фиксации в Java

Я выполняю двухфазную фиксацию с использованием распределенных ресурсов. Как я могу имитировать неудачу участвующей базы данных? Вытягивание сетевого кабеля не работает, поскольку вызывает тупик в таблице. В настоящее время я использую крючки в коде приложения, которые бросают StaleConnectionException в разных точках, как до выполнения запроса, после выполнения запроса. Моя озабоченность этим подходом заключается в следующем:

  • Есть ли лучший способ имитировать отказ БД?
  • Что происходит с объектом соединения, когда соединение с БД происходит плохо? Сохраняет ли это значение или становится нулевым?
  • Что на самом деле происходит, когда приложение пытается подключиться к БД? Какое значение получает объект подключения? Использует ли оно существующее значение из пула соединений?

Я также хотел бы протестировать в промежуточных точках, например, во время выполнения запроса, во время фиксации (после отправки отправки и т.д.). Прямо сейчас я помещаю приложение в режим отладки и вступаю в вызов функции и вытаскиваю штепсель между ними. Но этот подход является ручным и не будет работать для тестирования весов.

Есть ли симулятор/эмулятор или инструмент, который может мне помочь?

Ответ 1

Это много вопросов:) Я постараюсь завершить предыдущие ответы.

Is there a better way to simulate the DB failure?

Тестирование всех случаев сложно. Один из способов проверить основные случаи - создать разъем JCA (драйвер DB - это разъем JCA). Вы можете получить соединения от соединителя, который будет зачислен в транзакцию (третий участник). Затем соединение может вызвать определенные ошибки.

Есть три части, которые работают вместе: (1) приложение, (2) приложение. серверный менеджер транзакций и (3) разъем jca (так называемый адаптер ресурсов).

Communications between the three parts

Соединение подключается к транзакции через ManagedConnection.getXAResource. С помощью специального jca-коннектора вы можете затем добавить исключение в приложение (Connection в picutre) или диспетчер транзакций сервера приложений (XAResource, полученный с помощью ManagedConnection на картинке). Вы можете явно исключить исключение во время XAResource.prepare и XAResource.commit, что соответствует ошибкам во время фиксации 2 фазы.

Обратите внимание, что трудно контролировать порядок привлечения участников (см. этот вопрос). Поэтому легко проверить, что один из prepare терпит неудачу (а именно ваш), но трудно контролировать порядок, в котором они вызываются. Воспроизведение всех возможных недопустимых состояний 2-х фазовой фиксации затруднено, особенно при оптимизации в игре.

(Я написал один раз разъем JCA (http://code.google.com/p/txfs), и есть другие, если вы хотите использовать пример кода.)

What happens to the connection object when DB connection goes bad? 
Does it retain its value or does it become null?

ManagedConnection может уведомить менеджера транзакций. Одним из уведомлений является ConnectionEvent.CONNECTION_ERROR_OCCURRED, который сообщает, что при использовании этого конкретного соединения произошла ошибка.

Как отмечено в другом ответе, обычно для каждого транзакции связано одно управляемое соединение. Управляемое соединение абстрагирует физическое соединение, и вы не хотите использовать слишком много. Приложение получает только "дескрипторы" (Connection на картинке). Ручки, полученные в рамках одной транзакции, указывают на одно и то же управляемое соединение. Это оптимизация, поддерживаемая большинством серверов приложений.

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

What actually happens when application tries to reconnect to DB?
What value does connection object get?
Does it use an existing value from the connection pool?

Сервер приложений управляет пулом управляемого соединения. Как сказано в предыдущем параграфе, во время использования он может испортиться. Но можно также пойти плохо, если не использовать. Например, используемое управляемое соединение в пуле может стать недействительным, так как физическое время ожидания физического подключения истечет. Серверы приложений обычно имеют функцию проверки правильности управляемого соединения, прежде чем он начнет ее использовать. Если нет, он попробует другое управляемое соединение из пула или создаст новый.

Ответ 2

Возможно, вы можете добавить свой собственный ресурс, который будет участвовать в фиксации, и приостановит транзакцию после первой фазы. Тем временем вы можете "вытащить вилку".

Ответ 3

Андрей ответил на одну часть вопроса, поэтому позвольте мне ответить на вторую часть.

Объект Connection, который вы получаете в своем приложении, является только оболочкой вокруг физического соединения. Эта оболочка играет роль в объединении пула и управлении транзакциями. Если что-то пойдет не так с БД, оболочка соединения станет непригодной, и вы можете только откатить. Это имеет смысл, потому что вы получаете доступ к соединению только до запуска 2PC, и все, что было сделано до начала 2PC, не может быть восстановлено.

Обратите внимание, что попытка освободить соединение и приобрести новый не изменит ничего, потому что, как только соединение из данного источника данных использовалось в транзакции, вы всегда будете получать одно и то же соединение от этого источника данных, пока вы находитесь в одной транзакции. Это означает, что ваше приложение не может "повторно подключиться", не перезагружая всю транзакцию.

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

Ответ 4

Лучше всего использовать его в базах памяти. Вызовите отказ и проверьте состояние источников данных до и после, чтобы обеспечить надлежащее выполнение отката/фиксации.

Что касается ваших других проблем, то они кажутся чрезвычайно высокими затратами/низкими наградами. Прочтите документацию поставщиков и убедитесь, что среда транзакций настроена соответствующим образом. Одно это делается, вы, вероятно, должны автоматизировать его, чтобы его руки были отключены.

Если вы не написали свой собственный менеджер транзакций 2PC для протокола + DB, я бы оставил тестирование этих функций вашим поставщиком.