RDBMS:选择max(“ORDER”)+ 1个事务隔离级别

时间:2015-09-15 16:04:45

标签: sql hibernate transactions rdbms

我有一个表标记,它具有以下结构和值:

    +----+----------+-------+
    | id | name     | order |
    +----+----------+-------+
    | 42 | 'foo'    | 1     |
    +----+----------+-------+
    | 43 | 'bar'    | 3     |
    +----+----------+-------+
    | 44 | 'baz'    | 2     |
    +----+----------+-------+

ID 是内部PK,名称是显示名称,订单(唯一)是必须显示这些代码的顺序('foo','baz','bar')。可以创建新标签,删除现有标签,并重新排序所有标签。

我想我会插入新标签的方式遇到问题。我需要做一些像(伪代码)的事情:

     begin transaction A;
     select max("order") + 1 into next_order from Tag;
     insert into Tag("name", "order") values('blah', next_order);
     commit A;

当然,同时可以运行另一个事务:

     begin transaction B;
     select max("order") + 1 into next_order from Tag;
     insert into Tag("name", "order") values('bluh', next_order);
     commit B;

让我们采用最高的事务隔离级别 SERIALIZABLE ,我明白它可以保护我免受幻读,即使“A”提交而“B”运行,“B”也不会看到新的行('blah',4)。

不幸的是,“B”和“A”会选择相同的max(“order”)+ 1,而“A”和“B”提交后的表格看起来像:

    +----+------------------+
    | id | name     | order |
    +----+----------+-------+
    | 42 | 'foo'    | 1     |
    +----+----------+-------+
    | 43 | 'bar'    | 3     |
    +----+----------+-------+
    | 44 | 'baz'    | 2     |
    +----+----------+-------+
    | 45 | 'blah'   | 4     |
    +----+----------+-------+ 
    | 46 | 'bluh'   | 4     |
    +----+----------+-------+

我希望我错了,是吗?

如果我不是,那么在表中原子地处理“行顺序”的常见模式是什么?在插入新行时我应该锁定整个表吗?或者我应该使用“order”列没有唯一约束,'blah'和'bluh'插入顺序是未定义的,它们都是第4个

提前感谢您的建议。

1 个答案:

答案 0 :(得分:0)

如果用户删除标记或想要更改订单,该怎么办?

我会锁定桌子。您可能需要触发器才能插入/更新/删除。

因此插入应该使用order = null正常工作,并将事务逻辑放在触发器中。