Mysql ReadUncommitted是否可以知道将存在的所有较低的自动增量ID?

Mysql ReadUncommitted是否可以知道将存在的所有较低的自动增量ID?,mysql,auto-increment,isolation-level,read-uncommitted,Mysql,Auto Increment,Isolation Level,Read Uncommitted,假设我们有一个具有自动递增主键的表。我想加载比我看到的上一个ID大的所有ID SELECT id FROM mytable WHERE id > 10; 使用天真的方法,我会冒跳过ID的风险: 交易1索赔ID 11 交易2索赔ID 12 事务2提交 我读取所有ID>10。我看到12,下次我将读取所有ID>12。我跳过了11节 事务1提交。出于所有目的,ID11现在已经存在 作为一种解决方案,我建议进行双重检查,以确保不会提交任何中间ID: SET TRANSACTION ISOLAT

假设我们有一个具有自动递增主键的表。我想加载比我看到的上一个ID大的所有ID

SELECT id
FROM mytable
WHERE id > 10;
使用天真的方法,我会冒跳过ID的风险:

  • 交易1索赔ID 11
  • 交易2索赔ID 12
  • 事务2提交
  • 我读取所有ID>10。我看到12,下次我将读取所有ID>12。我跳过了11节
  • 事务1提交。出于所有目的,ID11现在已经存在
作为一种解决方案,我建议进行双重检查,以确保不会提交任何中间ID:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

SELECT COUNT(*)
FROM mytable
WHERE id > 10
AND id <= 12; -- Where 12 was the max seen in the first query
设置事务隔离级别读取未提交;
选择计数(*)
从mytable
其中id>10

idMysql在自动递增期间锁定表

因此,如果版本中没有bug,通常不会出现问题


锁的工作原理类似于信号量/关键部分。

自1992年以来,我一直在使用SQL数据库进行开发,我从未见过使用READ UNCOMMITTED是解决任何问题的正确方法

我猜您正在使用MySQL作为一种队列。也就是说,您依赖自动递增ID作为队列的头

我不认为你可以用你描述的方式来做这件事,因为事务生成其auto inc ID的顺序与它们提交的顺序不同

我建议您需要另一个名为
processed
或类似内容的专栏。然后,您可以查询尚未处理的记录:

SELECT id FROM mytable WHERE processed = false ORDER BY id
这样,查询将始终返回您尚未看到的任何记录。如果在您已经看到ID 12之后提交了ID 11,那么它将在下次运行此查询时显示

一旦您完成了要对记录执行的操作,那么:

UPDATE mytable SET processed = true WHERE id = ?

不需要处理
列的更好的解决方案是使用a来补充SQL数据库


当客户机添加记录时,他们还应该将刚刚插入消息队列的记录的ID发布到消息队列中。重要的是,此客户端在提交记录后将其发送到消息队列,否则消息队列的使用者可能会收到他们尚未看到的ID的通知。

谢谢您的建议!我知道MessageQueues和跟踪生产者中处理的能力。尽管有这些选择,我仍然希望找到这个问题的直接答案。这个答案可以从两个方面中选择一个,真的:如果存在一个ID被声明的时刻,
readuncommitted
,那么我的想法不起作用,否则它就起作用了。我不建议使用readuncommitted。这会破坏ACID的隔离特性,因此不应将其视为适当的解决方案。请注意,
READ UNCOMMITTED
仅用于确认。返回的唯一数据是
READ COMMITTED
查询的结果,前提是没有跳过未提交的ID。但是可能仍然存在获取ID的时刻,表再次解锁,但是
READ uncommitted
查询仍然没有可见的新行。还是这样?如果有任何指示,则为:(不,我对信号量的引用非常准确。您的自动增量是save。当您要求它时,它只有行数。毫秒后可能会有其他情况。表的锁定经常引起争论,因为大插入或长事务可以锁定表。在这种情况下,您可以检查它。在select中声明。除了cpu可以使用mimo队列之外,这就是为什么不能依赖insertsun的顺序。幸运的是,这没有给我任何保证。在获取ID时锁定表是很好的。但这并没有说明(A)解锁表(自动递增计数器递增)之间会发生什么和(B)实际将插入的ID存储在新行中。事实上,我在前面的评论中链接的问题似乎表明,在a和B之间有一个特定的时间跨度,ID已被声明,但尚未写入任何行(因此,即使对于
读取未提交的
,也看不到此类行).写之前先解锁是有道理的。