【问题标题】:Dot NET and SQL Server 2005 TransactionDot NET 和 SQL Server 2005 事务
【发布时间】:2009-07-20 19:28:50
【问题描述】:

在我必须向表 A 中插入一条记录,并且表中的一个字段引用另一个表 B 中的记录的情况下。我如何确保在我提交插入语句之前,该记录在表A引用的表B,插入表A的记录未被篡改。

我正在考虑将这两个表都包含在一个事务中并锁定该事务中涉及的所有记录。但这可能会导致并发不足。所以需要你的推荐。

谢谢,

【问题讨论】:

  • 代码为王,能否提供快速详细的示例,它是为您提供正确解决方案的关键。如果您需要首先检查数据是否存在,则需要使用不同的模式。

标签: c# transactions


【解决方案1】:

请注意,即使有事务,您也需要正确设置隔离级别。最偏执(因此也是最准确的)是“可序列化”,它会在您读取数据时取出锁(甚至是范围锁),这样其他 spid 就无法使用它。

【讨论】:

  • +1 用于提及可序列化,恕我直言,这是回答 OPs 问题的关键。可序列化会带来大量死锁,因此必须明智地使用它
【解决方案2】:

如果您想让对两个表的更改成为单个原子操作,那么它们应该在单个事务中执行。它在.net 中相对简单,您只需要在 SqlConnection 上使用 BeginTransaction 方法来创建一个新事务,然后让您的 SqlCommands 等针对事务而不是连接工作。您也可以使用 TransactionScope 执行此操作,但您可能会遇到 MSDTC 问题。

我不会担心有关使用事务的并发问题。我会回避尝试自己处理锁定问题,我会从原子更新和维护数据完整性开始。

【讨论】:

  • “我不会担心使用事务的并发问题。”我不确定这是不是很好的建议
【解决方案3】:

您不需要为此进行交易,只需外键关系即可。来自表A的关系,字段B_FK引用表B的主键,如果对应的表B行不存在,将阻止创建表A行。

【讨论】:

    【解决方案4】:

    如果“篡改”是指删除,那么 John 是对的,外键关系可能就是您想要的。但是,如果您的意思是修改,那么事务是唯一的方法。是的,这意味着你有一个潜在的瓶颈,但如果你希望你的操作是“原子的”,就没有办法避免这种情况。为避免任何明显的性能下降,您需要将事务的生命周期保持在最低限度。

    由于您使用的是 c#(可能是 ADO.NET),因此您可以使用框架中内置的事务功能。但是,最好让数据库服务器处理事务,因为这意味着事务可以在单个请求中启动、完成和提交(参见上面的事务生命周期)。

    【讨论】:

    • 你在游说存储过程吗:p 这是一个很好的观点。对我来说这个问题有点模糊,可能必须提高事务隔离级别才能使其正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2010-12-18
    相关资源
    最近更新 更多