【问题标题】:How do I guarantee row uniqueness in MySQL without the use of a UNIQUE constraint?如何在不使用 UNIQUE 约束的情况下保证 MySQL 中的行唯一性?
【发布时间】:2010-03-16 14:01:23
【问题描述】:

我有一些相当简单的要求,但我不确定如何实现它们:

  • 我有多个并发线程运行同一个查询
  • 查询提供一个“字符串”值 - 如果它存在于表中,则查询应返回匹配行的 id,否则查询应插入“字符串”值并返回最后插入的 id
  • “字符串”列是(并且必须是)文本列(它大于 varchar 255),因此我不能将其设置为唯一 - 必须通过访问机制强制执行唯一性
  • 查询需要是存储过程格式(不支持MySQL中的表锁)

如何保证“字符串”是唯一的?在另一个线程读取表并没有找到匹配的“字符串”项目后,如何防止其他线程写入表?

感谢您的建议..

【问题讨论】:

    标签: mysql


    【解决方案1】:

    如果您确定不能使用 DB 约束,请在另一个字段上使用 UNIQUE 索引,在该字段中存储完整字符串的良好加密哈希。我猜 MD5 或 SHA1 应该足够了。一些源代码管理系统(如 Git、Mercurial、Monotone 等)依赖于极低的哈希冲突可能性。

    【讨论】:

      【解决方案2】:

      您必须在读/写操作上创建同步线程或同步资源,因此当另一个线程正在读取或写入时,将不允许一个线程读取或写入。

      对于字符串,你可以做一个“贪婪”的查询,比如:

      select distinct string from table where ...
      

      线程第一次执行选择时,您将结果缓存在 HashMap 或类似的 Map 中,并在每次线程访问表以添加行时更新它。 首先,您将检查 HashMap 是否存在,然后执行查询。如果 HashMap 存在,您可以检查是否在其中找到您的字符串。

      【讨论】:

      • 我一开始就试过了,但是桌子很大,我无法缓存整个东西
      【解决方案3】:

      您可以对该文本进行选择,如果没有找到则插入它,否则更新。将其全部打包在一个事务中。

      【讨论】:

        【解决方案4】:

        您可以使用锁表,因为它在存储例程中不受支持,您可以使用

        START TRANSACTION;
        
            SELECT * FROM ....
        
        COMMIT;
        

        您只需要确保使用事务安全的存储引擎,例如 InnoDB

        【讨论】:

          猜你喜欢
          • 2012-06-27
          • 2016-09-06
          • 2013-05-17
          • 2015-12-23
          • 1970-01-01
          • 2020-03-30
          • 2021-01-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多