PostgreSQL-表空间、数据库、模式、角色
目录
1. 表空间(tablespace)
不同的数据库表空间有不同的定义。在postgres中,表空间允许在文件系统中定义数据库对象存储的位置,实质上就是指定一个目录。
1.1 应用场景
- 存储磁盘没有空间时,可以使用表空间把数据存在其它地方;
- 利用表空间对数据库进行性能优化。常用来将频繁使用的数据表或者索引放在高性能的硬盘上,而较少使用的放在普通硬盘上。
1.2 初始表空间
自带两个表空间:pg_default,pg_global
pg_default 用来存储系统目录对象,用户表、用户表index、临时表、临时表index、内部临时表的默认空间。存储目录:D:\Program Files\PostgreSQL\9.5\data\base
pg_global 用来存储系统字典表,存储目录:D:\Program Files\PostgreSQL\9.5\data\global
pg_tblspc 存储手动创建表空间的软连接信息。初始是空的,当手动增加表空间时,该目录下会自动生成一个软连接,指向表空间设定的路径。
表空间操作的一系列命令:
https://www.cnblogs.com/yanshw/p/11351136.html
1.3 表空间与数据库的关系
一个表空间可以让多个数据库使用,而一个数据库可以使用多个表空间,属于“多对多”的关系。
Oracle中,一个表空间只属于一个数据库,而一个数据库可以使用多个表空间,属于“一对多”的关系。
2. 数据库(database)
在postgre数据库中,数据库(database)可以认为是物理层面数据集合。
2.1 应用场景:
- 当使用不同的文字编码/排序规则等管理数据对象时,不同的文字编码规则/排序规则要创建独立的的数据库。Postgre关于文字编码/排序规则等行为的默认规则是以Database为单位的。
- 当需要对一组数据库表(或函数等)的并发数进行单独控制时,需要对这些表(或函数等)放入一个新建的Database中,postgre对最大并发访问会话进行单独控制的最小单元是Database。
- 当需要对一组数据库表(或函数等数据库对象)的访问进行严格隔离时(不仅仅是通过SQL层面的priviledge来控制),在postgre中,对于Access的控制,除了SQL级别的权限控制之外,可以在pg_hba.conf配置文件中进行会话级别的认证控制。会话级别的高精度访问控制可做到:【1】会话来源(IP地址);【2】会话所使用的数据库用户;【3】会话连接目标的Database名
2.2 用法实践:
PostgreSQL数据库创建一般使用ctreate database SQL语句来创建。
首先使用具有登陆和创建数据权限的角色登陆postgreSQL。
查看已存在数据库。使用\l指令
创建新数据库:user2
删除数据库:User2
进入目标数据库:User1,并在User1数据库中创建表:table1。
3. 模式(Schema)
在postgre数据库中,模式(schema)可以认为是逻辑层面数据集合,不同与数据库(database)物理层面的数据集合。Schema是数据库内部用于组织管理数据库对象的逻辑集合,schema下是各种应用程序会接触到的对象,比如:表、索引、数据类型、函数、操作符等。
3.1 应用场景:
当多个用户想使用同一个数据库,而这些用户之间又不能相互干扰。
当存在多个数据对象时,可以按业务或某种逻辑把对象组织成逻辑组。易管理和维护。
当集成第三方应用时,可以将第三方应用放在不同的模式中,可避免与其它已有数据对象在名字中的冲突。
总结:一般使用,一个用户对应一个schema,该用户的schema名等于用户名,并作为该用户缺省的schema模式权限:
一个新建的postgre数据包含一个叫public的预定义模式。
\dn+ 列出当前数据库的所有的模式和相关的权限。如下图:
第一列:当前数据库中模式的名称
第二列:当前数据库中每一个模式的所有者,默认为创建这个模式的角色。
第三列:模式的访问权限。
权限信息的格式为(左到右):权限接受者、权限、权限授予者。图中第二行第三列的权限信息可以解读为:postgres(权限接受者)=UC(权限)/postgres(权限授予者)。
对模式来说只有两种可以被授予的权限:USAGE和CREATE,对应权限信息中的的U和C。
USAGE权限允许角色查询数据库对象,例如包含在模式中的表和视图。
CREATE权限允许角色在模式中创建数据库对象。
有多个相关权限信息时,列出权限信息时会使用加号来分隔,而且我们注意到public模式的权限中,第二行里接受权限者为空字符串,这代表权限会授予给所有的用户。
新创建的用户默认对所有public模式都有UC权限。上图中我执行了public模式的create权限回收操作:revoke create on schema public from public。所以上图中二行三列“+”号后只有“U”。
3.2 用法实践:
如上图:在postgis01数据中,存在postgis01、public、topology三个模式(schema),这三个模式的拥有者分别为:postgis01、postgres(后两个)。
(1)以postgres用户连接postgis01数据库,分别在postgis01和public 模式中创建表:“table10”进行验证:
结果:创建都是ok。Postgres是超级用户
(2)以postgis01用户连接postgis01数据库,分别在postgis01和public 模式中创建表:“table11”进行验证:
结果:我们发现在postgis01模式中创建表成功,在public模式中创建表失败,报不具备权限的错误。Postgis01用户是postgis01模式的拥有者。
(3)创建一个新用户user1(默认),观察当前数据库【模式权限列表】,以这个新用户连接postgis01数据库,分别在postgis01和public 模式中创建表:“table12”进行验证:
首先从postgis01用户切换到postgres用户。备注:postgis01没有给设置创建角色权限。
使用create user user1 with password ‘****’ 创建新用户user1。
切换到新用户连接数据库,查看【模式权限列表】没有发生任何变化。
在postgis01和public模式下创建表:”table12”。
结果:都创建失败,报没有权限的error。User1用户既不是超级用户,也不是postgis01和public模式的拥有者。
3.3 GRANT和REVOKE
这两条指令分别用来添加或撤销模式中的相应权限。
标准格式; Revoke create on schema 【模式名称】 from 【角色名称】
角色名称为:public 时,代表所有用用户
(1)移除所有用户对postgis01数据库中public模式的查询权限usage。
Revoke create on schema public from public 这条语句中,使用了两个public,第一个public 代表postgis01数据库的public模式,第二个public代表了all users。在实际使用中第一个public可以是数据库中任意有效的模式名,第二个public可以为一个特定的角色名或以逗号分隔的角色名列表。
结论:=“u/postgres” 没有再出现,所有新建用户,将不具有对postgis01数据库中public模式下的对象有任何操作(包括查询和创建)。
(2)让所有用户具有对postgis01数据库中public模式的create(创建数据库对象)权限。
切换到postgres用户。执行\dn+指令,发现除postgres用户外,其他用户都没有对public模式进行create的操作权限。
执行命令:Grant create on schema public to public; 再查看用户对public模式的权限(此时所有用户都具有对public模式具有create权限)
切换到刚才新建的用户:user1;
使用用户user1在postgis01数据库的public模式中创建表:table20。
使用用户user1在postgis01数据库的postgis01模式中创建表:table20。
结论:使用用户user1,在public模式中创建表table20 成功。在postgis01模式中创建表table20失败。
3.4 模式搜索路径
应用场景
postgreSQL数据库引入模式后,如果一个用户具有对几个模式的访问权限,当这个用户要访问某个模式(schema)中的表时,为了精确搜索到这张表我们很容易就会想到在这个表名前加上特定的模式名称。postgreSQL也是支持这样的路径定位方式,同时postgreSQL也提供了“模式搜索路径的机制”来让我们在应用中省略在表名前加模式名称的过程。
深入学习:
首先切换到超级管理员角色postgres,执行指令:show search_path; 返回当前【搜索路径缺省设置】如下图:
“$user”,表示搜索与用户名称相同的模式(schema)
场景假设:使用用户user1,执行:create table table21(id int)语句,来创建一个table21的表。
(1)psql首先尝试在user1模式中创建table21。如果user1模式不存在,那么会尝试在public模式中创建table21。
(2)由于user1模式不存在,那么会尝试在public模式中创建table21.如果找不到public以此类推。---此处为什么会报错,需要进一步深入排查。
修改模式搜索路径:
使用指令:SET search_path TO myschema,public;
3.5 模式的创建删除
创建指令:CREATE SCHEMA schema_name [ AUTHORIZATION user_name ]
参数:schema_name 模式名称,缺省使用user_name,且不能以pg_开头。
user_name 模式属于的用户,缺省为执行命令的用户。
删除指令:DROP SCHEMA [ IF EXISTS ] name [, ...]。
说明:
1.首先确保执行命令是超级用户,具有创建和删除模式的权限。
2.在创建时,如果指定 user_name,那么新创建模式的拥有者是 当前用户。如果不指定schema_name而指定了user_name,那么新创建模式的名称和用户名称同名(如上图)。
3.在删除时,一般都加上 ‘cascade‘ 关键字,表示删除指定模式,以及模式内包含的东西,如果不加,如果指定模式内还有其它对象,一般会报依赖错误。
4. 角色(role||user)
在postgreSQL数据库中,角色及用户,用户及角色。这种设计理念自我感觉比较反人类,但使用起来,还算比较方便。
角色(用户)是数据库服务器(集群)全局范围内的权限控制系统,用于各种集群范围内所有对象权限管理,角色(用户)不局限于postgreSQL的某个单独的数据库,但角色如果需要登陆数据库管理系统则必须连接到一个数据库上。角色可以拥有各种数据库对象。
用户(登陆角色):具有登陆权限的角色,普通意义上的用户。在pgAdmin中也就是登陆角色
组角色:不具有登陆权限的角色,就是组角色。设计组角色的意义是为了将其作为一个权限集合使用。组角色可以被登陆角色继承,从而让登陆角色具有组角色的权限。
在PostgreSQL数据库中,没有区分角色和用户的概念,"CREATE USER" 为 "CREATE ROLE" 的别名,这两个命令几乎是完全相同的,唯一的区别是唯一的区别是"CREATE USER" 命令创建的用户默认带有LOGIN属性,而"CREATE ROLE" 命令创建的用户默认不带LOGIN属性。但并不代表"CREATE ROLE"创建不出带有LOGIN的用户。
4.1角色创建删除实践
登陆角色和组角色的创建:
CREATE USER name [ [ WITH ] option [ ... ] ]
如图:新建了两个登陆角色user2,user3;新建一个组角色manager。
登陆角色和组角色的删除:都使用DROP ROLE rolename;在删除前确保该角色没有依赖。
4.2 角色权限验证
角色有两种权限:
【角色权限(roleattribute)】,包括登陆、创建角色、创建数据库、修改目录等操作的权限。
【数据库操作权限(privilege)】,包括数据库连接,数据表crud、触发器、存储过程等操作的权限。如:SELECT、INSERT、UPDATE、DELETE、RULE、REFERENCES、TRIGGER、CREATE、TEMPORARY、EXECUTE和USAGE。
超级用户权限,一个角色可以被授予超级用户(Superuser)权限,拥有此权限的角色可以彻底控制PostgreSQL服务,因此授予这种权限是一定要慎重。
4.3 角色继承
PostgreSQL数据库在角色维护中设计了一套机制,这套机制可以理解为“角色继承”。来更加合理的管理维护用户的角色权限。
角色继承:一个角色可以被其它角色继承从而拥有被继承角色的权限,可以被继承的角色也称为组角色,组角色也可以被组角色继承,并且这种角色间的继承关系可以有无限多层(为了不让这种嵌套关系过于复杂,在使用过程中一般不建议多层继承)。继承角色将拥有被继承角色的权限。
登陆角色可以继承组角色,组角色可以继承组角色(注:使用中一般不会为组角色授予登陆权限,即使PostgreSQL具有这样的能力,组角色只是将其作为一个“权限集合”使用,而不是作为一个真真需要登陆的用户角色来使用)。
角色继承验证实践
前置场景:
使用前面创建的登陆角色和组角色:user2,user3,Manage。User2继承Mange
实现思路:
当前三个角色都只有基本权限(都不具备在postgis01数据库中对postgis01模式进行建表的操作权限)。使用用户user2连接postgis01数据库,创建表table31(应该会失败),
给Manager赋予数据库postgis01的postgis01模式的Create权限。然后使用用户user2连接postgis01数据库,再创建表table31(应该会失败)。再切换到Manage角色,创建表table31(应该会成功)
结论:虽然user2角色没有对postgis01模式的Create权限,但user2角色继承于角色manage,manage被赋予create权限,所以基于角色继承机制,user2最后也具有了对postgis01模式的操作权限。
4.5 Set role和Set session Authorization
先介绍PostgreSQL中的两个全局变量:current_user和session_user。执行以下语句即可查询这两个变量的值:
首次登陆,这两个变量的值相同。执行Set role会修改current_user的值,执行 SET SESSION AUTHORIZATION 会同时改变 current_user 和 session_user 的值。
Set role命令的主要特点:
SET ROLE 无须 SUPERUSER 权限即可执行。
SET ROLE 会修改 current_user 变量的值,但不修改 session_user 的值。
一个具备 SUPERUSER 权限的 session_user 同名角色可以通过 SET ROLE 设置为任何用户。
非超级用户可以通过 SET ROLE 设置为 session_user 同名角色或者其所属的组用户。
SET ROLE 命令可以让执行角色获取到所“扮演”角色的全部权限,
Set session authorization命令的主要特点:
只有超级用户才可以执行 SET SESSION AUTHORIZATION 。
SET SESSION AUTHORIZATION 权限在整个会话存续期间都是有效的,也就是说即使超级用户通过 SET SESSION AUTHORIZATION 来“扮演”了一个非超级用户,只要会话未中断,都可以在上面再次执行 SET SESSION AUTHORIZATION 命令。
SET SESSION AUTHORIZATION 会将 current_user 和 session_user 修改为要“扮演”的角色。
具备超级用户权限的 session_user 同名角色可以通过 SET ROLE 来“扮演”任何其他角色。
注意:通过这两条指令修改的值,只在本次会话期间有效。会话结束,会回到原始状态。
4.6 角色数据库操作权限
PostgreSQL对新创建的数据库都会分配一个所有者,所有者通常是执行create语句的角色。数据库所有者和超级用户在初始状态就具有数据库的所有操作权限,要允许其它角色(用户)对数据库进行操作,就必须为该用户设置权限。
在PostgreSQL中,数据库操作权限分为以下几种:
- SELECT:允许从指定的表,视图、序列的执行select操作,也允许使用copy to。
- INSERT:允许将新行insert到执行的表中。
- UPDATE:
- DELETE:
- TRUNCATE:允许在指定的表上创建触发器。
- REFERENCES:允许创建引用指定表或表的指定列的外键约束。
- TRIGGER:允许在指定的表上创建触发器。
- CREATE:允许在数据库中创建新的schema、table、index。
- CONNECT:允许用户连接到指定的数据库,在连接启动时检查此权限。
- TEMPORARY:允许在使用指定数据库时创建临时表。
- EXECUTE:允许使用指定的函数或过程
- USAGE:对于schema,允许访问指定模式中包含的对象。对于sequence,允许使用currval和nextval函数,对于类型和域,允许在创建表、函数和其它模式对象时使用类型或域。
- ALL PRIVILEGES:一次授权所有可用权限。
每一个数据库都有一个information_schema.table_privileges视图,在该视图中可以查询当前数据库用户的所有权限。如图:
information_schema.table_privileges 视图结构说明:
grantor:授权者;grantee:被授权者; table_catalog:数据库名称;
table_schema:模式名称;table_name:表名;privilege_type:权限类型;
is_grantable:是否可以被授予;with_hierarchy:继承
示例如下:
(1)查看某用户的表权限
select * from information_schema.table_privileges where grantee='user_name';
(2)查看usage权限表
select * from information_schema.usage_privileges where grantee='user_name';
(3)查看存储过程函数相关权限表
select * from information_schema.routine_privileges where grantee='user_name';
角色数据库操作权限分配和删除(Grant和Revoke)
Grant 命令的基本语法如下
GRANT privilege [, ...] ON object [, ...] TO { PUBLIC | GROUP group | username }
参数解释:
privilege ? 值可以为:SELECT,INSERT,UPDATE,DELETE, RULE,ALL。
object ? 要授予访问权限的对象名称。可能的对象有: table, view,sequence。
PUBLIC ? 表示所有用户。
GROUP group ? 为用户组授予权限。
Username ? 要授予权限的用户名。PUBLIC 是代表所有用户的简短形式。
REVOKE命令的基本语法如下:
REVOKE privilege [, ...] ON object [, ...] FROM { PUBLIC | GROUP groupname | username }
参数解析参考Grant。
5.表空间、数据库、模式之间的关系
表空间 是一个存储区域,在一个表空间中可以存储多个数据库,尽管PostgreSQL不建议这么做,但我们这么做是完全可行的。
一个数据库并不知道直接存储表结构等对象的,而是在数据库中逻辑创建一个模式,在模式中创建表等对象。将不同的模式指派该不同的角色,可以实现权限分离,又可以通过授权,实现模式间对象的共享,并且,还有一个特点是:public模式可以存储大家都需要访问的对象。
这样,我们的网就形成了,可是,既然一个表在创建的时候可以指定表空间,那么是否可以给一个表指定它所在的数据库表空间之外的表空间呢?答案是肯定的!这么做完全可以:那这不是违背了表属于模式,而模式属于数据库,数据库最终存在于指定表空间这个网的模型了吗?
是的,看上去这确实是不合常理的,但这么做又是有它的道理的,而且现实中,我们往往需要这么做:将表的数据存储在一个较慢的磁盘上的表空间,而将表的索引存储在一个快速的磁盘上的空间。但我们再查看表所属的模式还是没有变的,它依然属于指定的模式。所以这并不违反常理。实际上,PostgreSQL并没有限制一张表必须属于某个特定的表空间,我们之所以会这么认为,是因为在关系递进时,偷欢了一个概念:模式是逻辑存在的,它不受表空间的限制。
PostgreSQL用户权限管理完整的操作,可参考这位网友的博文。
https://www.cnblogs.com/zhoujinyi/p/10939715.html
针对PostgreSQL数据库的,表空间、数据库、模式、角色的基本概念以及简单操作不了解的,可以查阅PostgreSQL的官方文档。