【postgresql】创建删除数据库代码分析
创建数据库接口
CREATE DATABASE
CREATE DATABASE – 创建一个新数据库
CREATE DATABASE name
[ [ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ TABLESPACE [=] tablespace_name ]
[ CONNECTION LIMIT [=] connlimit ] ]
CREATE DATABASE创建一个新PostgreSQL数据库。
要创建一个数据库,你必须是一个超级用户或者有特殊的CREATEDB权限。
缺省情况下新数据库将通过复制标准系统数据库template1来创建。 可以通过TEMPLATE name指定不同的模板。 尤其是,用TEMPLATE template0创建一个很纯净的、 只包括PostgreSQL预定义的标准对象的数据库。 这个方法对于避免把任何已经加入到template1里的本地安装对象拷贝到新数据库是非常有用的。
参数
- name 要创建的数据库名字。
- user_name 数据库用户的名字,他将是新数据库的所有者,或者是使用DEFAULT选项来指定当前缺省用户(也就是执行命令的用户)。 要创建一个其他角色所有的数据库,你必须是那个角色的直接或间接的成员,或者是超级用户。
- template 模板名,即从哪个模板创建新数据库,或者使用DEFAULT选项来指定缺省模板(template1)。
- encoding 创建新数据库使用的字符编码。 可以使用文本名字(例如’SQL_ASCII’)、整数编号或是DEFAULT选项来指定(模版数据库的编码)。
- lc_collate 用于新数据库的排序规则(LC_COLLATE)。 这影响到应用对字符串的排序顺序,例如:在有ORDER BY的查询中,以及用于文本列的索引的顺序。 在默认情况下,使用模板数据库的排序规则。
- lc_ctype 用于新数据库的字符分类(LC_CTYPE)。 这影响字符的分类,例如: 小写、大写和数字。 默认情况下使用模板数据库的字符分类
- tablespace_name 和新数据库关联的表空间名字, 或者使用DEFAULT选项表示使用模版数据库的表空间。 这个表空间将成为在这个数据库里创建的对象的缺省表空间。
- connlimit 数据库可以接受多少并发的连接。-1(缺省)意味着没有限制。
示例
创建一个由用户salesapp拥有的数据库sales,缺省表空间是salesspace:
CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;
createdb
createdb – 创建一个新 PostgreSQL 数据库
createdb 是一个 SQL 命令 CREATE DATABASE的封装。 因此,用哪种方法创建的数据库都一样。
模板数据库
CREATE DATABASE实际上通过拷贝一个已有数据库进行工作。 默认情况下,它拷贝名为template1 的标准系统数据库。所以该数据库是创建新数据库的"模板"。 如果你为template1数据库增加对象, 这些对象将被拷贝到后续创建的用户数据库中。 这种行为允许对数据库中标准对象集合的站点本地修改。例如, 如果你把过程语言PL/Perl安装到 template1中, 那么你在创建用户数据库后不需要额外的操作就可以使用该语言。
系统里还有名为template0 的第二个标准系统数据库。这个数据库包含和template1 初始内容一样的数据,也就是说,只包含你的PostgreSQL 版本预定义的标准对象。在数据库集簇被初始化之后,不应该对template0 做任何修改。通过指示CREATE DATABASE使用template0 而不是template1进行拷贝,你可以创建一个"纯净的"用户数据库, 它不会包含任何template1中的站点本地附加物。
要通过拷贝template0来创建一个数据库
CREATE DATABASE dbname TEMPLATE template0;
createdb -T template0 dbname; //Shell
可以创建额外的模板数据库,并且实际上可以通过将集簇中任意数据库指定为 CREATE DATABASE的模板来从该数据库拷贝。不过,我们必需明白, 这个功能并不是设计作为一般性的"COPY DATABASE" 功能。主要的限制是当源数据库被拷贝时,不能有其他会话连接到它。 如果在CREATE DATABASE开始时存在任何其它连接,那么该命令将会失败。 在拷贝操作期间,到源数据库的新连接将被阻止。
对于每一个数据库在pg_database系统表中 存在两个有用的标志:datistemplate和datallowconn列。 datistemplate可以被设置来指示该数据库是不是要作为 CREATE DATABASE的模板。如果设置了这个标志,那么该数据库可以被任何有 CREATEDB权限的用户克隆;如果没有被设置, 那么只有超级用户和该数据库的所有者可以克隆它。如果datallowconn为假, 那么将不允许与该数据库建立任何新的连接(但已有的会话不会因为把该标志设置为假而被中止)。 template0数据库通常被标记为datallowconn = false来阻止对它的修改。 template0和template1通常总是被标记为 datistemplate = true。
当数据库集簇被初始化时,也会创建**postgres数据库。 这个数据库用于做为用户和应用连接的默认数据库。**它只是template1 的一个简单拷贝,需要时可以删除并重建。
代码解析
createdb函数
创建database的代码在src/backend/commands/dbcommands.c里的createdb函数中
函数原型为
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt);
CreatedbStmt结构体包含数据库名称和其他的可选参数,由上层的查询引擎解析得到
typedef struct CreatedbStmt
{
NodeTag type;
char *dbname; /* name of database to create */
List *options; /* List of DefElem nodes */
} CreatedbStmt;
createdb函数主要的逻辑可以总结为
- 从stmt中提取createdb的可选参数。如tablespace、owner、template等。
- 检查该用户是否具有创建数据库的权限,没有则直接保存返回
- 调用get_db_info函数获得模板数据库的信息
- 检查要拷贝的模板数据库是否被标记为datistemplate,如果没有标记需要检查用户是superuser或owner
- 检查参数stmt中指定的tablespace的权限。判断参数stmt中指定的tablespace是否和目标模板数据库的tablespace是否一致。
- 调用get_database_oid获取dbname对应的oid, 如果有效说明dbname已经存在,报错。
- 调用CountOtherDBBackends函数获取要拷贝的模板数据库是否有活跃的后台进程,如果有则不能对目标模板数据库进行拷贝。
- 为新database生成一个新的oid,并且检查在现在的tablespace目录下不存在file冲突。
- 调用CatalogTupleInsert向系统表pg_database中插入一个tuple。
- 迭代遍历模板数据库的所有表空间(tablespace),调用存储引擎的copydir函数将模板表空间拷贝到新创建的database。
删除数据库接口
DROP DATABASE
DROP DATABASE 删除数据库。
输入参数是database的name。
该命令会移除catalog系统表中对应的一个存在的database的表项,并且删除掉包含数据的目录。
该命令只能被database owner执行。
该命令在连接到目标数据库的时候不能执行,因此使用脚本dropdb更加方便,它是本命令的包装版本。
dropdb
dropdb销毁掉一个存在的pg database。执行该命令的user必须是超级用户superuser或者database的owner。
代码分析
删除database的代码在src/backend/commands/dbcommands.c里的dropdb函数中
参考文献
- http://www.postgres.cn/docs/9.5/manage-ag-templatedbs.html
- https://www.postgresql.org/docs/9.1/app-createdb.html
- https://www.postgresql.org/docs/7.3/sql-dropdatabase.html
上一篇: C++中宏定义的优缺点
下一篇: ECshop 数据库表结构