【发布时间】:2020-01-11 21:02:51
【问题描述】:
我在线程进程中遇到了这种情况。有表格样例:
id | type | external_key | balance | amount | date
1 TOPUP MT1 10 2019-01-1 13:01:00.500110
2 USAGE MT1 -1 2019-01-1 13:01:01.300100
3 TOPUP MT3 5 2019-01-1 13:01:02.400300
每行上的每个新数据我都会运行此触发器来更新字段余额以存储每一行的当前余额:
create or replace function function_update_balance() returns trigger
language plpgsql
as $$
BEGIN
IF new.type = 'CBA_ADJ' THEN
update example set balance=(SELECT SUM(case when amount >= 0 then amount when amount <= 0 then amount end) FROM example WHERE id=id and type=new.type and external_key =new.external_key ) WHERE id=new.id and date<= new.date;
END IF;
return null;
END;
$$
;
如果行插入速度不快(不像线程),则余额具有正确的余额,如下所示:
id | type | external_key | balance | amount | date
1 TOPUP MT1 10 10 2019-01-1 13:01:00.500110
2 USAGE MT1 9 -1 2019-01-1 13:01:01.300100
3 TOPUP MT3 5 5 2019-01-1 13:01:02.400300
但是当数据插入线程时(只是在 per , milisecond 上不同,余额没有像这样的正确结果:
id | type | external_key | balance | amount | date
1 TOPUP MT1 10 10 2019-01-1 13:01:00.500110
2 USAGE MT1 9 -1 2019-01-1 13:01:01.300100
3 TOPUP MT3 5 5 2019-01-1 13:01:02.400300
4 USAGE MT1 8 -1 2019-01-1 13:01:03.404000
5 USAGE MT1 8 -1 2019-01-1 13:01:02.405000
6 USAGE MT1 8 -1 2019-01-1 13:01:03.407000
7 USAGE MT1 8 -1 2019-01-1 13:01:03.408000
8 USAGE MT1 4 -1 2019-01-1 13:01:05.612000
就像,更新时的选择在最后一个事务提交之前读取了相同的值,我尝试过这样的隔离:
create or replace function function_update_balance() returns trigger
language plpgsql
as $$
BEGIN
IF new.type = 'CBA_ADJ' THEN
start transaction isolation level repeatable read;
update example set balance=(SELECT SUM(case when amount >= 0 then amount when amount <= 0 then amount end) FROM example WHERE id=id and type=new.type and external_key =new.external_key ) WHERE id=new.id and date<= new.date;
END IF;
return null;
END;
$$
;
然后给我错误:
ERROR: cannot begin/end transactions in PL/pgSQL
Hint: Use a BEGIN block with an EXCEPTION clause instead.
Where: PL/pgSQL function function_update_currentbalance() line 5 at SQL statement
关于并发进程这个问题的任何线索?
【问题讨论】:
标签: postgresql sql-update plpgsql