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

处理PG数据库磁盘满异常宕机,这些“歪招”你必须要知道

5392

首先要知道一个知识点,pg数据库在数据目录其实是xlog目录满时实例将会异常crash,如果发生在生产环境中,这时会陷入一个很难处理的地步,因为你会发现数据目录里面能删的东西很少,如果误删除某些文件,可能造成数据库无法启动或者数据丢失。下面聊聊出现这种情况怎么处理。分为常规方法和非常规方法。

01

常规方法

1.删除pg_log运行日志

pg的运行日志默认存在于数据目录pg_log目录下,这些日志可能很大。如果可以删除,有限删除这些日志。

2.删除磁盘占位文件

一般有经验的pg dba都会在pg的数据目录里面放置一个无用的磁盘占位文件,预防这种问题,在应急时将这个文件删除,启动数据库。

02

非常规方法(慎用)

1.删除xlog文件

删除xlog文件有两种方式,但是在异常宕机的情况下删除都可能造成数据丢失,一定要注意这一点。一种是使用pg_resetxlog命令会删除指定的xlog文件,pg_resetxlog同时更新检查点信息,如果之前实例是异常crash的(比如由于磁盘满而crash),那么使用pg_resetxlog的时候会强制提示你添加-f参数并提示你可能造成数据丢失。

另外就是直接rm删除xlog文件,这样删除后数据库会无法启动,会提示找不到xlog,原因在于控制文件中的xlog位置没有更新,还是需要使用pg_resetxlog再删除一次更新一下控制文件信息,然后再启动数据库。

2.移动数据文件

数据库中的数据文件/表文件往往比较大,而数据库里面可能有一些无用的表,如果这些表可以清理的话,那么可以采用这种方法。

将base目录里面某个库的某个表文件移动到其他位置,然后启动数据库,然后删除无用的表,再将之前移动的表文件拷贝回来,然后启动数据库。

下面简单演示下这种操作的可行性

启动压力程序对test_1表插入数据,直到磁盘满

    test=# select oid,relname from pg_class where relname like '%test%';
    oid | relname
    -------+--------------
    74279 | test
    90663 | test_1
    90666 | idx_1_test_1
    90667 | idx_2_test_1
    (4 rows)


    test=# \d+
    List of relations
    Schema | Name | Type | Owner | Size | Description
    --------+--------+-------+----------+---------+-------------
    public | test | table | postgres | 2320 MB |
    public | test_1 | table | test | 159 MB |
    (2 rows)


    test=# \d+
    List of relations
    Schema | Name | Type | Owner | Size | Description
    --------+--------+-------+----------+---------+-------------
    public | test | table | postgres | 2320 MB |
    public | test_1 | table | test | 200 MB |
    (2 rows)
    复制

    压一段时间后,发现数据库挂掉

      test=# \d+
      List of relations
      Schema | Name | Type | Owner | Size | Description
      --------+--------+-------+----------+---------+-------------
      public | test | table | postgres | 2320 MB |
      public | test_1 | table | test | 7058 MB |
      (2 rows)
      复制

        test=# \d+
        WARNING: terminating connection because of crash of another server process
        DETAIL: The postmaster has commanded this server process to roll back the
        current transaction and exit, because another server process exited
        abnormally and possibly corrupted shared memory.
        HINT: In a moment you should be able to reconnect to the database and
        repeat your command.
        server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
        The connection to the server was lost. Attempting reset: Failed.
        !>
        复制

        查看数据目录磁盘空间

          [postgres@db01 33318]$ df -h pgdata
          Filesystem Size Used Avail Use% Mounted on
          /dev/mapper/data1vg-lvpgdata 99G 94G 0 100% pgdata
          复制

          进入base目录,删掉idx_2_test_1索引文件的一个文件,注意要删除第一个文件90667,如果删除的是带后缀的比如90667.1,那么启动数据库的时候会自动创建这个文件,还是会造成目录满,然后无法启动。

          因为是索引,可以直接删除,mv到其他目录也可以,这里直接删除吧,当然也可以mv一个表的文件到另一个位置,恢复后再拷贝回来。

          [postgres@db01 33318]$ rm 90667

          启动数据库,可以正常启动

            [postgres@db01 ~]$ pg_ctl start -l logfile
            waiting for server to start.... done
            server started
            复制


            删掉这个索引,删掉其他无用表,对该索引进行重建,注意drop索引之后数据目录里面的带后缀的索引文件不会自动清理,因为丢失了第一个文件,需要手动删除。

              test=# drop index idx_2_test_1;
              DROP INDEX
              [postgres@db01 33318]$ ll 90667*
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:48 90667.1
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:44 90667.2
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:45 90667.3
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:45 90667.4
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:45 90667.5
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:46 90667.6
              -rw------- 1 postgres postgres 1073741824 Sep 21 15:48 90667.7
              -rw------- 1 postgres postgres 572620800 Sep 21 15:48 90667.8
              [postgres@db01 33318]$ rm 90667.*
              复制


              正常重启数据库,没有问题

                [postgres@db01 ~]$ pg_ctl restart -l logfile
                waiting for server to shut down.... done
                server stopped
                waiting for server to start.... done
                server started
                复制


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

                评论