MySQL无原生分片功能,权限(GRANT/REVOKE)仅控制库表访问,无法实现物理分片隔离;分片路由、键值映射等必须由应用或中间件完成,数据库只负责按分片库精确授权并禁止跨库访问。

MySQL 没有原生分片功能,权限不能实现数据分片
直接说结论:GRANT 和 REVOKE 只能控制「谁能看到哪些表/库」,无法让不同用户写入物理上隔离的分片表。所谓“用权限做分片”,本质是应用层路由 + 权限隔离的组合策略,不是 MySQL 自己在拆数据。
常见误解是:给用户 A 授予 db_shard_01.users 的权限,给用户 B 授予 db_shard_02.users 的权限,就等于实现了分片。但问题在于——users 表结构相同、逻辑上仍是同一张业务表,MySQL 不知道它们是“同一个分片键的不同副本”。分片路由、键值映射、跨分片查询这些事,它一概不管。
真正可行的分片用户管理:按分片库+表级权限划分
如果你已用中间件(如 MyCat、ShardingSphere)或应用自己做了分片路由,那数据库侧的用户管理就该配合这个逻辑:每个分片库独立授权,且禁止跨库访问。
CREATE USER 'shard_app_user_01'@'%' IDENTIFIED BY 'pwd';GRANT SELECT, INSERT, UPDATE ON shard_db_01.* TO 'shard_app_user_01'@'%';REVOKE DROP, ALTER, CREATE ON *.* FROM 'shard_app_user_01'@'%';- 务必执行
FLUSH PRIVILEGES;,否则权限不生效 - 不要授
ON *.*或ON shard_db_*. *—— 通配符在 MySQL 权限系统中不支持正则,shard_db_*会被当作字面量库名,无效
容易踩的坑:权限粒度与分片一致性错位
最常出问题的是「读写分离场景下分片用户被误复用」。比如主库用 shard_app_user_01 写 shard_db_01,但从库也给了它 SELECT 权限,结果应用没控制好路由,把本该查 shard_db_02 的请求发到了 shard_db_01 的从库上——查不到数据,还误以为是分片逻辑错了。
- 分片用户应严格绑定「单一分片库 + 明确角色」:写用户只给主库分片库的 DML 权限;读用户只给对应从库分片库的
SELECT - 避免用同一用户名在多个分片库上重复授权,MySQL 不会报错,但权限叠加后行为难预测
-
SHOW GRANTS FOR 'user'@'host'要逐个检查,确认没有意外继承的全局权限(比如mysql库权限) - 如果用了代理层(如 ProxySQL),注意它可能缓存用户权限,修改后需重启或刷新规则
为什么不能依赖视图或存储过程模拟分片?
有人想建一个 users 视图,UNION ALL 所有分片表,再给用户授视图权限。这看似“透明分片”,实则危险:
- 跨分片
INSERT会失败(视图不可更新,除非所有分片表都满足可更新视图条件,而实际分片表通常有不同主键策略) -
WHERE user_id = ?无法下推到具体分片,MySQL 会全表扫描所有分片表,性能崩盘 - 事务中涉及多分片时,视图无法保证原子性——一个分片成功、另一个失败,应用层无法回滚
- DDL 变更(如加字段)必须同步操作所有分片表,视图本身不解决这个运维复杂度
分片不是权限问题,也不是语法糖能绕开的。核心逻辑必须落在应用或中间件里,数据库只负责守住边界——哪个用户,能碰哪块磁盘上的哪些文件。










