【问题标题】:How can I lock a table for read and write so I can execute SQL and then remove the locks afterward?如何锁定表以进行读写,以便我可以执行 SQL,然后再删除锁定?
【发布时间】:2012-07-29 11:58:42
【问题描述】:

我刚刚开始深入研究 Teradata 的锁定功能,Google 对此的解释相当复杂。希望我能从 SE 那里得到一个非常简单和精简的答案。

在 Teradata 中遇到许多与标识列有关的问题后,我决定创建一种模仿 Oracle 序列的机制。为此,我正在创建一个包含两个字段的表,一个包含表名,另一个存储其最后使用的序列。然后,我将创建一个采用表名的存储过程。在该过程中,它将执行以下选项:

  • 从序列表中选择最后使用的序列到一个变量中 (select LastId from mydb.sequence where tablename = :tablename)
  • 将变量的值加 1,从而使其递增
  • 更新序列表以使用增量值
  • 将序列变量返回到过程的 OUT 参数,以便我可以在我的 .NET 应用程序中访问序列 ID

当所有这些操作都在进行时,我需要锁定序列表以进行所有读写访问,以确保对过程的其他调用不会尝试对当前正在排序的表进行排序.这显然是为了防止相同的序列在同一张表中被使用两次。

如果这是 .NET,我会使用 Sync Lock (VB.NET) 或 lock (C#) 来阻止其他线程进入代码块,直到当前线程完成。我想知道是否有一种方法可以像锁定 .NET 中的线程一样锁定表。

【问题讨论】:

    标签: stored-procedures locking teradata


    【解决方案1】:

    考虑为事务的行哈希锁使用显式锁定机制:

    BEGIN TRANSACTION;
    
    LOCKING ROW EXCLUSIVE
    SELECT LastId + 1 INTO :LastID
    FROM MyDB.SequenceCols
    WHERE TableName = :TableName
      AND DatabaseName = :DatabaseName;
    
    UPDATE MyDB.SequenceCols
    SET LastId = :LastID
    WHERE TableName = :TableName
      AND DatabaseName = :DatabaseName;
    
    END TRANSACTION;
    

    rowhash 锁将允许其他进程针对其他表使用该过程。要确保行级锁定,您必须完全限定 SequenceCols 表的主索引。实际上,SequenceCols 表的主索引在DatabaseNameTableName 上应该是唯一的。

    编辑:

    排他行哈希锁将阻止另一个进程读取该行,直到 END TRANSACTION 被处理为行哈希锁的所有者。

    【讨论】:

    • 如果此过程同时被调用两次,并且两个调用最终都选择了相同的 ID,然后它们中的任何一个进入更新,会发生什么?
    • 查看编辑以获取有关独占 rowhash 锁的更多说明。
    • 所以我得到了一切工作。有没有办法测试这种锁定是否有效?我很自然地想找到一种方法让 sproc 等待,以便我有足够的时间发送另一个请求,但研究表明只有 UDF 能够做到这一点。
    • 您可以使用 BTEQ 并使用 .OS 命令调用在提交 END TRANSACTION 命令之前休眠一段时间的脚本来测试存储过程之外的逻辑。这将允许您调用第二个进程,该进程尝试使用睡眠进程持有的存储过程为同一个表分配新的标识值。
    • 好的,你已经拿到了薪水,所以我会标记你的答案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多