用户在postgres中实现节流

时间:2019-12-02 07:41:07

标签: postgresql throttling database-deadlocks

到目前为止,我所做的是一个使用节流ID和时间间隔并在给定时间间隔多次调用的情况下返回true的函数。否则,它将返回null

这在测试时按预期工作,但在更强大的工作负载中会产生错误,

ERROR:  canceling statement due to statement timeout
===> - CONTEXT:  while locking tuple (2,108) in relation "shared"
    SQL function "throttle" statement 1

任何建议如何避免死锁?


CREATE OR REPLACE FUNCTION monitor.throttle(id_i text, every_i interval)
 RETURNS boolean
 LANGUAGE sql
AS $function$

    with
    nv as (
      select id_i id,
        '1'::text val,
        every_i every,
        clock_timestamp() modtime
    ),
    upsert as (
        update monitor.shared m set
          modtime = case
            when m.modtime+every >nv.modtime then m.modtime
            else nv.modtime
          end
        FROM nv
        WHERE m.id = nv.id
        RETURNING m.*
    ),
    ins as (
        INSERT INTO monitor.shared (id,modtime,val)
          SELECT id,modtime,val FROM nv
          WHERE NOT EXISTS (
            SELECT 1 FROM upsert up WHERE up.id = nv.id
          )
        returning *
    )
    select
        case
            -- don't throttle
            when i.id is not null or u.modtime=nv.modtime then null
            -- throttle
            else true
        end
    from nv
    left join upsert u on true
    left join ins i on true

$function$

\d monitor.shared
               Unlogged table "monitor.shared"
 Column  |           Type           |       Modifiers
---------+--------------------------+------------------------
 id      | text                     | not null
 val     | text                     |
 modtime | timestamp with time zone | not null default now()
Indexes:
    "shared_pkey" PRIMARY KEY, btree (id)

0 个答案:

没有答案