暂无图片
暂无图片
-1
暂无图片
暂无图片
暂无图片

openGauss中的锁超时

4158

pg从9.3版本开始提供了lock_timeout参数用以指定锁超时时间,默认0,openGauss由于是基于9.2.4版本pg研发,所以没有这个参数,但是openGauss中存在两个参数控制着锁超时:lockwait_timeout,update_lockwait_timeout

对于这两个参数的解释如下:

lockwait_timeout:控制单个锁的最长等待时间。当申请的锁等待时间超过设定值时,系统会报错。

update_lockwait_timeout:允许并发更新参数开启情况下,该参数控制并发更新同一行时单个锁的最长等待时间。当申请的锁等待时间超过设定值时,系统会报错。

从字面意思和解释可以看到如果获取更新锁的时候走update_lockwait_timeout,如果不获取更新锁,那么走lockwait_timeout。

两个参数的默认值如下:

    postgres=# show update_lockwait_timeout;
    update_lockwait_timeout
    -------------------------
    2min
    (1 row)


    postgres=# show lockwait_timeout;
    lockwait_timeout
    ------------------
    20min
    (1 row)

    下面来验证一下这两个参数的区别,为了减少测试时间,我们将update_lockwait_timeout设置为10s,将lockwait_timeout设置为20s。该参数只能写入postgresql.conf配置文件中。

    场景1:两个事物update同一行

    会话1:

      test=# begin;
      BEGIN
      test=# update test set id=2 where id=1;
      UPDATE 1

      会话2:

        test=# \timing
        Timing is on.
        test=# update test set id=3 where id=1;
        ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for ShareLock on transaction 102055465 after 10002.340 ms
        DETAIL: blocked by hold lock thread 139785215145728, statement <update test set id=2 where id=1;>, hold lockmode ExclusiveLock.
        Time: 10017.495 ms

        可以看到这个并发更新的锁走的是update_lockwait_timeout参数。

        场景2:select for update场景

        会话1:

          test=# begin;
          BEGIN
          test=# update test set id=2 where id=1;
          UPDATE 1

          会话2:

            test=# select * from test where id=1 for update;
            ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for ShareLock on transaction 102055467 after 10000.174 ms
            DETAIL: blocked by hold lock thread 139785215145728, statement <update test set id=2 where id=1;>, hold lockmode ExclusiveLock.
            Time: 10006.634 ms

            可以看到select for update依旧走的是更新锁update_lockwait_timeout锁超时参数。

            场景3:显式lock table

            会话1:

              test=# begin;
              BEGIN
              test=# lock table test;
              LOCK TABLE

              会话2:

                test=# update test set id=3 where id=1;
                ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for RowExclusiveLock on relation 16386 of database 16385 after 20002.091 ms
                LINE 1: update test set id=3 where id=1;
                ^
                DETAIL: blocked by hold lock thread 139785215145728, statement <lock table test;>, hold lockmode AccessExclusiveLock.
                Time: 20008.300 ms
                test=# select * from test;
                ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for AccessShareLock on relation 16386 of database 16385 after 20000.128 ms
                LINE 1: select * from test;
                ^
                DETAIL: blocked by hold lock thread 139785215145728, statement <lock table test;>, hold lockmode AccessExclusiveLock.
                Time: 20006.237 ms

                可以看到显式lock table时走的才是lockwait_timeout锁超时参数。

                场景4:ddl

                会话1:

                  test=# begin;
                  BEGIN
                  test=# update test set id=2 where id=1;
                  UPDATE 1

                  会话2:

                    test=# drop table test;
                    ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for AccessExclusiveLock on relation 16386 of database 16385 after 20000.169 ms
                    DETAIL: blocked by hold lock thread 139785215145728, statement <update test set id=2 where id=1;>, hold lockmode RowExclusiveLock.
                    Time: 20006.911 ms
                    test=# create index on test(id);
                    ERROR: Lock wait timeout: thread 139785179494144 on node dn_6001_6002_6003 waiting for ShareLock on relation 16386 of database 16385 after 20000.102 ms
                    DETAIL: blocked by hold lock thread 139785215145728, statement <update test set id=2 where id=1;>, hold lockmode RowExclusiveLock.
                    Time: 20006.578 ms

                    可以看到ddl等待锁的情况走的也是lockwait_timeout参数。

                    所以可以看到两个参数区别在于update_lockwait_tiemout在于控制并发更新同一行数据时的锁等待时间,而lockwait_timeout参数在于控制ddl锁等待以及显式lock table时的锁等待时间。

                    文章转载自数据库架构之美,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论