【问题标题】:MemSql > workaround for SELECT ... FOR UPDATEMemSql > SELECT ... FOR UPDATE 的解决方法
【发布时间】:2018-12-13 14:28:20
【问题描述】:

我使用 MemSql 作为我的数据库,我需要有SELECT ... FOR UPDATE 功能。但是,我正在使用的 6.5 版本不支持它。这个问题有解决办法吗?

我的问题如下:多个进程从同一个表中选择一条记录(尚未处理),从 SQL 代码中执行一些工作,然后执行 UPDATE 以将记录标记为已处理。如果我有可能做SELECT ... FOR UPDATE,那么我可以锁定记录以确保只有一个进程可以选择它。

我能想到的一种解决方法是使用一些 LockToken 列并执行类似

的操作
UPDATE Tbl SET LockToken = 'a_unique_token' WHERE LockToken IS NULL LIMIT 1;
SELECT * FROM Tbl WHERE LockToken = 'a_unique_token';

但在这种情况下我得到了

错误代码:1749。MemSQL Distributed 不支持功能“UPDATE...LIMIT 必须限制在单个分区”。

我也可以使用 LOCK TABLES 完成这项工作,但根据 this 的说法,它们也不支持。

这类问题有解决办法吗?

【问题讨论】:

    标签: select locking singlestore


    【解决方案1】:

    是的,您的解决方法是个好主意。解决该错误的一种方法是选择要锁定的特定行,而不是使用 LIMIT 1,例如 UPDATE Tbl SET LockToken = 'a_unique_token' WHERE LockToken IS NULL and id = (select id from Tbl WHERE LockToken IS NULL limit 1)。 (或者你可以使用(select min(id) from Tbl WHERE LockToken IS NULL) 或类似的东西来根据你想要的选择一个id。)如果你有一个关于id的索引,这应该会很好。

    此外,您可以查看现在支持选择更新的版本 6.7:https://docs.memsql.com/sql-reference/v6.7/select/

    【讨论】:

    • 但是在 UPDATE 的条件部分使用 SELECT 是否安全?据我了解,该部分没有锁定,两个不同的进程可以运行相同的 SELECT 脚本和相同的 ID 值。
    • 是的,你是对的,两个进程都将读取相同的 id,而第二个进程只会阻止执行 SET,直到第一个进程已经设置它,因此更新零行。但是您可以检测到这一点并重试,因此假设大部分工作都在事务的后期,并且设置锁定的初始更新只是整个工作的一小部分,这种通用策略仍然会有所帮助。您还可以检索随机 id 而不是 min/max,这样并发线程就不太可能尝试锁定同一行。
    • 我明白了。在那种情况下,我有两个问题: 1. MemSql 中是否有任何 sql 级别的可能性来检索更新的行数? 2. UPDATE语句中的条件执行后是否执行UPDATE的行锁定?在这种情况下,它将在执行LockTocken IS NULL AND ID = (...) 条件后锁定一行。对吗?
    • 1.更新的行数由 UPDATE 语句返回 - 例如MySQL CLI 打印“匹配的行:1 更改:1”。您还可以检查 SELECT * FROM Tbl WHERE LockToken = 'a_unique_token' 查询是否返回任何内容。 2. 它在评估过滤器时锁定,因此只有一个 UPDATE 会看到 LockToken IS NULL,其他人会在第一次更新更改后看到 LockToken。您可以通过在一个会话中运行 begin; UPDATE Tbl ...,然后在另一个会话中运行 UPDATE TBL ...,然后在第一个会话中运行 commit 来观察此行为。
    • 谢谢。我试图弄清楚一个问题。如果从每个线程中我正在更新具有相同 ID 的行的 LockToken,并且在同一脚本中我选择同一行以在 C++ 代码中使用它,那么当一个 UPDATE 将覆盖另一个的 LockToken 时,不可能有任何情况?在这种情况下,在我的 C++ 代码中,我将使用一条记录,该记录在我从 DB 读取之后已更新。
    猜你喜欢
    • 2011-06-28
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2018-03-27
    • 1970-01-01
    • 2013-09-23
    • 2017-12-15
    • 2017-12-05
    相关资源
    最近更新 更多