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

【磐维数据库】外表访问权限

jingzeng.huang 2025-07-27
138

一、场景说明
用户U_A创建了外部服务器server_A,创建了表T_A,现在用户U_B要访问外表T_A需要哪一些权限?

二、场景准备

1.创建用户U_A
panweidb=# CREATE USER U_A PASSWORD 'panwei$123';
panweidb=# ALTER USER U_A SYSADMIN;
panweidb=# \du U_A
           List of roles
 Role name | Attributes | Member of
-----------+------------+-----------
 U_A       | Sysadmin   | {}


2.切换到U_A下创建外部服务器
[omm@panwei203 ~]$ gsql -d panweidb -U U_A
panweidb=> CREATE SERVER U_SERVER FOREIGN DATA WRAPPER POSTGRES_FDW OPTIONS(host '192.168.110.91',port '17700',dbname 'panweidb');
CREATE SERVER
--查看外部服务器
1)\des
             List of foreign servers
      Name      |   Owner    | Foreign-data wrapper
----------------+------------+----------------------
 fore_server    | u1         | postgres_fdw
 fore_server    | u2         | postgres_fdw
 pwaudit_server |            | file_fdw
 test_server    | loacluser1 | postgres_fdw
 u_server       | U_A        | postgres_fdw

2) select * from pg_catalog.pg_foreign_server;
panweidb=> select * from pg_catalog.pg_foreign_server;
    srvname     | srvowner | srvfdw | srvtype | srvversion | srvacl |                    srvoptions
----------------+----------+--------+---------+------------+--------+--------------------------------------------------
 pwaudit_server |        0 |  19820 |         |            |        |
 fore_server    |    20725 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 test_server    |    20730 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 fore_server    |    20740 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 u_server       |    20757 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}

需要sysadmin权限才能创建外部服务器,否则会提示权限不足。
panweidb=> CREATE SERVER U_SERVER FOREIGN DATA WRAPPER POSTGRES_FDW OPTIONS(host '192.168.110.91',port '17700',dbname 'panweidb');
ERROR:  permission denied for foreign-data wrapper postgres_fdw
DETAIL:  N/A

3.创建user mapping
user mapping是创建本地服务器的用户映射到外部服务器用户,外部服务器用户需要具有所需访问表的权限。
panweidb=> CREATE USER MAPPING FOR USER SERVER U_SERVER OPTIONS (user 'extuser1', password 'panwei#123');
CREATE USER MAPPING

user_name
要映射到外部服务器的一个现有用户的名称。 CURRENT_USER和USER匹配当前用户的名称。 当PUBLIC被指定时,一个所谓的公共映射会被创建,当没有 特定用户的映射可用时将会使用它。
OPTIONS ( option 'value' [, ... ] )
这个子句指定用户映射的选项。这些选项通常定义该映射实际的用户名和 口令。选项名必须唯一。允许的选项名和值与该服务器的外部数据包装器 有关。

--查看user mapping信息
select * from pg_user_mappings;
 umid  | srvid |   srvname   | umuser |  usename   |                                              umoptions
-------+-------+-------------+--------+------------+-----------------------------------------------------------------------------------------------------
 20718 | 20717 | fore_server |     10 | omm        | {user=u1,password=encryptOptD5SGGRWOLjRHtWoKdB3y6O/9vjCnxsSnPHwbgqKa0EWM0HVNX3XzBDI9GaMcgnvD}
 20736 | 20734 | test_server |  20730 | loacluser1 | {user=extuser1,password=encryptOpt4DegfR/awOY9CyqD77Jgg9NE8lS9TvsN62CCcNkFIZNQb7qJigbNjfxr1aUbnhIR}
 20747 | 20744 | fore_server |  20725 | u1         | {user=u1,password=encryptOptXMRNNzLTd0a+eaMPN5RJMuRp8/Qlnk2z2YRGogM2GPVXAZym3OvAzyEiebS5arzE}
 20748 | 20744 | fore_server |  20740 | u2         | {user=u1,password=encryptOptPAAWy1w4GPwTZZEa2ZQEJxzStdBH0XRFc68F9tk3p0dLHdumXMjWRSlW9rhleBuh}
 20749 | 20717 | fore_server |  20725 | u1         | {user=u1,password=encryptOptciJH8dveiSspVR9TWTV8GN1gQvQayqGqhXokXG0XIubtBXzuIa59lB1o6DyZix3W}
 20756 | 20717 | fore_server |  20740 | u2         | {user=u1,password=encryptOptcJzwV2kitpvaf+zY2dcxDe8A9APn8Ec81kZxcF1igYiA9vfedyIuEWul5fkzl4el}
 20762 | 20761 | u_server    |  20757 | U_A        | {user=extuser1,password=encryptOptH/v9WtG7Ocb8mJokILIcLoZcXk1fQhUN+5oxIzUUrb5wCyC3YtmsiQZOIUICA0Dv}

