【问题标题】:How to do locking in SQL Server like MYSQL如何像 MYSQL 一样锁定 SQL Server
【发布时间】:2010-01-04 16:36:19
【问题描述】:

我正在将 webapp 从 mysql 转换为 SQL Server。现在我想转换以下代码(这是一个简化版):

LOCK TABLES media WRITE, deleted WRITE;
INSERT INTO deleted (stuff) SELECT stuff FROM media WHERE id=1 OR id=2;
DELETE FROM media WHERE id=1 OR id=2;
UNLOCK TABLES;

因为我正在复制将要删除的内容,所以我想确保对“媒体”或“已删除”的任何读取都将等到整个操作准备好。否则这些读取将在几秒钟后看到不再存在的内容。

如何在 SQL Server 中复制此行为?我阅读了一些关于事务和隔离级别的页面,但我不知道是否可以禁用对表“媒体”和“已删除”(或行级别)的任何读取。

谢谢!

【问题讨论】:

    标签: mysql sql-server locking transactions


    【解决方案1】:

    您可以在查询中使用锁定提示。如果你指定一个表锁并持有它直到事务结束,那应该是等价的。

    begin transaction;
    
    INSERT INTO deleted
       SELECT stuff FROM media WITH (tablock holdlock)
       WHERE id = 1 or id = 2;
    
    DELETE FROM media where id = 1 or id = 2;
    
    commit;
    

    【讨论】:

    【解决方案2】:

    作为一种与数据库无关的方法,您可能会考虑使用“已删除”或“非活动”列来指示是否应将结果返回给用户。例如,您可以对列使用整数,如果列的值不为零,则从用户视图中排除记录。所以,除了上面的选择和插入,你可以这样做(所有示例都在 MySQL SQL 方言中):

    UPDATE media SET inactive=1 WHERE stuff=1 OR stuff=2;
    

    这将从用户视图中排除记录。然后,您可以根据您上次更新非活动记录的时间将非活动记录复制到“已删除”表并从媒体表中删除它们:

    INSERT INTO deleted (stuff) SELECT stuff FROM media WHERE inactive = 1;
    DELETE from media WHERE inactive <= 1;
    

    该整数可用于标识“删除”记录的“非活动作业”。

    根据您对架构的描述,这种情况与锁定方法不太匹配,因为“媒体”表可能会在执行 UPDATE 语句期间被修改。如果有一个列(例如时间戳)可用于进一步定义记录以标记为非活动状态,则可以解决(或至少减轻问题)。

    【讨论】:

      猜你喜欢
      • 2019-07-29
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多