【发布时间】:2014-01-16 20:47:24
【问题描述】:
我有一个使用 EF6 和 SQL Server 的 ASP.NET MVC 应用程序,最多有 15 个左右的并发用户。为了确保每个页面请求期间不同查询之间的数据一致性,我将所有内容都包含在事务中(使用System.Transactions.TransactionScope)。
当我使用IsolationLevel.ReadCommitted 和.Serializable 时,会出现如下死锁错误:
事务(进程 ID #)在锁资源上与另一个进程死锁,并已被选为死锁牺牲品。
当我使用IsolationLevel.Snapshot 时,我收到如下错误:
快照隔离事务由于更新冲突而中止。您不能使用快照隔离直接或间接访问数据库“#”中的表“dbo.#”来更新、删除或插入已被另一个事务修改或删除的行。重试事务或更改更新/删除语句的隔离级别。
这些错误在使用IsolationLevel.Snapshot 时最不常见(大致每天一到三个)。
我对这个问题的理解使我相信,保证零交易失败的唯一方法是:
- 完全序列化所有数据库访问,或
- 实现某种类型的事务重试功能。
我无法做到 1,因为某些任务和请求需要一段时间才能运行,而应用程序的其他部分需要保持合理的响应。
我倾向于认为可以通过让 MVC 重新运行控制器操作来实现重试,但我不知道如何去做这样的事情。
我也不知道如何重现我的用户造成的错误。我现在得到的只是信息量不大的异常日志。我可以设置 EF 来记录在数据库上运行的所有 SQL,现在 EF6 允许您这样做,但我不确定这实际上会有多大帮助。
有什么想法吗?
【问题讨论】:
标签: c# sql-server asp.net-mvc transactions