这个问题是关于优化的。 有问题的情况如下:
我有一个包含数据的表,应该由多个事务读取和操作。该表由三列组成:{id,message,status}。
ID MESSAGE STATUS
1 First Message NEW
2 Second Message MOD
3 Third Message FIN
....
如图所示,状态是以下三种状态之一:{new,mod,fin}。它们指示行是否为新行,此时正在处理或已成功处理。 我这样做,以便多个事务在此表上工作。事务将读取所有“NEW”消息并将状态更改为“MOD”,以指示它们正在处理并锁定它们。之后他们被处理。成功处理的行将设置为“FIN”,失败的行将设置为“NEW”,以便下一个事务将再次尝试这些。
除了更改状态外,该表是只读的。要处理的准确信息永远不会改变。
上述过程有效,但我认为它不必要地复杂化。我在这里寻找的是一个更简单的解决方案。我已经读过不同的隔离级别,但它们基本上都会导致行以某种方式锁定,以便其他事务必须等待。我不想那样。相反,我希望其他查询忽略那些已读取的行。
现在终于回答了这个问题: 是否可以在读取时锁定行,以便其他转换忽略它们,而不是等待解锁这些行的事务?
我想要这样的事情: 可以说这张桌子有30行。
有没有办法在不需要状态栏的情况下执行此操作?
答案 0 :(得分:1)
有没有办法在不需要状态栏的情况下执行此操作?
简而言之,不,但不是由于锁定/并行问题。
实际上,您需要简单地使用该状态列,以便在处理系统最终出现故障时,您知道在重新启动时需要再次处理哪些行。它实际上使得更容易并行工作是一个附带的好处。
关于你的其余问题:
我已经阅读了不同的隔离级别,但它们基本上都会导致行以某种方式锁定,以便其他事务必须等待。我不想那样。相反,我希望其他查询忽略那些已读取的行。
......好吧,你很幸运,因为这不是你想要发生的事情。您的主要问题是,为了锁定仅读取的行,您不仅必须阻止其他进程读取这些行(因为通常只读共享锁),您必须阻止行从插入也是如此。但是,如果您使用写入锁定行,则交错过程变得更加简单和容易。
您需要的只是Cursor Stability
:
但是,如果更改了行中的任何数据,则会保持锁定,直到提交更改为止。
在此隔离级别下,当可更新游标位于该行上时,没有其他应用程序可以更新或删除行。在CS下,无法访问其他应用程序的未提交数据。 但是,不可重复的读取和幻像读取是可能的。
...允许其他处理器更新类似数据是非可重复读取的内容。我们实际上希望它们发生!我们不想要幻像读取(如果两行读取相同的数据然后尝试更新它会发生什么),但我们可以围绕它设计我们的应用程序。
执行此操作的一种方法是启动工作单元(这可能是隐式或显式的,具体取决于平台),然后发出更新语句:
UPDATE Transactions SET status = 'MOD'
WHERE status = 'NEW'
然后只需检索更新的行,以便知道要处理的内容:
SELECT id, message
FROM Transactions
WHERE status = 'MOD'
将它们标记为已完成:
UPDATE Transaction SET status = 'FIN'
WHERE status = 'MOD'
最后提交更改:
COMMIT
(请注意,此版本存在轻微弱点 - 如果系统在更新到'FIN'
之后但在提交之前发生故障,则该行将重置为'NEW'
,这可能是它自己的问题。但至少'MOD'
将正确回滚)