greatsql教程FG017-GreatSQL多租户架构实战
内容简介
本教程详细介绍GreatSQL数据库的多租户架构,包括多租户架构的概念、实现方式、最佳实践等内容。风哥教程参考GreatSQL官方文档多租户架构指南,帮助读者掌握多租户架构的设计和实现。
多租户架构是一种在单一数据库实例中为多个客户(租户)提供隔离服务的设计模式,广泛应用于SaaS(软件即服务)等场景。本教程将从基础概念入手,逐步深入到实战案例和最佳实践。
目录大纲
Part01-基础概念与理论知识
1.1 多租户架构概述
多租户架构是一种软件架构模式,允许单一实例的应用或数据库服务于多个客户(租户),每个租户的数据相互隔离但共享相同的硬件和软件资源。
多租户架构的核心目标是:
- 资源共享,降低成本
- 数据隔离,保证安全
- 简化管理,提高效率
- 快速部署,灵活扩展
1.2 多租户实现模式
多租户架构的主要实现模式包括:
- 数据库级隔离:为每个租户创建独立的数据库
- Schema级隔离:为每个租户创建独立的Schema
- 表级隔离:在同一表中使用租户ID区分不同租户的数据
- 混合隔离:结合多种隔离方式
1.3 多租户架构的优势与挑战
优势:
- 降低硬件和维护成本
- 简化部署和管理
- 提高资源利用率
- 便于功能升级和统一维护
挑战:
- 数据隔离和安全性
- 性能和资源争用
- 扩展性
- 备份和恢复
Part02-生产环境规划与建议
2.1 多租户架构设计原则
风哥提示:多租户架构设计应考虑隔离性、性能、可扩展性和可维护性等因素。
多租户架构设计原则:
- 隔离性:确保不同租户的数据相互隔离
- 可扩展性:支持租户数量的增长
- 性能:保证各租户的性能不受其他租户影响
- 可维护性:便于管理和维护
- 安全性:保护租户数据安全
2.2 租户隔离策略
租户隔离策略建议:
- 数据库级隔离:适合租户数量较少、数据量较大的场景
- Schema级隔离:适合租户数量中等、数据量适中的场景
- 表级隔离:适合租户数量较多、数据量较小的场景
2.3 性能优化建议
多租户架构性能优化建议:
- 使用索引加速查询
- 合理设计租户ID字段
- 使用连接池管理数据库连接
- 实施资源限制
- 定期清理数据
- 使用缓存减少数据库负载
更多视频教程www.fgedu.net.cn
Part03-生产环境项目实施方案
3.1 多租户架构实施方案
多租户架构实施步骤:
- 选择合适的隔离模式
- 设计数据模型
- 实现租户管理功能
- 配置资源限制
- 实施监控和告警
- 测试和优化
3.2 租户管理方案
租户管理方案:
- 租户注册和认证
- 租户资源分配
- 租户权限管理
- 租户数据备份和恢复
- 租户生命周期管理
3.3 监控与维护方案
监控与维护方案:
- 监控租户资源使用情况
- 监控数据库性能
- 定期备份数据
- 实施数据库优化
- 处理租户请求和问题
Part04-生产案例与实战讲解
4.1 基于数据库的多租户实现
# 创建租户数据库 CREATE DATABASE fgedudb_tenant1 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE fgedudb_tenant2 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE DATABASE fgedudb_tenant3 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
# 创建租户用户 CREATE USER ‘tenant1’@’%’ IDENTIFIED BY ‘Tenant1@123456’; CREATE USER ‘tenant2’@’%’ IDENTIFIED BY ‘Tenant2@123456’; CREATE USER ‘tenant3’@’%’ IDENTIFIED BY ‘Tenant3@123456’;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
学习交流加群风哥微信: itpux-com
# 授权租户用户 GRANT ALL PRIVILEGES ON fgedudb_tenant1.* TO ‘tenant1’@’%’; GRANT ALL PRIVILEGES ON fgedudb_tenant2.* TO ‘tenant2’@’%’; GRANT ALL PRIVILEGES ON fgedudb_tenant3.* TO ‘tenant3’@’%’; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
# 在租户数据库中创建表
mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “CREATE TABLE fgedu_users (id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL);” mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “INSERT INTO fgedu_users (username, email) VALUES (‘fgedu_user1’, ‘fgedu_user1@fgedu_tenant1.com’), (‘fgedu_user2’, ‘fgedu_user2@fgedu_tenant1.com’);”
mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “CREATE TABLE fgedu_users (id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL);” mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “INSERT INTO fgedu_users (username, email) VALUES (‘fgedu_user1’, ‘fgedu_user1@fgedu_tenant1.com’), (‘fgedu_user2’, ‘fgedu_user2@fgedu_tenant1.com’);”
# 验证租户数据隔离
mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “SELECT * FROM fgedu_users;” mysql -u tenant2 -pTenant2@123456 -D fgedudb_tenant2 -e “SELECT * FROM fgedu_users;”
mysql -u tenant1 -pTenant1@123456 -D fgedudb_tenant1 -e “SELECT * FROM fgedu_users;” mysql -u tenant2 -pTenant2@123456 -D fgedudb_tenant2 -e “SELECT * FROM fgedu_users;”
+—-+———-+——————+
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@fgedu_tenant1.com |
| 2 | fgedu_user2 | fgedu_user2@fgedu_tenant1.com |
+—-+———-+——————+
ERROR 1146 (42S02): Table ‘fgedudb_tenant2.fgedu_users’ doesn’t exist
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@fgedu_tenant1.com |
| 2 | fgedu_user2 | fgedu_user2@fgedu_tenant1.com |
+—-+———-+——————+
ERROR 1146 (42S02): Table ‘fgedudb_tenant2.fgedu_users’ doesn’t exist
4.2 基于Schema的多租户实现
# 创建租户Schema CREATE SCHEMA tenant1; CREATE SCHEMA tenant2; CREATE SCHEMA tenant3;
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
Query OK, 1 row affected (0.01 sec)
# 创建租户用户并授权 CREATE USER ‘schema_tenant1’@’%’ IDENTIFIED BY ‘SchemaTenant1@123456’; CREATE USER ‘schema_tenant2’@’%’ IDENTIFIED BY ‘SchemaTenant2@123456’; GRANT ALL PRIVILEGES ON tenant1.* TO ‘schema_tenant1’@’%’; GRANT ALL PRIVILEGES ON tenant2.* TO ‘schema_tenant2’@’%’; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
学习交流加群风哥QQ113257174
# 在租户Schema中创建表
mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “CREATE TABLE tenant1.fgedu_users (id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL);” mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “INSERT INTO tenant1.fgedu_users (username, email) VALUES (‘fgedu_user1’, ‘fgedu_user1@schema1.com’), (‘fgedu_user2’, ‘fgedu_user2@schema1.com’);”
mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “CREATE TABLE tenant1.fgedu_users (id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL);” mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “INSERT INTO tenant1.fgedu_users (username, email) VALUES (‘fgedu_user1’, ‘fgedu_user1@schema1.com’), (‘fgedu_user2’, ‘fgedu_user2@schema1.com’);”
# 验证租户数据隔离
mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “SELECT * FROM tenant1.fgedu_users;” mysql -u schema_tenant2 -pSchemaTenant2@123456 -e “SELECT * FROM tenant1.fgedu_users;”
mysql -u schema_tenant1 -pSchemaTenant1@123456 -e “SELECT * FROM tenant1.fgedu_users;” mysql -u schema_tenant2 -pSchemaTenant2@123456 -e “SELECT * FROM tenant1.fgedu_users;”
+—-+———-+——————+
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@schema1.com |
| 2 | fgedu_user2 | fgedu_user2@schema1.com |
+—-+———-+——————+
ERROR 1142 (42000): SELECT command denied to user ‘schema_tenant2’@’%’ for table ‘fgedu_users’
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@schema1.com |
| 2 | fgedu_user2 | fgedu_user2@schema1.com |
+—-+———-+——————+
ERROR 1142 (42000): SELECT command denied to user ‘schema_tenant2’@’%’ for table ‘fgedu_users’
4.3 基于表的多租户实现
# 创建带有租户ID的表 CREATE TABLE fgedudb.fgedu_multi_tenant_users ( id INT PRIMARY KEY AUTO_INCREMENT, tenant_id INT NOT NULL, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, INDEX idx_tenant_id (tenant_id) );
Query OK, 0 rows affected (0.01 sec)
# 插入多租户数据 INSERT INTO fgedudb.fgedu_multi_tenant_users (tenant_id, username, email) VALUES (1, ‘fgedu_user1’, ‘fgedu_user1@fgedu_tenant1.com’), (1, ‘fgedu_user2’, ‘fgedu_user2@fgedu_tenant1.com’), (2, ‘fgedu_user1’, ‘fgedu_user1@fgedu_tenant2.com’), (2, ‘fgedu_user2’, ‘fgedu_user2@fgedu_tenant2.com’), (3, ‘fgedu_user1’, ‘fgedu_user1@fgedu_tenant3.com’);
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
Records: 5 Duplicates: 0 Warnings: 0
# 创建租户视图 CREATE VIEW fgedudb.tenant1_users AS SELECT id, username, email FROM fgedudb.fgedu_multi_tenant_users WHERE tenant_id = 1; CREATE VIEW fgedudb.tenant2_users AS SELECT id, username, email FROM fgedudb.fgedu_multi_tenant_users WHERE tenant_id = 2;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
# 创建租户用户并授权视图 CREATE USER ‘fgedu_table_tenant1’@’%’ IDENTIFIED BY ‘fgedu@123456’; CREATE USER ‘fgedu_table_tenant2’@’%’ IDENTIFIED BY ‘fgedu@123456’; GRANT SELECT, INSERT, UPDATE, DELETE ON fgedudb.tenant1_users TO ‘fgedu_table_tenant1’@’%’; GRANT SELECT, INSERT, UPDATE, DELETE ON fgedudb.tenant2_users TO ‘fgedu_table_tenant2’@’%’; FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
# 验证租户数据隔离
mysql -u fgedu_table_tenant1 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant1_users;” mysql -u fgedu_table_tenant2 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant2_users;” mysql -u fgedu_table_tenant1 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant2_users;”
mysql -u fgedu_table_tenant1 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant1_users;” mysql -u fgedu_table_tenant2 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant2_users;” mysql -u fgedu_table_tenant1 -pfgedu@123456 -e “SELECT * FROM fgedudb.tenant2_users;”
+—-+———-+——————+
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@fgedu_tenant1.com |
| 2 | fgedu_user2 | fgedu_user2@fgedu_tenant1.com |
+—-+———-+——————+
+—-+———-+——————+
| id | username | email |
+—-+———-+——————+
| 3 | fgedu_user1 | fgedu_user1@fgedu_tenant2.com |
| 4 | fgedu_user2 | fgedu_user2@fgedu_tenant2.com |
+—-+———-+——————+
ERROR 1142 (42000): SELECT command denied to user ‘fgedu_table_tenant1’@’%’ for table ‘tenant2_users’
| id | username | email |
+—-+———-+——————+
| 1 | fgedu_user1 | fgedu_user1@fgedu_tenant1.com |
| 2 | fgedu_user2 | fgedu_user2@fgedu_tenant1.com |
+—-+———-+——————+
+—-+———-+——————+
| id | username | email |
+—-+———-+——————+
| 3 | fgedu_user1 | fgedu_user1@fgedu_tenant2.com |
| 4 | fgedu_user2 | fgedu_user2@fgedu_tenant2.com |
+—-+———-+——————+
ERROR 1142 (42000): SELECT command denied to user ‘fgedu_table_tenant1’@’%’ for table ‘tenant2_users’
Part05-风哥经验总结与分享
5.1 多租户架构最佳实践
- 选择合适的隔离模式:根据租户数量和数据量选择合适的隔离模式
- 合理设计租户ID:使用整数或UUID作为租户ID
- 实施资源限制:限制每个租户的资源使用
- 使用连接池:管理数据库连接,提高性能
- 实施监控:监控租户资源使用和数据库性能
- 定期清理数据:清理过期数据,优化存储空间
- 备份策略:实施合理的备份策略,确保数据安全
5.2 常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 租户数据泄露 | 实施严格的权限管理,使用视图或存储过程限制数据访问 |
| 性能下降 | 优化查询,使用索引,实施资源限制 |
| 资源争用 | 实施连接池,限制并发连接数 |
| 备份困难 | 使用分区表,实施增量备份 |
| 扩展性问题 | 使用分库分表,实施水平扩展 |
更多学习教程公众号风哥教程itpux_com
5.3 性能优化技巧
# 创建租户管理存储过程 DELIMITER // CREATE PROCEDURE fgedudb.create_tenant( IN tenant_id INT, IN tenant_name VARCHAR(50), IN tenant_password VARCHAR(100) ) BEGIN — 创建租户数据库 SET @db_name = CONCAT(‘fgedudb_tenant’, tenant_id); SET @create_db = CONCAT(‘CREATE DATABASE ‘, @db_name, ‘ CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci’); PREPARE stmt FROM @create_db; EXECUTE stmt; DEALLOCATE PREPARE stmt; — 创建租户用户 SET @user_name = CONCAT(‘tenant’, tenant_id); SET @create_user = CONCAT(‘CREATE USER ”’, @user_name, ”’@”%” IDENTIFIED BY ”’, tenant_password, ””); PREPARE stmt FROM @create_user; EXECUTE stmt; DEALLOCATE PREPARE stmt; — 授权租户用户 SET @grant_priv = CONCAT(‘GRANT ALL PRIVILEGES ON ‘, @db_name, ‘.* TO ”’, @user_name, ”’@”%”’); PREPARE stmt FROM @grant_priv; EXECUTE stmt; DEALLOCATE PREPARE stmt; — 刷新权限 FLUSH PRIVILEGES; — 记录租户信息 INSERT INTO fgedudb.tenants (id, name, database_name, username) VALUES (tenant_id, tenant_name, @db_name, @user_name); END // DELIMITER ;
Query OK, 0 rows affected (0.01 sec)
# 创建租户表 CREATE TABLE fgedudb.tenants ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL, database_name VARCHAR(100) NOT NULL, username VARCHAR(50) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );
Query OK, 0 rows affected (0.01 sec)
# 调用存储过程创建租户 CALL fgedudb.create_tenant(4, ‘Tenant4’, ‘Tenant4@123456’); SELECT * FROM fgedudb.tenants;
Query OK, 1 row affected (0.01 sec)
+—-+——–+—————+———-+———————+
| id | name | database_name | username | created_at |
+—-+——–+—————+———-+———————+
| 4 | Tenant4 | fgedudb_tenant4 | tenant4 | 2026-04-09 20:00:00 |
+—-+——–+—————+———-+———————+
+—-+——–+—————+———-+———————+
| id | name | database_name | username | created_at |
+—-+——–+—————+———-+———————+
| 4 | Tenant4 | fgedudb_tenant4 | tenant4 | 2026-04-09 20:00:00 |
+—-+——–+—————+———-+———————+
多租户监控脚本
# 创建多租户监控脚本
cat > /greatsql/scripts/multi_tenant_monitor.sh << 'EOF'
#!/bin/bash # multi_tenant_monitor.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
echo “=== Multi-Tenant Monitor ===” echo “Date: $(date)” echo “”
# 检查租户数据库大小 TENANTS=$(mysql -u root -pFGedu123456! -e “SELECT database_name FROM fgedudb.tenants” -s) for DB in $TENANTS; do SIZE=$(mysql -u root -pFGedu123456! -e “SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as size FROM information_schema.tables WHERE table_schema = ‘$DB'” -s)
echo “Tenant database $DB: $SIZE MB” done echo “”
# 检查租户连接数
echo “=== Tenant Connections ===” mysql -u root -pFGedu123456! -e “SHOW PROCESSLIST” | grep -E ‘tenant[0-9]’ echo “” echo “Multi-tenant monitoring completed!” EOF
# 设置脚本权限
chmod +x /greatsql/scripts/multi_tenant_monitor.sh
cat > /greatsql/scripts/multi_tenant_monitor.sh << 'EOF'
#!/bin/bash # multi_tenant_monitor.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
echo “=== Multi-Tenant Monitor ===” echo “Date: $(date)” echo “”
# 检查租户数据库大小 TENANTS=$(mysql -u root -pFGedu123456! -e “SELECT database_name FROM fgedudb.tenants” -s) for DB in $TENANTS; do SIZE=$(mysql -u root -pFGedu123456! -e “SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as size FROM information_schema.tables WHERE table_schema = ‘$DB'” -s)
echo “Tenant database $DB: $SIZE MB” done echo “”
# 检查租户连接数
echo “=== Tenant Connections ===” mysql -u root -pFGedu123456! -e “SHOW PROCESSLIST” | grep -E ‘tenant[0-9]’ echo “” echo “Multi-tenant monitoring completed!” EOF
# 设置脚本权限
chmod +x /greatsql/scripts/multi_tenant_monitor.sh
# 执行多租户监控脚本 /greatsql/scripts/multi_tenant_monitor.sh
=== Multi-Tenant Monitor ===
Date: Wed Apr 9 20:00:00 CST 2026
Tenant database fgedudb_tenant1: 0.12 MB
Tenant database fgedudb_tenant2: 0.00 MB
Tenant database fgedudb_tenant3: 0.00 MB
Tenant database fgedudb_tenant4: 0.00 MB
=== Tenant Connections ===
+—-+———–+—————–+—————+———+——+———-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—-+———–+—————–+—————+———+——+———-+——————+
| 10 | tenant1 | 192.168.1.1:12345 | fgedudb_tenant1 | Sleep | 0 | | NULL |
+—-+———–+—————–+—————+———+——+———-+——————+
Multi-tenant monitoring completed!
Date: Wed Apr 9 20:00:00 CST 2026
Tenant database fgedudb_tenant1: 0.12 MB
Tenant database fgedudb_tenant2: 0.00 MB
Tenant database fgedudb_tenant3: 0.00 MB
Tenant database fgedudb_tenant4: 0.00 MB
=== Tenant Connections ===
+—-+———–+—————–+—————+———+——+———-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—-+———–+—————–+—————+———+——+———-+——————+
| 10 | tenant1 | 192.168.1.1:12345 | fgedudb_tenant1 | Sleep | 0 | | NULL |
+—-+———–+—————–+—————+———+——+———-+——————+
Multi-tenant monitoring completed!
风哥提示:多租户架构是SaaS应用的重要技术基础,合理的多租户设计可以显著降低运维成本,提高资源利用率。
from greatsql视频:www.itpux.com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
