PostgreSQL 多租户

简介:

PostgreSQL 多租户

作者

digoal

日期

2016-11-07

标签

PostgreSQL , 多租户 , schema , DATABASE , PDB , Oracle 12c


背景

Oracle 12c提出了数据库多租户的概念,即PDBs(私有数据库),因为早期Oracle的设计是以schema为隔离的,schema的隔离不够彻底,原因是通过赋权就很容易获得不同SCHEMA下的数据。

PDB的设计与PostgreSQL的Database概念非常相似,所以PostgreSQL实际上很适合用来实现类似PDB的场景,也即是多租户的场景。

用户可以参考我写的《PostgreSQL 逻辑结构 和 权限体系 介绍》

实际上如果不需要彻底的隔离,可以考虑继续使用schema。

使用数据库或SCHEMA作为多租户的基础,各有优劣。

基于数据库的多租户

1. 优点

数据库隔离较为彻底,从认证层面就开始隔离了,数据库与数据库之间也无法直接访问,必须要登陆到对方的数据库中才能访问对方的数据(即使使用fdw, dblink也是有登陆的过程的)。

登陆时可以通过pg_hba.conf控制来源IP,用户是否有权限登陆目标库。

同时在数据库中的权限体系中还可以配置是否允许用户访问目标库,或者在目标库创建SCHEMA。

2. 缺点

因为每个数据库对应了各自的元信息,大概有几百个文件,所以如果租户比较多,数据库也会比较多。

基于schema的多租户

1. 优点

单个数据库,多个SCHEMA的方式,比较轻巧,如果是企业私有的多租户,可以这样使用。

通过数据库的权限体系隔离用户,访问不同SCHEMA。

2. 缺点

无法通过pg_hba.conf控制schema的权限,权限隔离可能不够彻底。

用户可通过查看元表,观察到其他schema的对象,定义等信息,不安全。如果是企业内部私有的,并且这部分缺陷不敏感时可以使用。

创建租户和删除租户需要产生大量元数据,或删除大量元数据,可能导致STANDBY长时间延迟。详见

《PostgreSQL DaaS设计注意 - schema与database的抉择》

例子

基于database

创建用户
create role 租户名 login ...;


配置防火墙
pg_hba.conf
host 数据库 用户 来源IP md5


从模板创建数据库
create database db with template templatexxx;


回收权限
revoke all on database db from public;


赋权
grant all on database db to 租户;

基于schema

创建用户
create role 租户名 login ...;

创建schema
create schema xx;

回收权限
revoke all on schema xx from public;

赋权
grant all on schema xx to 租户;

以schema为例的多租户路由选择

例如通过客户端application_name或者客户端IP地址,区分不同的租户。

每个租户的模板完全一样,只是使用了不同的schema。

客户使用search_path修改路径,完成对路由的选择。

一套程序,完成多租户的方法:

建立会话后,首先选择路由(即根据客户端IP或设置的application_name,设置对应的路由)。

也可以每次设置路由(开销大,较浪费)。

后续的操作则会自动匹配对应的schema.

路由函数举例

以application_name为schema命名

create or replace function public.route() returns void as $$
declare  
begin
  execute 'set search_path='||current_setting('application_name')||', "$user", public' ;
end;
$$ language plpgsql strict;
postgres=# select public.route();
 route 
-------

(1 row)

postgres=# show search_path ;
      search_path      
-----------------------
 psql, "$user", public
(1 row)

接下来的SQL都会首先搜索psql中的对象。

如果schema很多,而且要经常调用,建议写成C function,使用更高效的匹配算法,例如hash search。

在业务函数中封装选择函数的例子。

create or replace function 业务函数(参数) returns  xx as $$
declare
  xx;
begin
  perform 路由函数(影响路由选择的参数);
  业务SQL;
  ////
end;
$$ language plpgsql strict;
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
前端开发 JavaScript 搜索推荐
Marp 入门与教程:让你一分钟爱上代码写PPT的乐趣
Marp 是一个基于 Markdown 的开源幻灯片制作工具,可将 Markdown 文档轻松转换为精美幻灯片。支持 VS Code 插件实时预览、命令行工具批量处理、自定义主题等,适用于技术分享、工作汇报和教学等多种场景。相比 LaTeX Beamer,Marp 学习成本低,跨平台支持好,设计现代美观。
|
机器学习/深度学习 人工智能 算法
展望2024: 中国AI算力能否引爆高性能计算和大模型训练的新革命?
2023年是人工智能发展的重要转折年,企业正在从业务数字化迈向业务智能化。大模型的突破和生成式人工智能的兴起为企业实现产品和流程的革新提供了先进工具,引领产业迈入智能创新的新阶段。在这个新时代,企业不再仅关注如何增强智能化能力,而更加注重如何利用人工智能实现产品和流程的革新。
3796 0
|
SQL 运维 关系型数据库
使用Binlog日志恢复误删的MySQL数据
今天文章的主题是如何使用Mysql内置的Binlog日志对误删的数据进行恢复,读完本文,你能够了解到: MySQL的binlog日志是什么?通常是用来干什么的? 模拟一次误删数据的操作,并且使用binlog日志恢复误删的数据。
2450 1
|
人工智能 监控 安全
微信怎么无限制加人?有这种技术吗
微信无限制加人技术解析与合规实践指南
|
Android开发
Uniapp 与原生android的交互 和简单配置
Uniapp 与原生android的交互 和简单配置
2712 0
Uniapp 与原生android的交互 和简单配置
关于支付宝异步通知的那些事
一、如何指定接收异步通知的地址     对于支付产生的交易,支付宝会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果 作为参数通知到商户系统。     以app支付为例,支付请求中notify_url参数的(如下图):      二、异步通知返回参数介绍     支付宝通过POST请求的形式将支付结果作为参数通知到商户系统。
3641 12
|
SQL Java 数据库连接
数据库迁移不再难:Flyway 与 Liquibase 大比拼,哪个才是你的真命天子?
【9月更文挑战第3天】数据库迁移在软件开发中至关重要,尤其在使用 ORM 框架如 Hibernate 时。为确保部署时能顺利应用最新的数据库变更,开发者常使用自动化工具。Flyway 和 Liquibase 是当前流行的两种选择,均能有效管理数据库版本控制。Flyway 采用 SQL 脚本表示变更,简单易用;Liquibase 支持多种脚本格式,功能更强大,适合复杂项目。本文将对比这两种工具的特点,并通过示例展示各自的优缺点,帮助开发者根据项目需求做出合适的选择。
3802 1
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
751 3
|
Java 开发工具 Maven
java解析apk获取应用信息
请注意,你需要替换"path/to/your/apkfile.apk"为你的APK文件的实际路径。
1065 0
|
关系型数据库 MySQL
解决MySQL insert出现Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘xxx‘ at row 1
解决MySQL insert出现Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘xxx‘ at row 1
1693 2