PingCAP
  • 文档
  • 案例
  • 博客
  • 关于
  • 下载
PingCAP
  • 文档
  • 案例
  • 博客
  • 关于
  • 下载

Contact

  • 微信扫一扫
    微信ID:pingcap2015

English
文档
  • 关于 TiDB
    • TiDB 简介
    • TiDB 整体架构
    • TiDB 核心特性
  • TiDB 快速入门
    • 快速入门指南
    • SQL 基本操作
  • TiDB 用户文档
    • TiDB 数据库管理
      • TiDB 服务
      • TiDB 进程启动参数
      • TiDB 数据目录
      • TiDB 系统数据库
      • TiDB 系统变量
      • TiDB 专用系统变量和语法
      • TiDB 服务器日志文件
      • TiDB 访问权限管理
      • TiDB 用户账户管理
      • 使用加密连接
    • SQL 优化
      • 理解 TiDB 执行计划
      • 统计信息
    • 语言结构
      • 字面值
      • 数据库、表、索引、列和别名
      • 关键字和保留字
      • 用户变量
      • 表达式语法
      • 注释语法
    • 字符集和时区
      • 字符集支持
      • 字符集配置
      • 时区
    • 数据类型
      • 数值类型
      • 日期和时间类型
      • 字符串类型
      • JSON 数据类型
      • 枚举类型
      • 集合类型
      • 数据类型默认值
    • 函数和操作符
      • 函数和操作符概述
      • 表达式求值的类型转换
      • 操作符
      • 控制流程函数
      • 字符串函数
      • 数值函数与操作符
      • 日期和时间函数
      • 位函数和操作符
      • Cast 函数和操作符
      • 加密和压缩函数
      • 信息函数
      • JSON 函数
      • GROUP BY 聚合函数
      • 其他函数
      • 精度数学
    • SQL 语句语法
      • 数据定义语句 (DDL)
      • 数据操作语句 (DML)
      • 事务语句
      • 数据库管理语句
      • Prepared SQL 语句语法
      • 实用工具语句
      • TiDB SQL 语法图
    • JSON 支持
    • Connectors 和 API
    • TiDB 事务隔离级别
    • 错误码与故障诊断
    • 与 MySQL 兼容性对比
    • TiDB 内存控制
    • 慢查询日志
    • 高级功能
      • 历史数据回溯
      • 垃圾回收 (GC)
  • TiDB 运维文档
    • 软硬件环境需求
    • 部署集群
      • Ansible 部署方案(强烈推荐)
      • 离线 Ansible 部署方案
      • Docker 部署方案
      • Docker Compose 部署方案
      • 跨机房部署方案
    • 配置集群
      • 参数解释
      • TiDB 配置项解释
      • 使用 Ansible 变更组件配置
      • 开启 TLS 验证
      • 生成自签名证书
    • 监控集群
      • 整体监控框架概述
      • 重要监控指标详解
      • 组件状态 API & 监控
    • 扩容缩容
      • 集群扩容缩容方案
      • 使用 Ansible 扩容缩容
    • 升级
      • 升级组件版本
      • TiDB 2.0 升级操作指南
    • 性能调优
    • 备份与迁移
      • 备份与恢复
      • 数据迁移
        • 数据迁移概述
        • 全量导入
        • 增量导入
    • 故障诊断
  • TiDB 周边工具
    • Syncer
    • Loader
    • TiDB-Binlog
    • PD Control
    • PD Recover
    • TiKV Control
    • TiDB Controller
  • TiSpark 文档
    • TiSpark 快速入门指南
    • TiSpark 用户指南
  • 常见问题与解答(FAQ)
  • 最佳实践
  • 版本发布历史
    • 2.1 RC3
    • 2.1 RC2
    • 2.0.7
    • 2.1 RC1
    • 2.0.6
    • 2.0.5
    • 2.1 Beta
    • 2.0.4
    • 2.0.3
    • 2.0.2
    • 2.0.1
    • 2.0
    • 2.0 RC5
    • 2.0 RC4
    • 2.0 RC3
    • 2.0 RC1
    • 1.1 Beta
    • 1.1 Alpha
    • 1.0
    • Pre-GA
    • RC4
    • RC3
    • RC2
    • RC1
  • TiDB 路线图
  • 用户案例
    • 北京银行
    • 海航
    • 今日头条
    • 转转
    • Mobike
    • 饿了么(一)
    • 饿了么(二)
    • 爱奇艺
    • 易果生鲜
    • 同程旅游
    • 去哪儿
    • G7
    • 一面数据
    • 凤凰网
    • 猿辅导
    • Mobikok
    • 二维火
    • 客如云
    • Ping++
    • 乐视云
    • 零氪科技
    • 威锐达测控
    • 盖娅互娱
    • 游族网络
    • 西山居
    • FUNYOURS JAPAN
    • 特来电
    • 万达网络
    • 360金融
    • 中国电信翼支付
    • 某电信运营商
  • 更多资源
    • 常用工具
    • PingCAP 团队技术博客
    • 知乎专栏
    • Weekly
    • 英文文档

