所以我用这段代码进行了测试:
MySqlTransaction trans = null;
var con = new MySqlConnection(DBInfo.CON_STRING);
try
{
con.Open();
trans = con.BeginTransaction();
var query = "INSERT INTO test (num) VALUE (@val1)";
var cmd = new MySqlCommand(query, con);
cmd.Transaction = trans;
cmd.Prepare();
cmd.Parameters.AddWithValue("@val1", 0);
for (int i = 0; i <= 15; i++)
{
cmd.Parameters["@val1"].Value = i;
cmd.ExecuteNonQuery();
if (i == 10)
{
//throw new DivideByZeroException();
MessageBox.Show("pause");
}
}
trans.Commit();
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
try
{
if (trans != null) trans.Rollback();
}
catch (Exception ex1)
{
MessageBox.Show(ex1.Message);
}
}
finally
{
con.Close();
}
提交和回滚方法。我有个问题。在for
块中,我有一个MessageBox来暂停代码的执行,这样我就可以停止程序来模拟程序的突然执行。问题是查询没有提交,但是服务器发生了什么?是否自动回滚?如果运行程序的PC恰好是服务器并且停电了,会发生什么?(假设断电发生在执行for
块的中间。
3条答案
按热度按时间hfyxw5xn1#
当数据库服务器在断电后重新启动时,它将恢复到仅包含已提交工作的干净状态。
当数据库客户端在事务执行过程中中断时,服务器将通过回滚事务来自动清理事务。
3lxsmp7m2#
这是一个非常好的问题。MySQL是ACID compliant。ACID遵从性的字面用例是“如果我们在事务期间拔出插头会发生什么”。本质上,它归结为每个操作都是原子的,这意味着它要么完成,要么不完成。如果没有,那么保证保存该事务之前的数据库状态,您可以在那里继续。如果它完成了,那么您可以确保,如果您的下一个操作失败,您的当前状态将被保存。
有趣的事实:NoSQL数据库MongoDB的主要警告之一是它不符合ACID。因此,如果你有一个更新多个set的事务,并且你拔出电源插座,那么你的数据库的状态是不确定的(有些可能已经保存,有些可能没有)。
请让我知道如果你有任何问题!
pxq42qpu3#
当您启动一个事务时,数据库命令实际上并不更改数据库本身,而是维护用户请求的更改列表。有很多机制可以使这项工作明显透明,但更改存储在日志中。当你执行一个提交时,它会将所有这些事务写入数据库的一个块中,所以所有的更改都是同时进行的。如果您执行回滚,或者您什么都不做(就像停电的情况一样),那么事务日志将被删除,就好像您从未执行过这些命令一样。
在日志中延迟和原子提交(意味着它们都在一次保存,没有人,没有另一个线程或另一个进程介入)可能会导致一些奇怪的事情。
例如,如果您有两个到数据库的连接,并执行以下操作:
1.打开两个单独的连接:connection1和connection2
1.在连接1上开始事务
1.使用连接1将数据行R插入表T
1.使用连接2,在表T中查找,您将找不到行R
1.在connection1上提交事务
1.现在使用连接2,查看表T,您现在将找到行R。
这是绝对正确的行为。在第4点,数据仍在connection1的事务日志中,尚未写入数据库表,因此在连接2上不可见。只有当connection1的事务日志提交到数据库时,它才能在连接2上可见。