Sql 如何确保系列数据修改操作全部执行?

Sql 如何确保系列数据修改操作全部执行?,sql,transactions,acid,reliability,Sql,Transactions,Acid,Reliability,我有一系列的数据修改操作要做,比如 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执行时,应用程序实例可能会崩溃,而其他两个则会丢失 注意,这是一个分布式环境,可能是另一

我有一系列的数据修改操作要做,比如

 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,但我如何才能做到这一点

我可以使用存储过程吗?应用程序实例只触发存储过程,数据库finsh所有sql


如果在执行事务时,应用程序实例突然崩溃,是否会导致死锁?

死锁不是在执行结束前失败的崩溃请求。如果您的请求在事务中崩溃,则不会导致死锁

使用存储过程总是比较好的,但对于这种特定情况,这并没有帮助

我的建议是使用带有try-catch的事务在失败时回滚事务。 诸如此类:

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

您可以检查更完整的示例

死锁不是在执行结束前失败的崩溃请求。如果您的请求在事务中崩溃,则不会导致死锁

使用存储过程总是比较好的,但对于这种特定情况,这并没有帮助

我的建议是使用带有try-catch的事务在失败时回滚事务。 诸如此类:

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

您可以检查更完整的示例

如果某个应用程序正在数据库服务器上执行事务,并且该应用程序在提交事务之前崩溃(突然与数据库断开连接),则数据库服务器将回滚该事务。断开连接不会使数据库处于不可用(可能死锁)状态

因此,当应用程序在事务期间崩溃时,数据库内容不会反映三种更新操作中的任何一种。它将丢失正在进行的事务

如何处理这种潜在的故障模式

  • 降低事务期间崩溃的概率。尽量避免在你的应用程序中做一些可能会在你的交易过程中使其崩溃的事情。例如,如果您从其他服务器或设备获取数据,请在开始事务之前获取所有数据。此解决方案通常适用于生产应用程序
  • 重新启动应用程序时,为应用程序装配某种方式,以查找最近成功的交易。一个好办法?将这样的列添加到一个表中:(这是MySQL的东西。)
  • 这会导致每列上的每个更新操作自动将
    NOW()
    放入
    last\u UPDATE\u timestamp
    列中。然后,当崩溃的应用程序重新启动时,您可以执行以下操作

    SELECT MAX(last_update_timestamp) FROM table
    
    您将知道最近一次成功更新是何时发生的。如果回滚事务,此自动更新也会回滚。如果您知道上次成功更新发生的时间,您的应用程序可能能够重做因崩溃而回滚的更新


    如果您选择构建重做事务功能,请确保构建它以便可以测试它<代码>如果(testingAppCrash)崩溃=1/0可能会在您的应用程序中起作用。

    如果应用程序正在数据库服务器上执行事务,并且应用程序在提交事务之前崩溃(突然与数据库断开连接),则数据库服务器会回滚该事务。断开连接不会使数据库处于不可用(可能死锁)状态

    因此,当应用程序在事务期间崩溃时,数据库内容不会反映三种更新操作中的任何一种。它将丢失正在进行的事务

    如何处理这种潜在的故障模式

  • 降低事务期间崩溃的概率。尽量避免在你的应用程序中做一些可能会在你的交易过程中使其崩溃的事情。例如,如果您从其他服务器或设备获取数据,请在开始事务之前获取所有数据。此解决方案通常适用于生产应用程序
  • 重新启动应用程序时,为应用程序装配某种方式,以查找最近成功的交易。一个好办法?将这样的列添加到一个表中:(这是MySQL的东西。)
  • 这会导致每列上的每个更新操作自动将
    NOW()
    放入
    last\u UPDATE\u timestamp
    列中。然后,当崩溃的应用程序重新启动时,您可以执行以下操作

    SELECT MAX(last_update_timestamp) FROM table
    
    您将知道最近一次成功更新是何时发生的。如果回滚事务,此自动更新也会回滚。如果您知道上次成功更新发生的时间,您的应用程序可能能够重做因崩溃而回滚的更新


    如果您选择构建重做事务功能,请确保构建它以便可以测试它<代码>如果(testingAppCrash)崩溃=1/0可能会在你的应用程序中起作用。

    我的意思是,当执行一系列sql时,应用程序实例会崩溃而不会遇到异常。我的意思是,当执行一系列sql时,应用程序实例会崩溃而不会遇到异常。