权限管理

权限管理概述

TiDB的权限管理系统是按照 MySQL 的权限管理进行实现,大部分的 MySQL 的语法和权限类型都是支持的。如果发现行为跟 MySQL 不一致的地方,欢迎报告 issue。

示例

用户账户操作

更改密码

set password for 'root'@'%' = 'xxx';

添加用户

create user 'test'@'127.0.0.1' identified by 'xxx';

用户名是大小写敏感的。host则支持模糊匹配,比如:

create user 'test'@'192.168.10.%';

允许 test 用户从 192.168.10 子网的任何一个主机登陆。

如果没有指定 host,则默认是所有 IP 均可登陆。如果没有指定密码,默认为空:

create user 'test';

等价于

create user 'test'@'%' identified by '';

删除用户

drop user 'test'@'%';

这个操作会清除用户在 mysql.user 表里面的记录项,并且清除在授权表里面的相关记录。

忘记root密码

使用一个特殊的启动参数启动 TiDB(需要root权限):

sudo ./tidb-server -skip-grant-table=true

这个参数启动,TiDB 会跳过权限系统,然后使用 root 登陆以后修改密码:

mysql -h 127.0.0.1 -P 4000 -u root

权限相关操作

授予权限

授予 xxx 用户对数据库 test 的读权限:

grant Select on test.* to 'xxx'@'%';

为 test 用户授予所有数据库,全部权限:

grant all privileges on *.* to 'xxx'@'%';

如果 grant 的目标用户不存在,TiDB 会自动创建用户。

mysql> select * from mysql.user where user='xxxx';
Empty set (0.00 sec)

mysql> grant all privileges on test.* to 'xxxx'@'%' identified by 'yyyyy';
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.user where user='xxxx';
+------|------+
| user | host |
+------|------+
| xxxx | %    |
+------|------+
1 row in set (0.00 sec)

例子中 xxxx@% 就是自动添加进去的用户。

grant 对于数据库或者表的授权,不检查数据库或表是否存在。

mysql> select * from test.xxxx;
ERROR 1146 (42S02): Table 'test.xxxx' doesn't exist

mysql> grant all privileges on test.xxxx to xxxx;
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.tables_priv where user='xxxx';
+------|------+
| user | host |
+------|------+
| xxxx | %    |
+------|------+
1 row in set (0.00 sec)

grant 可以模糊匹配地授予数据库和表

mysql> grant all privileges on `te%`.* to genius;
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host,db from mysql.db where user='genius';
+--------|------|-----+
| user   | host | db  |
+--------|------|-----+
| genius | %    | te% |
+--------|------|-----+
1 row in set (0.00 sec)

这个例子中通过 % 模糊匹配,所有 te 开头的数据库,都被授予了权限。

收回权限

revoke语句与grant对应:

revoke all privileges on `test`.* from 'genius'@'localhost';

注意 revoke 收回权限时只做精确匹配,若找不到记录则报错。而 grant 授予权限时可以使用模糊匹配。

mysql> revoke all privileges on `te%`.* from 'genius'@'%';
ERROR 1141 (42000): There is no such grant defined for user 'genius' on host '%'

关于模糊匹配和转义,字符串和 identifier

> mysql> grant all privileges on `te\%`.* to 'genius'@'localhost';
> Query OK, 0 rows affected (0.00 sec)
> ```
>
> 这个例子是精确匹配名叫 `te%` 的数据库,注意到用了 `\` 转义字符。
>
> 以单引号包含的,是一个字符串。以反引号包含的,是一个 identifier。注意下面区别:
>
> ```
> mysql> grant all privileges on 'test'.* to 'genius'@'localhost';
> ERROR 1064 (42000): You have an error in your SQL syntax; check the
> manual that corresponds to your MySQL server version for the right
> syntax to use near ''test'.* to 'genius'@'localhost'' at line 1
>
> mysql> grant all privileges on `test`.* to 'genius'@'localhost';
> Query OK, 0 rows affected (0.00 sec)
> ```
>
> 如果一些特殊的关键字想做为表名,可以用反引号包含起来。比如:
>
> ```
> mysql> create table `select` (id int);
> Query OK, 0 rows affected (0.27 sec)
> ```

#### 查看为用户分配的权限

`SHOW GRANT` 语句可以查看为用户分配了哪些权限。

```sql
show grants for 'root'@'%';

更精确的方式,可以通过直接查看授权表的数据实现。比如想知道,test@% 该用户是否拥有对 db1.t 的 Insert 权限。

先查看该用户是否拥有全局 Insert 权限:

select Insert_priv from mysql.user where user='test' and host='%';

如果没有,再查看该用户是否拥有 db1 数据库级别的 Insert权限:

select Insert_priv from mysql.db where user='test' and host='%';

如果仍然没有,则继续判断是否拥有 db1.t 这张表的 Insert 权限:

select table_priv from mysql.tables_priv where user='test' and host='%' and db='db1';

权限系统的实现

授权表

有几张系统表是非常特殊的表,权限相关的数据全部存储在这几张表内。

  • mysql.user 用户账户,全局权限
  • mysql.db 数据库级别的权限
  • mysql.tables_priv 表级别的权限
  • mysql.columns_priv 列级别的权限

这几张表包含了数据的生效范围和权限信息。例如,mysql.user 表的部分数据:

mysql> select User,Host,Select_priv,Insert_priv from mysql.user limit 1;
+------|------|-------------|-------------+
| User | Host | Select_priv | Insert_priv |
+------|------|-------------|-------------+
| root | %    | Y           | Y           |
+------|------|-------------|-------------+
1 row in set (0.00 sec)

这条记录中,Host 和 User 决定了 root 用户从任意主机(%)发送过来的连接请求可以被接受,而 Select_priv 和 Insert_priv 表示用户拥有全局的 Select 和 Insert 权限。mysql.user 这张表里面的生效范围是全局的。

mysql.db 表里面包含的 Host 和 User 决定了用户可以访问哪些数据库,权限列的生效范围是数据库。

理论上,所有权限管理相关的操作,都可以通过直接对授权表的 CRUD 操作完成。

实现层面其实也只是包装了一层语法糖。例如删除用户会执行:

delete from mysql.user where user='test';

但是不推荐用户手动修改授权表。

连接验证

当客户端发送连接请求时,TiDB 服务器会对登陆操作进行验证。验证过程先检查 mysql.user 表,当某条记录的 User 和 Host 和连接请求匹配上了,再去验证 Password。用户身份基于两部分信息,发起连接的客户端的 Host,以及用户名 User。如果 User不为空,则用户名必须精确匹配。

User+Host 可能会匹配 user 表里面多行,为了处理这种情况,user 表的行是排序过的,客户端连接时会依次去匹配,并使用首次匹配到的那一行做权限验证。排序是按 Host 在前,User 在后。

请求验证

连接成功之后,请求验证会检测执行操作是否拥有足够的权限。

对于数据库相关请求 (INSERT,UPDATE),先检查 mysql.user 表里面的用户全局权限,如果权限够,则直接可以访问。如果全局权限不足,则再检查 mysql.db 表。

user 表的权限是全局的,并且不管默认数据库是哪一个。比如 user 里面有 DELETE 权限,任何一行,任何的表,任何的数据库。

db表里面,User 为空是匹配匿名用户,User 里面不能有通配符。Host和Db列里面可以有 % 和 _,可以模式匹配。

user 和 db 读到内存也是排序的。

tables_priv 和 columns_priv 中使用 % 是类似的,但是在Db, Table_name, Column_name 这些列不能包含 %。加载进来时排序也是类似的。

生效时机

TiDB 启动时,将一些权限检查的表加载到内存,之后使用缓存的数据来验证权限。系统会周期性的将授权表从数据库同步到缓存,生效则是由同步的周期决定,目前这个值设定的是5分钟。

修改了授权表,如果需要立即生效,可以手动调用:

flush privileges;

限制和约束

一些使用频率偏低的权限当前版本的实现中还未做检查,比如 FILE/USAGE/SHUTDOWN/EXECUTE/PROCESS/INDEX 等等,未来会陆续完善。

现阶段对权限的支持还没有做到 column 级别。

Create User 语句

CREATE USER [IF NOT EXISTS]
    user [auth_spec] [, user [auth_spec]] ...
auth_spec: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY PASSWORD 'hash_string'
}

user 参见用户账号名。

  • IDENTIFIED BY ‘auth_string’

设置登录密码,auth_string 将会被 TiDB 经过加密存储在 mysql.user 表中。

  • IDENTIFIED BY PASSWORD ‘hash_string’

设置登录密码,hash_string 将会被 TiDB 经过加密存储在 mysql.user 表中。目前这个行为和 MySQL 不一致,会在接下来的版本中修改为和 MySQL 一致的行为。

"权限管理" 更新于 May 27 2018: modified some errors about privileges (f95216b)
修改本文

本页导航

产品

  • TiDB
  • TiSpark
  • TiDB 路线图

文档

  • 快速入门
  • 最佳实践
  • 常见问题解答
  • TiDB 周边工具
  • 版本发布说明

资源

  • 博客
  • GitHub
  • 知乎专栏

公司

  • 关于我们
  • 招贤纳士
  • 新闻报道

联系我们

  • Twitter
  • LinkedIn
  • Reddit
  • Google Group
  • Stack Overflow
  • 微信公众号

    微信扫一扫
    微信ID:pingcap2015

© 2018 北京平凯星辰科技发展有限公司

English