4.创建外表
说明:创建外表的用户需要映射到外部服务器的用户才能建表
panweidb=> CREATE FOREIGN TABLE F_A(
id INT,
name VARCHAR(10)
) SERVER U_SERVER OPTIONS (SCHEMA_NAME 'extuser1',TABLE_NAME 'extt1');
CREATE FOREIGN TABLE
--查看表
panweidb=> \d
                            List of relations
 Schema |             Name              |     Type      | Owner | Storage
--------+-------------------------------+---------------+-------+---------
 U_A    | F_A                           | foreign table | U_A   |
 public | F_B                           | foreign table | omm   |
 public | pg_type_nonstrict_basic_value | view          | omm   |
 public | pw_login_info                 | view          | omm   |

panweidb=> select * from F_A;
 id | name
----+------
  1 | fw
(1 row)

三、让U_B用户访问U_A下的表

1.创建用户U_B
panweidb=# CREATE USER U_B PASSWORD 'panwei$123';

2.用U_A用户给U_B用户授权
panweidb=>  GRANT USAGE ON SCHEMA  U_A TO U_B;
panweidb=> GRANT SELECT ON ALL TABLES IN SCHEMA U_A TO U_B;


2.切换到U_B用户连接数据库并尝试访问U_A.F_A表
--授完权后,可以看看U_A下的表结构
panweidb=> \d  U_A.*
                  Foreign table "U_A.F_A"
 Column |    Type     | Modifiers | FDW Options | Attalias
--------+-------------+-----------+-------------+----------
 id     | integer     |           |             |
 name   | varchar(10) |           |             |
Server: u_server
FDW Options: (schema_name 'extuser1', table_name 'extt1')
FDW permition: write only

--但是访问表数据时会提示U_B也需要创建映射
panweidb=> select * from U_A.F_A;
ERROR:  user mapping not found for "U_B"
根据提示建立user mapping.那user mapping需要在哪一个用户下建立,还是都一样呢?
1)先尝试在U_B用户下建立user mapping
panweidb=> CREATE USER MAPPING FOR USER SERVER U_SERVER OPTIONS (user 'extuser1', password 'panwei#123');
ERROR:  server "u_server" does not exist
但是在U_B下创建user mapping时会提示U_SERVER不存在,那我们先到U_A下创建测试看看
2)在U_A下为U_B创建映射
panweidb=> CREATE USER MAPPING FOR U_B SERVER U_SERVER OPTIONS (user 'extuser1', password 'panwei#123');
CREATE USER MAPPING
panweidb=> select * from pg_user_mappings;
 umid  | srvid |   srvname   | umuser |  usename   |                                              umoptions
-------+-------+-------------+--------+------------+-----------------------------------------------------------------------------------------------------
 20718 | 20717 | fore_server |     10 | omm        | {user=u1,password=encryptOptD5SGGRWOLjRHtWoKdB3y6O/9vjCnxsSnPHwbgqKa0EWM0HVNX3XzBDI9GaMcgnvD}
 20736 | 20734 | test_server |  20730 | loacluser1 | {user=extuser1,password=encryptOpt4DegfR/awOY9CyqD77Jgg9NE8lS9TvsN62CCcNkFIZNQb7qJigbNjfxr1aUbnhIR}
 20747 | 20744 | fore_server |  20725 | u1         | {user=u1,password=encryptOptXMRNNzLTd0a+eaMPN5RJMuRp8/Qlnk2z2YRGogM2GPVXAZym3OvAzyEiebS5arzE}
 20748 | 20744 | fore_server |  20740 | u2         | {user=u1,password=encryptOptPAAWy1w4GPwTZZEa2ZQEJxzStdBH0XRFc68F9tk3p0dLHdumXMjWRSlW9rhleBuh}
 20749 | 20717 | fore_server |  20725 | u1         | {user=u1,password=encryptOptciJH8dveiSspVR9TWTV8GN1gQvQayqGqhXokXG0XIubtBXzuIa59lB1o6DyZix3W}
 20756 | 20717 | fore_server |  20740 | u2         | {user=u1,password=encryptOptcJzwV2kitpvaf+zY2dcxDe8A9APn8Ec81kZxcF1igYiA9vfedyIuEWul5fkzl4el}
 20762 | 20761 | u_server    |  20757 | U_A        | {user=extuser1,password=encryptOptH/v9WtG7Ocb8mJokILIcLoZcXk1fQhUN+5oxIzUUrb5wCyC3YtmsiQZOIUICA0Dv}
 20770 | 20761 | u_server    |  20766 | U_B        | {user=extuser1,password=encryptOptcC0FiibY2iUIY7l9/sM9fu2k93oPVuLGtint4x/4dnQFc7muaVEKqNwX+szWhUAN}
