本次分享主要介绍MatrixOne建模与多租户相关内容。
1 建模
#1 与MySQL的区别
使用create table语句建表和MySQL建表语句基本相同,也有几点要注意。
- MatrixOne暂不支持空间数据类型,其他数据类型在保持与 MySQL 命名一致的情况下,在精度与范围上,与 MySQL 存在有着细微的差异,具体可参见数据类型。
- MatrixOne主键主键必须包含 UNIQUE 值,不能包含 NULL 值
- MatrixOne索引目前支持主键索引、唯一索引,二级索引仅支持语法,暂无加速效果。
- MatrixOne目前只支持utf8编码,不支持修改,建表时可不指定编码。
- MatrixOne中仅有 TAE 一种存储引擎,它可以同时支持行和列存储以及事务处理能力,建表时无需使用 ENGINE=XXX 来更换引擎。
- MatrixOne中临时表只在当前会话中可见,在会话关闭时自动删除。这表示两个不同的会话可以使用相同的临时表名,而不会彼此冲突或与同名的现有非临时表冲突。在删除临时表之前,会隐藏现有表。
#2 序列
序列(Sequence)是一种特殊的数据库对象,它可以被用来自动生成唯一的数字序列。通常情况下,序列被用来为一个表的主键字段自动生成唯一的值。
▶ 2.1 创建序列
要在表格中使用序列,首先使用CREATE SEQUENCE创建一个序列对象my_sequence。
▶ 2.2 表中使用序列
将 my_sequence序列应用到表中的字段,为了将序列应用到表中的字段,需要在表定义中指定一个默认值为序列的下一个值,如下所示:
CREATE TABLE my_table (id INTEGER DEFAULT nextval('my_sequence'),name VARCHAR(50));
注意:在表中使用 SEQUENCE 时,需要注意 auto_increment 与 sequence 不能一起用,否则会报错。
▶ 2.3 插入数据
当插入一行数据时,如果没有指定 "id" 字段的值,那么 MatrixOne 将会自动从序列中获取下一个唯一的值作为其默认值。
▶ 2.4 验证序列
通过使用序列,可以轻松地在表格中自动分配唯一的标识符,从而避免了手动分配标识符可能带来的错误。使用下面的语句进行查询验证
#3 分区
▶ 3.1 范围分区
范围分区是一种基于连续值的分区方式,分区键可以是整数类型或日期类型中的 DATE 或 DATETIME。分区之间必须是互不重叠的,分区的定义使用 VALUES LESS THAN 运算符。需要注意的是,如果插入或更新的数据中,分区列的值没有对应的分区,那么相应的插入或更新操作将会失败。
▶ 3.2 列表分区
列表分区要求每个分区必须由明确定义的值列表组成,且每个分区的列表成员不能有重复值。列表分区只能使用整数类型作为分区键。
▶ 3.3 哈希分区
哈希分区通常用于将数据均匀分布在不同的分区中。常见的哈希分区有 HASH 函数分区和 KEY 函数分区。
在 HASH 函数分区中,必须明确指定用于分区的列或表达式,该列或表达式的类型必须是整数,并且建议明确指定分区数量,该数量必须是正整数。
CREATE TABLE tm1 (
s1 CHAR(32) PRIMARY KEY
)
PARTITION BY KEY();
与 HASH 函数分区不同的是,KEY 函数分区支持除大对象类型(TEXT/BLOB)之外的所有类型作为分区键,而且不一定需要指定分区数量。如果分区键是该表的主键列,那么在不显式指定分区键时,系统会默认以主键列作为分区键。
#4 Cluster by
单列语法为:create table() cluster by col;
多列语法为:create table() cluster by (col1, col2);
在建表时使用 Cluster by 命令,对于无主键的表,可以按照指定的列对表进行物理排序,并将数据行重新排列成与该列的值的顺序相同的顺序。这种物理排序有助于提高查询性能。
以下是使用 Cluster by 的一些注意事项:
- Cluster by 不能和主键同时存在,否则会语法报错。
- Cluster by 只能在建表时指定,不支持动态创建。
2 用户、角色与权限
#1 MatrixOne 权限管理概述
MatrixOne 权限管理帮助你管理租户、用户帐号生命周期,分配给用户相应的角色,控制 MatrixOne 中资源的访问权限。当数据库或集群单位中存在多个用户时,权限管理确保用户只访问已被授权的资源,赋予用户最少权限原则可降低企业信息安全风险。MatrixOne 也可以通过权限管理实现多租户方案。在 MatrixOne 中,每个租户在集群中所拥有的数据或资源被安全的隔离,跨集群单位的用户不可访问其他集群单位的资源,在该集群中被赋权访问资源的用户才有权访问本集群单位内的资源。
>> 集群
集群是 MatrixOne 权限管理中最高层级的对象,当部署完 MatrixOne 后便创建了集群这个对象。
注意: 对集群对象的操作权限的集合被称为系统权限。
>> 租户
MatrixOne 集群内可以创建和管理多个数据和用户权限体系完全隔离的租户,并对这些资源隔离的租户进行管理,这种多租户功能既节省了部署和运维多套数据业务系统的成本,又能利用租户间的硬件资源共享最大限度的节约机器成本。
在 MatrixOne 中将租户称为 Account。
>> 系统租户
为了兼容传统非多租户数据库的使用习惯,MatrixOne 在集群创建完成后会自动新建一个系统默认租户,也就是系统租户,即 Sys Account,如果你现在只有一套数据业务系统需要 MatrixOne 管理,便不需要创建更多的租户,直接登录并访问系统租户 (Sys Account) 即可。
>> 角色
角色也是一个对象,它是 MatrixOne 中用来管理和分配权限的对象。
在租户中,用户如果没有被赋予角色,那么用户就不能做任何操作。首先,需要先有一个高权限的账号先做一些初期的资源分配,比如说,由系统租户或者租户创建一些角色和用户,将对象权限授予给角色,再将角色赋予给用户,这个时候,用户就可以对对象进行操作了。
#2 初始化配置
系统集群创建后自动生成并授予root集群管理员权限,可以创建、编辑、删除租户。root还是系统租户管理员,管理系统租户下的所有资源,包含用户、角色、数据库/表/视图,授权管理。也就是说系统其实默认存在一个系统租户,不单独创建租户也可以使用MatrixOne。租户管理员在租户创建成功后默认可以管理普通租户下的所有资源,包含用户、角色、数据库/表/视图,授权管理。普通用户被创建后则被授予了public角色,只有连接MatrixOne的权限。
#3 登录
由于MatrixOne与Mysql8.0的协议具有高度的兼容性,我们使用Mysqlclient来连接MatrixOne。其中 -h、-p、-P`参数与 MySQL 相同,不同之处在于-u 代表用户,在 MatrixOne 的用户体系中,用户是位于租户 account以下一层的概念,因此登录时需要先指定租户 account_name,再指定租户中的用户 username才能完成登录。如果不指定accountname,则默认为系统租户sys(root)。
#4 租户
我们先使用root登录,create account命令来建立我们的第一个租户a1,租户管理员为admin,密码为test123。如果需要修改租户管理员密码,可以使用alter account命令。在系统运行过程中,可能需要暂停或恢复租户账号,这时我们可以使用alter account命令将租户状态设置为suspend或open。当租户不再使用时,可以使用drop account命令删除租户。我们退出登录,使用刚创建的租户来登录系统。
#5 用户
创建用户命令和租户类似,用户是位于租户 account以下一层的概念,user_name创建后无法修改。我们可以使用create user命令新建用户jack,创建用户时必须同时指定用户密码。需要修改用户密码可以使用alter user命令,用户不再使用时,可以使用drop user删除用户。租户。查询当前登录用户及租户信息,可以使用select user()命令。在创建用户时,可以同时指定用户角色。
#6 角色
角色可以被看做是一组权限的集合。新创建的用户可以被赋予某一角色,授予角色即表示用户被自动赋予该角色所拥有的权限。后续对角色的权限变更,也会体现在所有属于该角色的用户权限上。
创建角色使用create role,此时该角色无权限,后续可以通过 GRANT 命令赋予该角色权限;删除角色使用drop role,值得注意的是如果使用这个角色的用户正在会话中,当角色被移除,会话随即断开,无法再使用这个角色进行操作。
使用show roles可以查看你的账户下创建的角色的元信息,包括角色名称、创建者、创建时间以及注释内容。
角色之间可以继承,但不能形成环形依赖;一个角色可以授权给多个用户;一个用户也可以有多个角色,但在某一时刻只能使用其中一个角色。
>> 角色切换
一个用户被授予多个角色,用于执行不同类型的数据业务。
主要角色:用户在某一时刻只能使用其中一个角色,我们称当前所使用的这个角色为主要角色。
次要角色:除了主要角色之外该用户所拥有的其他角色集合称为次要角色。
在默认情况下,如果用户想去执行另一个角色权限的 SQL 时,需要先切换角色(即 set role)。此外,为了兼容经典数据库的权限行为,MatrixOne 还支持开启使用次要角色的功能:使用 set secondary role all,执行这条 SQL 后,该用户便可同时拥有他所有角色的权限了,执行 set secondary role none 即可关闭此功能。
#7 权限
在 MatrixOne 中,为了方便管理多种操作权限,于是便把权限封装在一个实体内,这个实体就是对象。例如,`Select`,`Insert`,`Update` 等操作权限,便封装在了 Table 对象内。图中的层级关系均为 1:n 的关系,即一个集群中可以创建多个租户(Account),一个租户下可以创建多个用户和角色,一个数据库中可以创建多个表和视图。
MatrixOne 的访问控制权限分为系统权限和对象权限。系统权限为集群管理员(默认用户名为 root)的权限。对象权限可以按照赋权的对象细分为租户权限、用户权限、角色权限、数据库权限、表权限、发布订阅权限。
在MatrixOne中只能指定角色权限,再将角色授权给用户,不能直接授权给用户。
授权使用grant命令,撤销授权使用REVOKE命令,下面我们对权限相关进行一个演示。
首先使用create database创建一个数据库db1,创建数据库语句和MySQL完全相同。
授予所有库权限给我们刚创建的角色,使用GRANT ALL ON database *.* TO tm_mo_role;
授予指定库表的指定权限给角色,使用GRANT SELECT,INSERT,UPDATE ON table db1.* TO tm_mo_role;
撤销权限使用REVOKE命令,比如撤销数据库db1所有表的UPDATE权限,使用REVOKE UPDATE ON table db1.* FROM tm_mo_role;
给已创建的用户jack配置角色,使用 GRANT 'tm_mo_role' TO jack;
撤销jack的tm_mo_role角色,使用REVOKE tm_mo_role FROM jack;
我们前面说过角色可以继承,这里再新建一个tm_mo_role2,然后将tm_mo_role授权给tm_mo_role2,这样tm_mo_role2也拥有了tm_mo_role的权限。使用GRANT tm_mo_role TO tm_mo_role2;
查看当前用户权限,使用SHOW GRANTS;
租户管理员查看指定用户比如jack的权限,可以使用SHOW GRANTS FOR jack;
3 资源隔离场景
#1 场景描述
A 公司购买了 MatrixOne 集群,并且完成了部署。由于 A 公司规模比较大,业务线多且复杂,数据量也非常庞大,想要针对某个业务线开发一款应用程序,假设命名为 BusinessApp,但是需要跟其他业务线的数据进行隔离,那么 MatrxiOne 怎么隔离出这些数据资源、权限资源呢?
完成部署 MatrixOne 集群,研发部门的 Tom 获取到集群管理员的账号,公司指派他来完成资源隔离这一任务。Tom 需要这么做:
- Tom 使用集群管理员的账号登录 MatrixOne。
- Tom 需要先创建两个租户,租户账号一个是 BusinessAccount,一个是 ElseAccount。
- BusinessAccount 内的数据资源主要用于开发应用程序 BusinessApp。
- ElseAccount 内的数据资源可以用于其他业务目的。
#2 实操
使用集群管理员的用户名(默认 root)和密码登录 MatrixOne。
▶ 2.1 创建租户
- 租户 businessAccount 的登录用户名和密码分别为:admin1,test123;
- 租户 elseAccount 的登录用户名和密码分别为:admin2,test456。
▶ 2.2 租户businessAccount操作
使用 admin1 登录租户 businessAccount,并创建数据库db1,数据表 db1.t1,并向t1中插入数据,并使用select 验证表是否创建成功。
▶ 2.3 租户elseAccount操作
使用 admin2 登录租户 elseAccount,查看租户 businessAccount中的 db1.t1数据,提示表不存在。在租户elseAccount中也可以创建库db1和表db1.t1,在租户elseAccount 的db1.t1这张表内插入与租户businessAccount中表db1.t1不同的数据并查看,表中的数据和租户 businessAccount的t1表中的数据不同,说明MatrixOne实现了租户间的资源隔离。
4 用户创建与授权场景
#1 场景描述
还是沿用上面的场景示例,Tom 把 BusinessAccount 这个租户账号给了公司的数据管理员 Robert,让 Robert 去分配新的用户账号和权限给其他研发同事。
研发同事 Joe 是这个 A 公司项目 BusinessApp 的应用开发者,Joe 有一个开发任务,Joe 需要使用数据库内所有的数据。那么 Robert 就要帮 Joe 开通账号,给 Joe 授权:
- Robert 先给 Joe 创建了一个用户账号(即,用户),名字叫做 Joe_G,Joe 就使用 Joe_G 这个账号登录到 MatrixOne。
- Robert 又给 Joe 创建了一个角色,名字叫做 Appdeveloper,并且把 Appdeveloper 角色赋予给 Joe 的用户账号 Joe_G 上。
- Robert 又给角色 Appdeveloper 授予了 ALL ON DATABASE 的权限。
- Joe 就可以使用 Joe_G 这个账号登录到 MatrixOne,并且全权操作数据库进行开发了。
- Smith是运营人员,需要使用数据库中的数据进行最终业务报表的呈现,我们给他一个账号smith,赋予角色operator,把数据库db1的所有表的读权限授予角色operator
#2 实操
系统集群创建后自动生成并授予root集群管理员权限,可以创建、编辑、删除租户。root还是系统租户管理员,管理系统租户下的所有资源,包含用户、角色、数据库/表/视图,授权管理。也就是说系统其实默认存在一个系统租户,不单独创建租户也可以使用MatrixOne。租户管理员在租户创建成功后默认可以管理普通租户下的所有资源,包含用户、角色、数据库/表/视图,授权管理。普通用户被创建后则被授予了public角色,只有连接MatrixOne的权限。
▶ 2.1 新建用户、角色
- 用户Joe 的用户名和密码分别为:Joe_G,user123
- 用户 Smith的用户名和密码分别为:smith,user456
- 角色 Appdeveloper的命名为:appdeveloper
- 角色 Operator的命名为:operator
▶ 2.2 授权
将 db1 的ALL ON DATABASE,ALL ON TABLE 的权限授予给 appdeveloper,表的SELECT权限授予给 operator。
此时的角色权限如下图所示:
将角色 Appdeveloper授予给用户 Joe_G;将角色 operator授予给用户 u2。
▶ 2.3 使用 Joe_G登录businessAccount进行权限验证
Joe可以在数据库db1中创建表,向表中插入数据,查询刚刚插入的数据。
▶ 2.4 使用smith登录businessAccount进行权限验证
只能查询db1中的表t2的数据,但无法向表t2插入数据,也无法创建新表。
5 Q&A环节
感谢大家和我一起学习MatrixOne建模与多租户的相关知识,下面进入Q&A环节。
Q:MySQL中的表引擎能直接迁移吗?MO兼容InnoDB这些?
A:MatrixOne不支持MySQL的InnoDB,MyISAM等引擎,但可以直接使用MySQL的语句在,MO会忽略这些引擎,在MatrixOne中仅有TAE一种存储引擎,它是完全独立研发的,可以友好的适用于各类场景,无需使用ENGINE=XXX来更换引擎。
Q:支不支持物化视图?
A:MatrixOne目前不支持物化视图,在目前的AP性能支撑下,直接进行分析也可以获得较高的分析体验。物化视图功能也已经在MatrixOne的Roadmap中,如果您对物化视图有刚性较高的需求,欢迎给我们提Issue来描述您的场景:https://github.com/matrixorigin/matrixone/issues
Q:多租户之间是如何实现资源隔离的?
A:MatrixOne的资源隔离核心是ACCOUNT可以对应到CN Set的资源组上,或者可以认为租户的隔离就是CN的容器隔离。除了多租户可以分配不同资源组以外,单个租户内部也可以根据业务类型进一步分配CN资源组,进行更细粒度的控制。关于资源隔离的完整描述,您可以参考:https://docs.matrixorigin.cn/1.0.0-rc2/MatrixOne/Deploy/mgmt-cn-group-using-proxy/#_2
Q:MO的权限也是基于RBAC模型设计的吗?可不可以将权限直接授予到用户?
A:MatrixOne的权限管理是结合了基于角色的访问控制(RBAC,Role-based access control)和自主访问控制(DAC,Discretionary access control)两种安全模型设计和实现的,不支持将权限直接授予用户,需要通过角色进行授权。
Q:普通用户能授予MOADMIN角色吗?
A:不可以的,MOADMIN为最高的集群管理员权限,只有root用户拥有。
Q:MO对标识符大小写是否敏感?
A:MatrixOne默认对标识符大小写不敏感,并支持通过lower_case_table_names参数来进行大小写敏感的支持,对于参数的详细介绍您可以参考:https://docs.matrixorigin.cn/1.0.0-rc2/MatrixOne/Reference/Variable/system-variables/lower_case_tables_name/
Q:怎么查看临时表?show tables看不到,怎么知道是不是创建了?
A:目前可以通过"show create table 临时表名"来查看,由于临时表在创建后只在当前会话可见,在当前会话结束时,数据库自动删除临时表并释放所有空间,在它的生命周期内我们通常是可以人为感知的。
Q:目前连接MO支持哪些编程语言?
A:Java、Python、Golang语言连接器和ORM都是支持,其他语言逻辑上也可以当作MySQL来进行连接。
Q:MO在事务处理这块,与MySQL有什么区别?
A:MatrixOne 默认为悲观事务,也不支持表级锁。MatrixOne 中的 DDL 语句是支持事务性的,可以在一个事务中回滚 DDL 操作,与 MySQL 不同。
MySQL DDL语句却不支持事务。也就是说,如果在执行DDL语句时出现错误,无法回滚到之前的状态,但是msyql 执行ALTER TABLE时 有专门的语法支持事务, mysql是支持表级锁的、行级锁。
Q:MO支持设置连接白名单或者黑名单吗?
A:支持白名单,目前不支持黑名单。