【发布时间】:2015-09-15 16:04:44
【问题描述】:
我有一个表标签,它具有以下结构和值:
+----+----------+-------+
| id | name | order |
+----+----------+-------+
| 42 | 'foo' | 1 |
+----+----------+-------+
| 43 | 'bar' | 3 |
+----+----------+-------+
| 44 | 'baz' | 2 |
+----+----------+-------+
id 是内部 PK,name 是显示名称,order(唯一)是这些标签必须显示的顺序('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 个?
提前感谢您的建议。
【问题讨论】:
-
对列使用自动增量 ID。不要试图自己实现这个逻辑。
-
使用序列,这是唯一可靠、快速且可扩展的解决方案。
-
@GordonLinoff 我没有发现“顺序”列中的“间隙”不是问题,实际上使用序列总是会生成“当时的最大可能顺序”。我会走那条路,谢谢。
-
@a_horse_with_no_name 与 Gordon Linoff 的回复相同,您说的都对,谢谢。
标签: sql hibernate transactions rdbms