(8 rows)
再次尝试访问表U_A.F_A,还是会提示u_server服务器不存在。
panweidb=> select * from U_A.F_A;
ERROR:  server "u_server" does not exist

--在U_B下可以查看到u_server,但是不知道它属主
panweidb=> \des
            List of foreign servers
      Name      | Owner | Foreign-data wrapper
----------------+-------+----------------------
 fore_server    |       | postgres_fdw
 fore_server    |       | postgres_fdw
 pwaudit_server |       | file_fdw
 test_server    |       | postgres_fdw
 u_server       |       | postgres_fdw
(5 rows)

panweidb=> select * from pg_catalog.pg_foreign_server;
    srvname     | srvowner | srvfdw | srvtype | srvversion | srvacl |                    srvoptions
----------------+----------+--------+---------+------------+--------+--------------------------------------------------
 pwaudit_server |        0 |  19820 |         |            |        |
 fore_server    |    20725 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 test_server    |    20730 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 fore_server    |    20740 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
 u_server       |    20757 |  20716 |         |            |        | {host=192.168.110.91,port=17700,dbname=panweidb}
(5 rows)

在磐维数据库中,只有外部服务器的owner才能访问到外部服务器。
此时我们可以在U_B下创建一个同名的外部服务器,但是U_B用户并没有sysadmin权限,我们要怎么创建外部服务器呢?
我们可以先用具有sysadmin权限的用户创建一个server,再通过修改owner方式让U_B拥有一个同名的外部服务器。
omm用户下:
panweidb=# CREATE SERVER U_SERVER FOREIGN DATA WRAPPER POSTGRES_FDW OPTIONS(host '192.168.110.91',port '17700',dbname 'panweidb');
CREATE SERVER
panweidb=# \des
              List of foreign servers
      Name      |   Owner    | Foreign-data wrapper
----------------+------------+----------------------
 fore_server    | u1         | postgres_fdw
 fore_server    | u2         | postgres_fdw
 pwaudit_server |            | file_fdw
 test_server    | loacluser1 | postgres_fdw
 u_server       | U_A        | postgres_fdw
 u_server       | omm        | postgres_fdw
panweidb=# ALTER SERVER U_SERVER OWNER TO U_B;
ALTER SERVER
panweidb=# \des
              List of foreign servers
      Name      |   Owner    | Foreign-data wrapper
----------------+------------+----------------------
 fore_server    | u1         | postgres_fdw
 fore_server    | u2         | postgres_fdw
 pwaudit_server |            | file_fdw
 test_server    | loacluser1 | postgres_fdw
 u_server       | U_A        | postgres_fdw
 u_server       | U_B        | postgres_fdw

此时在切换到U_B下,查看外部服务器及访问外表U_A.F_A
panweidb=> \des
            List of foreign servers
      Name      | Owner | Foreign-data wrapper
----------------+-------+----------------------
 fore_server    |       | postgres_fdw
 fore_server    |       | postgres_fdw
 pwaudit_server |       | file_fdw
 test_server    |       | postgres_fdw
 u_server       |       | postgres_fdw
 u_server       | U_B   | postgres_fdw


panweidb=> select * from U_A.F_A;
 id | name
----+------
  1 | fw
(1 row)

至此,U_B用户成功访问U_A下的外表F_A.

给大家留个思考:
在上面如果我们先在U_B下创建完外部服务器,然后在U_B下创建为U_B创建user mapping是否能让U_B访问到U_A的外表呢?

四、总结
U_B访问U_A下的外部表,需要具备哪些步骤:
1)在U_B上创建同名的服务器,这时才能访问到U_A的外部服务器
2)需要在U_A下创建U_B到外部服务器的user mapping
3) 给U_B 访问U_A的schema权限和表权限

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论