【问题标题】:How to truncate big table in postgresql having size greater than 5231MB?如何截断大小大于 5231MB 的 postgresql 中的大表?
【发布时间】:2016-04-29 06:15:50
【问题描述】:

已经尝试过删除和截断,但花了很长时间。还尝试使用以下查询找出该表上是否存在任何锁定过程

SELECT bl.pid          AS blocked_pid,
         a.usename       AS blocked_user,
         kl.pid          AS blocking_pid,
         ka.usename      AS blocking_user,
         a.current_query AS blocked_statement
  FROM  pg_catalog.pg_locks         bl
   JOIN pg_catalog.pg_stat_activity a  ON a.procpid = bl.pid
   JOIN pg_catalog.pg_locks         kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid
   JOIN pg_catalog.pg_stat_activity ka ON ka.procpid = kl.pid
  WHERE NOT bl.GRANTED;

不返回任何行

【问题讨论】:

    标签: postgresql truncate


    【解决方案1】:

    TRUNCATE 应该很快,除非它无法获取对象上的 AccessExclusiveLock,在这种情况下它可以无限期地等待。

    上面提到的应该显示阻塞会话的查询没有识别对象级锁,这是 TRUNCATE 获取的那种锁。

    这里提到过,我假设这个查询是从哪里获取的:

    https://wiki.postgresql.org/wiki/Lock_Monitoring

    以下查询可能有助于查看哪些进程正在阻塞 SQL 语句(这些只查找行级锁,而不是对象级锁) 锁)。


    这是 PG 9.1 问题的演示:

    第 1 场会议:

    test=> create table footable(id int);
    CREATE TABLE
    test=> begin;
    BEGIN
    test=> insert into footable values(1);
    INSERT 0 1
    test=> 
    

    (未提交)

    第 2 场会议

    test=> truncate table footable;
    

    (被会话 #1 阻止)

    第 3 场会议

    test=> SELECT bl.pid          AS blocked_pid,
             a.usename       AS blocked_user,
             kl.pid          AS blocking_pid,
             ka.usename      AS blocking_user,
             a.current_query AS blocked_statement
      FROM  pg_catalog.pg_locks         bl
       JOIN pg_catalog.pg_stat_activity a  ON a.procpid = bl.pid
       JOIN pg_catalog.pg_locks         kl ON kl.transactionid = bl.transactionid AND kl.pid != bl.pid
       JOIN pg_catalog.pg_stat_activity ka ON ka.procpid = kl.pid
      WHERE NOT bl.GRANTED;
    
     blocked_pid | blocked_user | blocking_pid | blocking_user | blocked_statement 
    -------------+--------------+--------------+---------------+-------------------
    (0 rows)
    

    根据这个查询,没有会话被阻塞,所以显然是错误的。

    我建议您在此处尝试其他查询: https://wiki.postgresql.org/wiki/Find_Locks

    在这个例子中,产生这个输出:

    -[ RECORD 1 ]------+--------------------
    locktype           | relation
    database           | 113270
    relation           | 2660062
    page               | 
    tuple              | 
    virtualxid         | 
    transactionid      | 
    classid            | 
    objid              | 
    objsubid           | 
    virtualtransaction | 5/2548
    pid                | 4419
    mode               | AccessExclusiveLock
    granted            | f
    virtualtransaction | 4/2031
    pid                | 31775
    mode               | RowExclusiveLock
    granted            | t
    

    【讨论】:

      【解决方案2】:

      TRUNCATE 是删除表的最快方法。来自docs

      TRUNCATE 快速从一组表中删除所有行。它与每个表上的非限定 DELETE 具有相同的效果,但由于它实际上并不扫描表,因此速度更快。此外,它会立即回收磁盘空间,而不需要后续的 VACUUM 操作。这在大表上最有用。

      您也可以DROP 并重新创建表,即the same as TRUNCATE

      您的DELETE 最终也会完成,您只需要给 Postgres 一些时间。

      如果需要在不锁表的情况下清除所有内容,可以批量删除:

      DELETE FROM things LIMIT 1000;
      

      在某个地方循环设置,直到桌子空了,然后去吃点零食。

      【讨论】:

        猜你喜欢
        • 2020-09-26
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        • 2022-01-24
        • 2020-04-11
        • 2020-10-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多