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_
, is always searched if it exists. It can be explicitly listed in the path by using the aliasnnn
pg_temp
. If it is not listed in the path then it is searched first (even beforepg_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。