sql - 如何锁定某些行,因为它们在其他事务中没有被选择

标签 sql mysql concurrency transactions locking

我有一个表格,类似于我想要访问的 URL 列表。该表未被引用,也未引用其他表。 我的应用程序的作用是:

  • 从 URL 列表中选择一些行
  • 开始一个循环
    • 开始交易
    • 访问网址
    • 详细说明
    • 开始子交易
      • 检查结果是否已在前两个表中(选择)
      • 如果没有,请保存(插入)
    • 提交子事务
    • 开始子交易
      • 检查结果是否已在另一个表中(选择)
      • 如果没有,请保存(插入)
    • 提交子事务
    • 更新我正在访问的行
    • 提交主事务
  • 结束循环

到处都有大量的错误检查,主事务有数百个查询(选择和插入),mysql 的 CPU 占用率非常高(我猜是因为回滚日志很大),但所有这些都工作正常。

只是我无法运行该批处理的多个实例,因为它选择的行或多或少相同:这意味着我在几秒钟内多次访问某个 URL,这是我不希望的。

如果我将主事务的开始移到循环之外并选择要更新的行,我仍然不会获得多重并发,因为第二个实例不会运行选择,直到第一个实例的主事务不会运行提交。

一个可能的解决方案是在第一个表中添加一个“锁定”字段以设置为 true(实际上是当前日期,因为我尝试不使用 bool 值)。

另一种方法是启动主事务,然后一次仅选择一行(用于更新)(设置“限制 1”而不是现在的 5 或 10)。

我无法想象其他方式来获得我想要的东西:不要选择锁定的行。

有什么想法吗?

最佳答案

听起来好像您确实需要某种形式的标记来将行标识为“正在使用”,以便其他实例不会处理相同的数据;无论您使用 bool 类型还是日期类型都无关紧要,您必须以某种方式标记正在使用的行。

您可以通过调度程序、只能访问您的表的进程或线程来执行此操作,其唯一的工作是选择行并将它们传递给其他进程进行处理。即使这样,调度员也必须知道他们已经获取了多少数据,这样你就会回到同样的问题。

另一种方法是使用字段来指示该行正在使用中(正如您在问题中所说)。每个进程都会更新具有唯一 ID 的行 block ,在事务内执行以锁定表;我会使用从 CONNECTION_ID() 返回的连接号来标记它们,然后你就知道它是唯一的。

UPDATE ... WHERE connection_id IS NULL(应用了限制)事务完成后,该过程可以SELECT ... WHERE connection_id = CONNECTION_ID()来获取他们的行进行处理。

当他们完成工作时,整个循环再次开始标记下一组行,直到所有行都已处理完毕。

关于sql - 如何锁定某些行,因为它们在其他事务中没有被选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4749636/

相关文章:

sql - 运行用户定义的 SQL 脚本的 postgresql pgBench 工具

mysql - 将文本列设为唯一键

c# - 中文本/长文本 - Entity Framework 代码优先迁移

mysql - mysql 中 grails byte[] 属性的数据类型错误

MYSQL 的 PHP 脚本作用于一个文件,而不作用于另一个文件

kotlin - GlobalScope 与 LifecycleOwner :CoroutineScope

Java用户类

sql - 优化 sql 条件以将条件应用于所有相关行

java - 如何组织信号量以将多个 java 进程写入一个文本文件

concurrency - D 中是否有不可变数据 "burn up"RAM?