lightdb/postgresql public、pg_catalog schema、pg_namespace区别以及oid和用户指定系统目录表

  除了public和用户创建的模式如lt_abc之外,在lightdb中,每个数据库都包含一个pg_catalog和lt_catalog模式,它包含系统表和所有内置数据类型、函数、操作符。lt_catalog和pg_catalog总是搜索路径search_path中的一部分。如果它没有明确出现在路径中,那么它隐含地在所有路径之前搜索。这样就保证了内置名字总是可以被搜索。不过,你可以明确地把pg_catalog放在搜索路径之后,如果你想使用用户自定义的名字覆盖内置名字的话,例如oracle标识符覆盖原生PG标识符。

  另外,每个数据库中还包含information_schema,和mysql一样,因为它是SQL规范的一部分,不过它默认不在search_path搜索目录。

  考虑到逻辑备份和恢复,一般不建议用户表创建在public schema下,而是创建一个和用户名相同的schema,这样备份恢复可以指定schema,更加的方便。

关于临时模式pg_temp

  在执行DDL如create table过程中,pg内核中有一段逻辑是判断对象所属的命名空间是否为临时模式,如下:

    if (newRelation->schemaname)
    {
        /* check for pg_temp alias */
        if (strcmp(newRelation->schemaname, "pg_temp") == 0)
        {
            /* Initialize temp namespace */
            AccessTempTableNamespace(false);
            return myTempNamespace;
        }
        /* use exact schema given */
        namespaceId = get_namespace_oid(newRelation->schemaname, false);
        /* we do not check for USAGE rights here! */
    }
    else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
    {
        /* Initialize temp namespace */
        AccessTempTableNamespace(false);
        return myTempNamespace;
    }

  但是在pg官方文档包括internals章节中,从来没有提到任何pg_temp和临时模式直接相关的信息,仅仅在http://www.light-pg.com/docs/lightdb/13.3-22.2/runtime-config-client.html。如下:

Likewise, the current session's temporary-table schema, pg_temp_nnn, is always searched if it exists. It can be explicitly listed in the path by using the alias pg_temp. If it is not listed in the path then it is searched first (even before pg_catalog). However, the temporary schema is only searched for relation (table, view, sequence, etc) and data type names. It is never searched for function or operator names.

从源码可知,临时schema主要用于临时表的存储。

void
RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
{
    switch (newRelation->relpersistence)
    {
        case RELPERSISTENCE_TEMP:
            if (!isTempOrTempToastNamespace(nspid))
            {
                if (isAnyTempNamespace(nspid))
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                             errmsg("cannot create relations in temporary schemas of other sessions")));
                else
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                             errmsg("cannot create temporary relation in non-temporary schema")));
            }
            break;
        case RELPERSISTENCE_PERMANENT:
            if (isTempOrTempToastNamespace(nspid))
                newRelation->relpersistence = RELPERSISTENCE_TEMP;
            else if (isAnyTempNamespace(nspid))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                         errmsg("cannot create relations in temporary schemas of other sessions")));
            break;
        default:
            if (isAnyTempNamespace(nspid))
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                         errmsg("only temporary relations may be created in temporary schemas")));
    }
}

  实际上临时模式的名称为pg_temp_N,n为数字,它本质上无常规的模式无区别,仅仅通过名称标识。但是dba运维的时候需要记得这个事情,不要假设它是用户创建的随意schema,否则可能会导致有auto vacuum无法清理的野对象,见https://www.postgresql.org/message-id/CAM-w4HNtbP5qDYccbdFKpLNzSBtQbjpwhOBvRkBUXMErGN%2BGJQ%40mail.gmail.com

https://wiki.postgresql.org/images/d/d1/Managing_rights_in_postgresql.pdf

http://www.light-pg.com/docs/lightdb/13.3-22.2/sql-createschema.html

http://www.light-pg.com/docs/lightdb/13.3-22.2/catalog-pg-namespace.html

https://www.postgresql.org/message-id/6F99845517EB402E9269BD6767CCE53C%40dell2 大量的pg_temp_xx临时模式,其实本身并不存在问题。在olap和跑批系统中经常有很常见。

https://www.percona.com/blog/postgresql-upgrade-tricks-with-oid-columns-and-extensions/

  最后,需要注意的是,在ISO SQL中,catalog name代表的是数据库名,也就是跟mysql的database name是一样的。PG多了一级真正的schema。

posted @ 2021-09-06 20:40  zhjh256  阅读(780)  评论(0编辑  收藏  举报