【问题标题】:Lost update solution丢失更新解决方案
【发布时间】:2016-03-17 14:28:31
【问题描述】:

我想解决我的应用程序中丢失更新的问题,即在读取和更新一个事务之间另一个事务执行更新时的问题。

我想知道的是我是否可以通过在 SQL Server 中设置特定的隔离级别(READ_COMMITTED、READ_COMMITTED_SNAPSHOT 或 SNAPSHOT)来解决它,或者我必须在应用层实现逻辑,例如向我的实体添加行版本字段类,并在发生时手动检查并回滚。

【问题讨论】:

    标签: c# sql-server entity-framework transactions


    【解决方案1】:

    好像READ_COMMITTEDREAD_COMMITTED_SNAPSHOT不支持Update conflict detection,只有SNAPSHOT支持。来源:Understanding Row Versioning-Based Isolation Levels

    所以要解决 DB 层丢失更新的问题,必须使用SNAPSHOT 隔离级别。

    如果使用READ_COMMITTEDREAD_COMMITTED_SNAPSHOT,那么丢失更新问题必须在应用层解决。这是如何完成的Row versioning in Entity framework

    【讨论】:

      【解决方案2】:

      这是一篇很好的文章,解释了丢失更新问题 - https://vladmihalcea.com/a-beginners-guide-to-database-locking-and-the-lost-update-phenomena/ 它建议 REPEATABLE-READ 隔离级别,它确实有效(在这种情况下在 Postgres 中)。

      但例如,在 mysql 中可重复读取并不能解决丢失的更新,您必须使用某种锁定,例如 SELECT ... FOR UPDATE - http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

      【讨论】:

        【解决方案3】:

        为防止丢失更新,事务必须以至少可重复读取的隔离级别运行,并结合应用层中的事务块。

        【讨论】:

        • 我想要乐观锁定,而不是悲观。
        • 如果您的目标是提高并发性而不是在读取操作期间锁定数据,那么您可以利用 Read Committed Snapshot Isolation。您可以通过更改数据库或在特定表上运行快照隔离事务来启用 RCSI。更改数据库:ALTER DATABASE dbName SET ALLOW_SNAPSHOT_ISOLATION ON;设置事务隔离级别快照; BEGIN TRAN SELECT * FROM TABLE
        猜你喜欢
        • 1970-01-01
        • 2012-03-04
        • 1970-01-01
        • 1970-01-01
        • 2019-07-06
        • 2021-05-06
        • 1970-01-01
        • 1970-01-01
        • 2012-01-16
        相关资源
        最近更新 更多