Как я могу обеспечить выполнение всех операций изменения данных серии? - PullRequest
1 голос
/ 07 мая 2020

Мне нужно выполнить операцию изменения серийных данных, например

 1. update table_a set value=1 where id=1 
 2. update table_b set value=2 where id=1 
 3. update table_c set value=3 where id=1

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

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

Могу ли я использовать хранимую процедуру, экземпляр приложения запускает только хранимую процедуру, а база данных fin sh все sql?

Если при выполнении транзакции экземпляр приложения внезапно выйдет из строя, приведет ли это к мертвой блокировке?

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

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

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

Как справиться с этим потенциальным режимом сбоя?

  1. Уменьшите вероятность ошибки sh во время транзакции. Старайтесь не делать в своем приложении вещей, которые могут сделать его sh в процессе обработки транзакции. Например, если вы получаете данные с какого-то другого сервера или устройства, получите их все до того, как начнете транзакцию. Этого решения обычно достаточно для производственных приложений.
  2. Создайте для своего приложения какой-то способ после перезапуска, чтобы узнать о последней успешной транзакции. Один хороший способ? Добавьте такой столбец в одну из ваших таблиц: (это MySQL).
last_update_timestamp TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,

Это приводит к тому, что каждая операция UPDATE в каждом столбце автоматически ставит NOW() в столбец last_update_timestamp. Затем, когда ваше аварийное приложение перезапустится, вы можете сделать

SELECT MAX(last_update_timestamp) FROM table

, и вы узнаете, когда произошло самое последнее успешное обновление. Это автоматическое c обновление также откатывается при откате транзакции. Если вы знаете, когда произошло последнее успешное обновление, ваше приложение может повторить то, которое было откатано Cra sh.

Если вы решите создать возможность повторной транзакции, обязательно создайте его, чтобы вы могли его протестировать! if (testingAppCrash) crashNow = 1 / 0; может помочь в вашем приложении.

0 голосов
/ 07 мая 2020

Тупиковые ситуации - это не сбойные запросы, которые не выполняются до конца выполнения. Если ваш запрос вылетает из транзакции, это не приведет к тупиковой ситуации.

Всегда лучше использовать хранимые процедуры, но это не поможет вам в данном случае c.

Я бы предложил использовать транзакцию с уловкой попытки для отката транзакции в случае неудачи. Примерно так:

BEGIN TRY -- start of try
BEGIN TRANSACTION; -- start of transaction
    update table_a set value=1 where id=1 
    update table_b set value=2 where id=1
    update table_c set value=3 where id=1
COMMIT TRANSACTION; -- everything went ok we commit
BEGIN CATCH -- an error happened we rollback
    PRINT  N'Unexpected error';
    ROLLBACK TRANSACTION;
END CATCH

Более полные примеры можно посмотреть здесь

...