在SQL数据库中处理并发更新的常用方法是什么?
考虑一个简单的SQL模式(约束和默认值未显示..)之类的
create table credits (
int id,
int creds,
int user_id
);
Run Code Online (Sandbox Code Playgroud)
目的是为用户存储某种信用,例如stackoverflow的声誉.
如何处理该表的并发更新?一些选择:
update credits set creds= 150 where userid = 1;
在这种情况下,应用程序检索当前值,计算新值(150)并执行更新.如果其他人同时做同样的事情,那么这就是灾难.我猜测包装当前值的撤销和事务中的更新将解决这个问题,例如,Begin; select creds from credits where userid=1; do application logic to calculate new value, update credits set credits = 160 where userid = 1; end;在这种情况下,您可以检查新信用是否<0,如果负信用没有意义,则将其截断为0.
update credits set creds = creds - 150 where userid=1;
这种情况不需要担心并发更新,因为数据库负责一致性问题,但是有一些缺陷,即信用很高兴会变成负面的,这可能对某些应用程序没有意义.
那么简单地说,处理上面提到的(非常简单的)问题的公认方法是什么,如果db抛出错误怎么办?
假设有一家医院运行一个简单的数据库。该数据库中有一个名为“患者”的表,其中包含 1,000,000 条记录——每条记录都是状态为“活动”或“出院”的患者。
Bob 运行以下查询,该查询将需要几秒钟甚至几分钟的时间才能运行:
SELECT COUNT(*) FROM PATIENTS WHERE STATUS = "active"
Run Code Online (Sandbox Code Playgroud)
当 Bob开始执行查询时,有 100 名患者处于活动状态。
但是,在查询运行时,Susie 在表上运行以下命令:
UPDATE PATIENTS SET STATUS = "discharged" WHERE PATIENT_ID = 583739789
Run Code Online (Sandbox Code Playgroud)
该命令让一名活跃患者出院,将真正的“活跃”患者数量更改为 99。
Susie 执行此操作后,Bob 的查询完成。他的查询结果是 100 名活跃患者还是 99 名活跃患者?不同的数据库如何处理这个问题(Oracle、MySQL、SQLite 等)?
我的情况:
每个工人的查询:
BEGIN;
INSERT INTO "test_tbl" ("id",...) VALUES
(...),(...),...[1000 entries]... RETURNING id;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
表test_tbl仅PRIMARY KEY (id)具有索引约束CREATE UNIQUE INDEX formulas_pkey ON formulas USING btree (id)
问题
经过许多小时的分析,它接缝的是工人等另一个工人完成了插入。为什么工人不能同时将新数据插入同一张表?
我删除了所有约束和所有索引(主键,外键等),但仍然存在相同的问题。没有并行化。
补充说明:
postgresql parallel-processing multithreading bulkinsert sql-insert