如何在没有并发问题的情况下将一行中的字段设置为同一 table 中某些行的数量?
How to set a field in a row to number of some rows in the same table without concurrency problems in postgresql?
假设我有这样的架构:
CREATE TABLE "test2" (
"id" SERIAL NOT NULL,
"text" CHAR(10),
PRIMARY KEY ("id")
);
CREATE TABLE "test1" (
"id" SERIAL NOT NULL,
"fkey" INTEGER NOT NULL,
"order" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
);
ALTER TABLE "test1" ADD FOREIGN KEY ("fkey") REFERENCES "test2"("id") ON DELETE CASCADE ON UPDATE CASCADE;
为了一些性能优化,我想在 "order" 字段中存储 "test1" [=31] 中的行数=] 引用 “test2” 中的同一行。所以我在插入时尝试这个:
insert INTO "test1"
("fkey","order")
select '3', count(*) from "test1" where "fkey"='3';
这会不会有并发问题? (例如,当两个线程同时使用相同的 fkey 插入到 test1 时,order 的值可以变得不正确?如何解决这个问题?
是的,当多个插入同时完成时,您需要考虑并发问题。
有几种解决方案。在我的脑海中,我可以看到:
- 在数据库中获取独占锁。可能主要 table 中的一行就可以了。
- 管理数据库外的锁或信号量。
- 插入行,但以延迟的方式更新
order
,可能使用队列(很可能是优先级队列)或单个单独的进程。
- 插入时使用乐观锁定。
其中每一个都有一些缺点,因此这取决于您的具体要求。
我猜你不想在每次插入新的 child 时更新 所有兄弟姐妹 ;就性能而言,这可能有点矫枉过正。如果这听起来合理,也许您可以使用优先级队列,运行 每 10 分钟(左右)一个进程,将相同 parent 的所有 children 分组并立即更新它们。
假设我有这样的架构:
CREATE TABLE "test2" (
"id" SERIAL NOT NULL,
"text" CHAR(10),
PRIMARY KEY ("id")
);
CREATE TABLE "test1" (
"id" SERIAL NOT NULL,
"fkey" INTEGER NOT NULL,
"order" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ("id")
);
ALTER TABLE "test1" ADD FOREIGN KEY ("fkey") REFERENCES "test2"("id") ON DELETE CASCADE ON UPDATE CASCADE;
为了一些性能优化,我想在 "order" 字段中存储 "test1" [=31] 中的行数=] 引用 “test2” 中的同一行。所以我在插入时尝试这个:
insert INTO "test1"
("fkey","order")
select '3', count(*) from "test1" where "fkey"='3';
这会不会有并发问题? (例如,当两个线程同时使用相同的 fkey 插入到 test1 时,order 的值可以变得不正确?如何解决这个问题?
是的,当多个插入同时完成时,您需要考虑并发问题。
有几种解决方案。在我的脑海中,我可以看到:
- 在数据库中获取独占锁。可能主要 table 中的一行就可以了。
- 管理数据库外的锁或信号量。
- 插入行,但以延迟的方式更新
order
,可能使用队列(很可能是优先级队列)或单个单独的进程。 - 插入时使用乐观锁定。
其中每一个都有一些缺点,因此这取决于您的具体要求。
我猜你不想在每次插入新的 child 时更新 所有兄弟姐妹 ;就性能而言,这可能有点矫枉过正。如果这听起来合理,也许您可以使用优先级队列,运行 每 10 分钟(左右)一个进程,将相同 parent 的所有 children 分组并立即更新它们。