我有一个数据库中的表,负责存储有序/可重新排序的列表。它的形式如下:
| id | listId | index | title | ... |
其中id是主键,listId是外键,用于标识该项属于哪个列表,title和其他列是项目的内容。 index属性负责项目在列表中的位置。它是一个整数计数器(从0开始),在列表范围内是唯一的,但可能在列表之间重复。示例数据:
| id | listId | index | title | ...
---------------------------------------------
| "item1" | "list1" | 0 | "title1" | ...
| "item2" | "list1" | 1 | "title2" | ...
| "item3" | "list1" | 2 | "title3" | ...
| "item4" | "list2" | 0 | "title4" | ...
| "item5" | "list2" | 1 | "title5" | ...
用户可以创建/删除条目,将它们在列表内或列表之间移动。
为确保执行这些操作时索引的一致性,我采取以下措施:
创建条目:
- 计算此列表中的项目数
SELECT COUNT(DISTINCT "Item"."id") as "cnt"
FROM "item" "Item"
WHERE "Item"."listId" = ${listId}
- 插入新项,索引从步骤1计数:
INSERT INTO "item"("id", "listId", "index", "title", ...)
VALUES (${id}, ${listId}, ${count}, ${title})
这样,每插入一个项目,索引就会随之增长。
移动项目:
1. 检索项目的当前listId和索引:
SELECT "Item"."listId" AS "Item_listId", "Item"."index" AS "Item_index"
FROM "item" "Item"
WHERE "Item"."id" = ${id}
- 如有必要,更改“移动”的项目的索引,以保持顺序一致。例如,如果将项目向前移动,则其当前位置(不包括)和下一个位置(包括)之间的所有项目都需要将其索引减少1:
UPDATE "item"
SET "index" = "index" - 1
WHERE "listId" = ${listId}
AND "index" BETWEEN ${sourceIndex + 1} AND ${destinationIndex}
我会忽略跨列表移动的变化,因为它非常相似。
- 更新该项本身:
UPDATE "item"
SET "index" = ${destinationIndex}
WHERE "id" = ${id}
删除项目:
检索项目的索引和列表ID
将与此项相邻的同一列表中的所有项目向后移动1步,以消除间隙
UPDATE "item"
SET "index" = "index" - 1
WHERE "listId" = ${listId}
AND "index" > ${itemIndex}
DELETE FROM "item"
WHERE "id" = ${id}
问题是:
每个操作应提供哪些事务隔离级别?对于我来说保持索引列的一致性非常重要,不能有间隙,并且最重要的是不能有重复。我理解得对吗,创建项目操作受幽灵读取影响,因为它按某些条件计算项目数量,所以应该是可串行化的吗?其他操作呢?
(ListID, Index)
上的唯一索引强制执行最重要的约束条件 - 不允许重复。唯一索引约束条件很容易实现并且始终保持不变。 - Vladimir Baranov