oracle实例、schema,以及多租户方案

本文探讨了Oracle数据库中的实例、Schema概念,以及如何实现多租户方案。Schema与User一一对应,是数据库对象的集合。面对多项目需求,提出了两种方案:一是按项目分配不同Schema,需要解决数据库路由问题;二是所有项目数据存于同一表,通过项目ID区分,但可能面临数据库压力。两种方案各有优缺点,对ORM框架提出了挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从定义中我们可以看出schema为数据库对象的集合,为了区分各个集合,我们需要给这个集合起个名字,这些名字就是我们在企业管理器的方案下看到的许多类似用户名的节点,这些类似用户名的节点其实就是一个schema,schema里面包含了各种对象如tables, views, sequences, stored procedures, synonyms, indexes, clusters, and database links。

一个用户一般对应一个schema,该用户的schema名等于用户名,并作为该用户缺省schema。这也就是我们在企业管理器的方案下看到schema名都为数据库用户名的原因。Oracle数据库中不能新创建一个schema,要想创建一个schema,只能通过创建一个用户的方法解决(Oracle中虽然有create schema语句,但是它并不是用来创建一个schema的),在创建一个用户的同时为这个用户创建一个与用户名同名的schem并作为该用户的缺省shcema。即schema的个数同user的个数相同,而且schema名字同user名字一一 对应并且相同,所有我们可以称schema为user的别名,虽然这样说并不准确,但是更容易理解一些。

一个用户有一个缺省的schema,其schema名就等于用户名,当然一个用户还可以使用其他的schema。如果我们访问一个表时,没有指明该表属于哪一个schema中的,系统就会自动给我们在表上加上缺省的sheman名。比如我们在访问数据库时,访问scott用户下的emp表,通过select * from emp; 其实,这sql语句的完整写法为select * from scott.emp。在数据库中一个对象的完整名称为schema.object,而不属user.object。类似如果我们在创建对象时不指定该对象的schema,在该对象的schema为用户的缺省schema。这就像一个用户有一个缺省的表空间,但是该用户还可以使用其他的表空间,如果我们在创建对象时不指定表空间,则对象存储在缺省表空间中,要想让对象

### 多租户架构下数据库拆分实现方案多租户架构中,数据库拆分的实现通常有多种方案,包括逻辑隔离物理隔离。以下是几种常见的实现方式及其技术细节: #### 1. 数据库共享 + 表内数据隔离(逻辑隔离) 在这种方案中,所有租户共享同一个数据库实例表结构,但通过在表中添加一个 `tenant_id` 字段来区分不同租户的数据[^2]。每次查询时,都需要动态地将 `tenant_id` 加入到 SQL 查询条件中。 ```sql -- 示例:在查询时加入 tenant_id 条件 SELECT * FROM orders WHERE tenant_id = ? AND status = 'active'; ``` 为了确保数据隔离的安全性,可以在应用层或数据库层实现动态 SQL 拼接,或者使用 MyBatis-Plus 的拦截器机制自动注入 `tenant_id`[^1]。 #### 2. 数据库共享 + 租户 Schema 隔离(逻辑隔离) 此方案中,所有租户共享同一个数据库实例,但每个租户拥有独立的 Schema(或用户)。这种模式适用于支持多 Schema 的数据库,如 Oracle 或 PostgreSQL[^2]。 ```sql -- 示例:切换到特定租户Schema SET search_path TO tenant_schema_001; SELECT * FROM orders WHERE status = 'active'; ``` 可以通过动态修改数据库连接的 Schema 或使用多数据源切换技术实现该方案。 #### 3. 数据库实例隔离(物理隔离) 在这种方案中,每个租户拥有独立的数据库实例,完全实现了物理隔离。这可以避免租户间的数据冲突性能干扰[^3]。 ```java // 示例:基于 Dynamic Datasource 实现多租户数据库实例隔离 @MapperScan("com.ruoyi.system.mapper") public class TenantDatasourceConfig { @Bean public DataSource dataSource() { DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource(); Map<Object, Object> dataSourceMap = new HashMap<>(); // 添加租户 A 的数据源 DruidDataSource tenantADataSource = createDataSource("jdbc:mysql://tenant-a-db:3306/tenant_a"); dataSourceMap.put("tenant_a", tenantADataSource); // 添加租户 B 的数据源 DruidDataSource tenantBDataSource = createDataSource("jdbc:mysql://tenant-b-db:3306/tenant_b"); dataSourceMap.put("tenant_b", tenantBDataSource); dynamicDataSource.setTargetDataSources(dataSourceMap); dynamicDataSource.setDefaultTargetDataSource(tenantADataSource); return dynamicDataSource; } } ``` 通过动态数据源切换技术,可以根据当前请求的租户信息选择对应的数据源[^1]。 #### 4. 分布式数据库架构(物理隔离) 对于大规模多租户场景,可以采用分布式数据库架构,如 TiDB 或 ShardingSphere。每个租户可以配置独立的分片规则,甚至实现读写分离、一主多从等高级功能。 ```yaml # 示例:ShardingSphere 中的分片规则配置 dataSources: ds_0: url: jdbc:mysql://tenant-a-db:3306/tenant_a?serverTimezone=UTC&useSSL=false username: root password: root ds_1: url: jdbc:mysql://tenant-b-db:3306/tenant_b?serverTimezone=UTC&useSSL=false username: root password: root shardingRule: tables: orders: actualDataNodes: ds_${0..1}.orders databaseStrategy: inline: shardingColumn: tenant_id algorithmExpression: ds_${tenant_id % 2} ``` #### 成本与适用场景分析 - **逻辑隔离**:适合中小型多租户场景,成本较低,但可能存在性能瓶颈安全风险。 - **物理隔离**:适合对数据安全性性能要求较高的场景,但硬件运维成本较高。 - **分布式架构**:适合超大规模多租户场景,能够支持海量数据高并发访问,但复杂度较高[^4]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值