这是一个 Pl/pgsql 函数,用于在 LightDB 中记录运行时间较长的事务,可以选择输出任何阻塞语句的详细信息,并取消/终止有问题的语句/事务。
如有需要,可以使用 cron 或类似的工具进行调度。
谨慎使用取消/终止功能,并参阅有关 LightDB 中某些用例的更好替代方案的说明。
要简单记录长时间运行的事务,只需调用该函数,并传递开始记录的最短持续时间:
TEST=# SELECT pg_log_long_xact('1s'); NOTICE: long_xact pid: 4465 duration: 431.325747 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction NOTICE: long_xact pid: 16532 duration: 327.438302 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5; pg_log_long_xact --------------- (0 rows)
要记录有关长时间运行的事务可能等待的锁的额外信息,请将第二个参数设置为 true(尽管您可以通过启用 log_lock_waits 来记录类似的信息):
TEST=# SELECT pg_log_long_xact('1s', true); NOTICE: long_xact pid: 4465 duration: 471.885373 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction NOTICE: long_xact pid: 16532 duration: 367.997928 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5; NOTICE: long_xact waiter pid: 16532 blocker detail is; pid: 4465 duration: 471.885373 ms relation: any (public.balls (RowExclusiveLock)) lock type: transaction id 311824482 user: glyn application: ltsql client: [local] statement: <IDLE> in transaction pg_log_long_xact --------------- (0 rows)
要设置所使用的 raise 级别,请传递第三个参数,它可以是以下任何一种: “debug”、“log”、“info”、“notice”、“warning” 或 “text”,以作为文本结果集输出。 (回过头来看,默认值可能应该是 “log”)
TEST=# \t off 仅显示元组。 TEST=# SELECT pg_log_long_xact('1s', true, 'text'); long_xact pid: 4465 duration: 574.477076 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction long_xact pid: 16532 duration: 470.589631 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5; long_xact waiter pid: 16532 blocker detail is; pid: 4465 duration: 574.477076 ms relation: any (public.balls (RowExclusiveLock)) lock type: transaction id 311824482 user: glyn application: ltsql client: [local] statement: <IDLE> in transaction
要使其开始取消超过特定持续时间的语句,我们将持续时间作为第四个参数传递;每次运行时,将取消第一个超出此限制的事务,并优先处理阻塞语句。
(有一个 lock_timeout 参数,将中止等待时间超过指定毫秒数的任何语句,这要好得多。请注意,这里的区别是该函数将尝试中止阻塞事务而不是等待语句,或者如果没有锁定,则中止最长事务。)
TEST=# SELECT pg_log_long_xact('1s', true, 'text', '10 minutes'); long_xact pid: 4465 duration: 895.57988 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction long_xact unable to cancel backend with pid: 4465 long_xact pid: 16532 duration: 791.692435 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5; long_xact waiter pid: 16532 blocker detail is; pid: 4465 duration: 895.57988 ms relation: any (public.balls (RowExclusiveLock)) lock type: transaction id 31182 4482 user: glyn application: ltsql client: [local] statement: <IDLE> in transaction
我们还可以将持续时间作为第五个参数提供,以终止具有超过此时间长度的事务的后端进程,取消优先级与上述相同:
TEST=# SELECT pg_log_long_xact('1s', true, 'text', '10 minutes', '15 minutes'); long_xact pid: 4465 duration: 1026.90736 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction long_xact terminated backend with pid: 4465 long_xact pid: 16532 duration: 923.019915 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5;
默认情况下,该函数仅取消/终止最长运行的阻塞者或最长运行的事务,我们可以通过传递一个额外的参数来告诉它取消所有长时间运行的事务中的语句/终止后端进程,从而变得更加强制性:
TEST=#\t off TEST=# SELECT pg_log_long_xact('1s', true, 'text', '2 minutes', '3 minutes', true); long_xact pid: 19065 duration: 187.279089 ms user: glyn application: ltsql client: [local] statement: <IDLE> in transaction long_xact terminated backend with pid: 19065 long_xact pid: 16532 duration: 184.251569 ms user: glyn application: ltsql client: [local] statement: UPDATE balls SET description = 'TEST' WHERE id = 5; long_xact cancelled backend with pid: 16532 (4 rows)