我有一个带有主键的简单表。大多数读取操作以键的确切值获取一行。

每行的数据在按键顺序之前和之后都与行保持一定的关系。因此,当我插入新行时,我需要读取将要输入的2行,进行一些计算然后插入。

显然,关注的是,同时另一个连接可能会在相同的间隔中添加带有键值的行。如果密钥的值与第二个插件完全相同,我将被覆盖,但是如果密钥值不同,但在相同的间隔中,关系可能会被打破。

该解决方案似乎是在我决定添加新行或(如果可能的话)锁定以锁定关键值的间隔时(如果可能的话)锁定整个表格。但是,我希望当时不会阻止仅阅读交易。

我正在使用ODBC C ++的LibodBC ++包装器 在客户端程序和IBM DB2免费版中(尽管DB选择仍然可能会发生变化)。这就是我想做的:

  • 以自动命令和默认隔离模式启动连接
  • 在需要添加新行时,将自动命令设置为false和隔离模式为序列化
  • 读取新钥匙值之前和之后的行
  • 计算并插入新行
  • 犯罪
  • 返回到自动命令和默认隔离模式

这会做这份工作吗?其他交易是否可以同时阅读?还有其他/更好的方法吗?

顺便说一句,我看不到libodbc ++ i/fa的方式来指定仅阅读交易。在ODBC中可能吗?

编辑:感谢您的非常有用的答案,我很难选择一个。

有帮助吗?

解决方案

如果您的数据库处于可序列化模式,则根本不会遇到任何问题。给定一个键K,要获取上一个键和下一个键,您必须运行以下查询:

select key from keys where key > K order by key limit 1;      # M?
select key from keys where key < K order by key desc limit 1; # I?

以上作品在MySQL中起作用。此等效查询在DB2中起作用(来自评论):

select key from keys where key = (select min(key) from keys where key > K);
select key from keys where key = (select max(key) from keys where key < K);

第一个查询设置了一个范围锁定,该范围锁定可防止其他交易插入大于K的密钥,并且小于或等于M。

第二个查询设置了一个范围锁定,该范围锁定了其他交易插入小于K的密钥,并且大于或等于I。

主键上的唯一索引可防止K插入两次。因此,您完全被掩盖了。

这就是交易的目的;因此,您可以像整个数据库锁定一样编写代码。

注意:这需要一个支持真正序列化性的数据库。幸运的是,DB2确实如此。支持真正的序列化性的其他DBM:SQLServer和MySQL/InnoDB。 DBMS不是:Oracle,PostgreSQL!

其他提示

如果您的数据库和存储引擎允许,您应该发行 SELECT FOR UPDATE 对于这两个行,您都在尝试插入之间。

这将与任何并发 SELECT FOR UPDATE.

缺点是一排锁 1012 (插入 11)还将阻止选择 810 (插入 9).

InnoDBMySQL 也可以放置 next-key 锁定索引,即索引记录的锁定和下一个记录之间的差距。

在这种情况下,您只需要发布 SELECT FOR UPDATE 在第一行,因此在此之前同时插入一行。

但是,这需要迫使索引并提供 range 根据您的查询,索引的条件可能不可能,也可能不可能。

您的一般方法是正确的。但是,您应该使用覆盖两个行和所有可能的行的选择语句。例如:

SELECT * FROM MYTABLE WHERE PKCOL BETWEEN 6 AND 10

在具有悲观锁定和交易隔离级别可序列化的数据库系统中,该选择语句应防止插入新的行,以改变选择的结果。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top