对象管理 #
SphereEx-DBPlusEngine 按照逻辑库、对象层次进行管理。
逻辑库 #
逻辑库的概念 #
SphereEx-DBPlusEngine 中的逻辑库,是管理一组对象的单元。其形式上模拟了数据库的Database/Schema 的概念。
逻辑库的操作 #
- 创建
mysql> create database mydb;
- 删除
mysql> drop database mydb;
注意:删除逻辑库,将导致逻辑库下的相关对象被删除,且无法恢复。
- 查询
mysql> show databases;
- 使用
mysql> use mydb;
- 其他约束
- 不支持引用其他 Database 的对象,例如 select * from db2.t1。
- 不支持修改逻辑库名称。
- 不支持设置逻辑库的字符集、排序规则、只读状态、加密状态等。
后置步骤:添加数据源 #
在完成逻辑库创建后,还不能管理表等对象。在这之前还有一个关键步骤—添加数据源。添加数据源可以理解为为后续对象增加容器,来承载这些对象。关于数据源的操作,可参考 RESOURCE 相关的 DistSQL。
- 操作示例
REGISTER STORAGE UNIT ds_3307 (
HOST=127.0.0.1,
PORT=3307,
DB=test,
USER=testuser,
PASSWORD=testpwd
)
使用约束
SphereEx-DBPlusEngine 仅支持在一个逻辑库内添加同构的数据源,同构可理解为使用相同通信协议的数据库产品。
对象:表 #
表,是数据的基本承载主体。SphereEx-DBPlusEngine 通过封装底层数据源内的原始数据表,提供对外标准对象能力,并扩展出多种表类型,可满足不同场景需求。
表概念 #
| 名称 | 可见性 | 含义 |
|---|---|---|
| 逻辑表 | 可见 | 在 SphereEx-DBPlusEngine 对底层原始表的封装,是用户操作的主体,用户可视为标准数据库表使用。 |
| 物理表 | 不可见 | 由 SphereEx-DBPlusEngine 封装的底层数据库的真实物理表。这类表用户是直接不可访问的。 |
| 分片表 | 可见 | 由 SphereEx-DBPlusEngine 实现的一种逻辑表,是在数据分片场景中具有相同结构的一组水平拆分数据库(表)的逻辑对象。 |
| 广播表 | 可见 | 由 SphereEx-DBPlusEngine 实现的一种逻辑表,是在数据分片场景中具有相同结构的一组数据库(表)的逻辑对象。在所有分片内的表,结构和数据完全一致。 |
| 单表 | 可见 | 由 SphereEx-DBPlusEngine 实现的一种逻辑表,是在数据分片场景中一种数据库(表)的逻辑对象。其对应存储于某一数据源中。 |
| 加密表 | 可见 | 由 SphereEx-DBPlusEngine 实现的一种逻辑表,是在数据加密场景中一种数据库(表)的逻辑对象。 |
表操作 #
针对表的操作分为两种情况,一种是对逻辑表的操作(分片表、加密表等都是逻辑表的一种),另一种对物理表的操作。针对后者,SphereEx-DBPlusEngine 的处理与在数据源的操作是一致的,需要注意的当后者关联多个数据源时,是无法在指定数据源操作的。建议创建操作在数据源进行,并刷新元数据后,再在逻辑库进行其他操作。下文主要针对第一种情况进行说明。
- 增加
SphereEx-DBPlusEngine 针对表的增加操作,共分为三个步骤。
- 第一步:添加数据源 参见之前步骤
- 第二步:创建规则 根据需要需要的功能,创建对应的规则。下面以分片为例进行说明,其他参考插件说明。
sql> CREATE SHARDING TABLE RULE t_order(
RESOURCES(ds_3307,ds_3308),
SHARDING_COLUMN=order_id,
TYPE(NAME=hash_mod,PROPERTIES("sharding-count"=4)),
KEY_GENERATE_STRATEGY(
COLUMN=order_id,
TYPE(NAME=snowflake,PROPERTIES("worker-id"=123))
)
);
- 第三步:创建表
sql> CREATE TABLE t_order (
order_id int NOT NULL,
user_id int NOT NULL,
status varchar(50) DEFAULT NULL,
PRIMARY KEY (order_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
删除
SphereEx-DBPlusEngine 针对表的增加操作,共分为两个步骤。
- 删除表
sql> DROP TABLE IF EXISTS t_order;
- 删除规则
sql> DROP SHARDING TABLE RULE t_order;
需要注意的,目前 SphereEx-DBPlusEngine 尚未提供级联删除能力,如仅删除表会出现所谓“孤儿”现象,且可能造成后续创建同名对象的错误。建议可提供 Console 进行删除处理,或通过 “show sharding table rules” 命令定期查看是否存在未删除的无效对象。
修改
SphereEx-DBPlusEngine 针对表的修改操作,分为多种情况。
- 针对规则的修改 针对规则的修改,将改变现有数据存储方式。在 SphereEx-DBPlusEngine 中通过与迁移能力相结合来完成的,这其中涉及到数据迁移问题。具体参见数据迁移
- 针对物理表的修改 针对物理表的修改,建议通过命令行或图形方式,针对逻辑表进行修改。其对应操作将下发到物理表上。针对个别 SphereEx-DBPlusEngine 无法支持的表,可通过直接修改物理表后刷新元数据的方式完成。
查询
数据查询
在 SphereEx-DBPlusEngine 中创建的逻辑表,可通过正常的 DQL 方式查询。
结构查询
支持使用 DESC 或方言(如 MySQL 中的 show create table )查看元数据。但这种方式无法查看分片等细节,仅限于数据结构的查询。
其他问题 #
- 物理表分布
逻辑表的存储是通过若干张物理表组成。逻辑表与物理表间存在映射关系,可分为均匀分布和自定义分布两种形式。前者是指物理表在每个数据源内呈现均匀分布的态势, 例如:
db0
├── t_order0
└── t_order1
db1
├── t_order0
└── t_order1
后者则可以通过表达式的配置方式,实现特定规则的分布,例如:
db0
├── t_order0
└── t_order1
db1
├── t_order2
├── t_order3
└── t_order4
- 物理表发现机制
对于挂载数据源中已存在的表,SphereEx-DBPlusEngine 是可以探测到并可直接使用。目前探测机制是采取手动方式,即在 SphereEx-DBPlusEngine 启动时或认为执行 refresh table metadata 语句均可刷新元数据。如果发生物理表的结构变更,建议使用 refresh 语句来刷新元数据。
- 同名表覆盖问题
当出现逻辑表与物理表同名的情况,SphereEx-DBPlusEngine 会优先使用逻辑表,即此时物理表无法在 SphereEx-DBPlusEngine 中识别并使用。
- 广播表数据一致性
默认情况下,SphereEx-DBPlusEngine 不保证广播表数据一致性。如用户有刚需,可自行通过启动 XA 事务来保障。
对象:字段 #
SphereEx-DBPlusEngine 通过对底层数据源原始数据的封装,提供对外标准对象能力。针对表内字段上,SphereEx-DBPlusEngine 也做了封装对外服务。从用户侧,几乎无感,可视为数据库字段同等处理。
字段类型 #
SphereEx-DBPlusEngine 支持底层数据源的所有字段类型,具体参考数据类型。
特殊场景:数据加密 #
在数据加密场景下,SphereEx-DBPlusEngine 针对字段有一些特殊处理。在实现上,SphereEx-DBPlusEngine 通过引入逻辑列来屏蔽底层加密字段的差异。可简单理解为是一层映射关系,可根据需要映射到明文字段或密文字段。可根据用户使用需求,SphereEx-DBPlusEngine 完成对应的转换过程。针对逻辑列的添加、删除是由加密规则操作来维护的,用户不能手工干预。
对象:约束 #
SphereEx-DBPlusEngine 本身未对底层数据源约束方面做过多处理,原生数据库支持的约束依然有效。但在数据分片场景下,数据分布在多个节点上,部分约束受到限制。
支持情况 #
| 约束名称 | 约束含义 | 支持情况(分片表) | 支持情况(分片表) | 备注 |
|---|---|---|---|---|
| PK | 主键 | 部分支持 | 支持 | 支持包含分片键的主键约束 |
| FK | 外键 | 不支持 | 支持 | |
| UK | UK | 部分支持 | 支持 | 支持包含分片键的唯一性约束 |
| Not NULL | 非空 | 支持 | 支持 | |
| CHECK | 检查 | 部分支持 | 支持 | 支持不含跨分片校验的检查逻辑 |
限制情况 #
部分与约束相关的数据字典暂未支持,如 MySQL 下的 INFORMATION_SCHEMA.KEY_COLUMN_USAGE。
对象:索引 #
SphereEx-DBPlusEngine 本身未对底层数据源索引方面做过多处理,原生数据库支持的索引依然有效。但在数据分片场景下,数据分布在多个节点上,部分索引功能受到限制。
限制功能 #
- 分片条件下,不支持跨分片的唯一性索引。
- 分片条件下,不支持二级(或全局)索引。
对象:视图 #
SphereEx-DBPlusEngine 本身未对底层数据源视图方面做过多处理,原生数据库支持的视图依然有效。但在数据分片场景下,数据分布在多个节点上,部分视图功能受到限制。
对象:序列或自增长类型 #
序列或自增长类型,是数据库保证数据唯一性的有效手段。SphereEx-DBPlusEngine 本身未对底层数据源序列或自增长方面做处理,原生数据库支持依然有效。但在数据分片场景下,是有所不同的,受限于分布式环境的限制,很难如单机数据库的方式支持。一般推荐在分布式环境下,使用“分布式 ID”的功能替代,SphereEx-DBPlusEngine 通过一种名为“键生成器”的方式来支持多种分布式 ID。
键生成器用法 #
- 相关语法
具体参见DistSQL。除了可用上述方式创建外,还可以在分片规则定义中直接使用。
- 生成示例
下面通过示例说明下键生成器的用法。
sql> CREATE SHARDING TABLE RULE t_order(
-> RESOURCES(ds_3307,ds_3308),
-> SHARDING_COLUMN=order_id,TYPE(NAME=hash_mod,PROPERTIES("sharding-count"=4)),
-> KEY_GENERATE_STRATEGY(COLUMN=order_id,TYPE(NAME=uuid,PROPERTIES("worker-id"=123)))
-> );
Query OK, 0 rows affected (0.03 sec)
sql> CREATE TABLE t_order (
-> order_id varchar(50) NOT NULL,
-> user_id int NOT NULL,
-> status varchar(50) DEFAULT NULL,
-> PRIMARY KEY (order_id)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected (0.12 sec)
sql> INSERT INTO t_order(user_id, status) VALUES
-> (1, 'SUCCESS'),
-> (2, 'FAIL'),
-> (3, 'FAIL'),
-> (4, 'FAIL'),
-> (5, 'FAIL');
Query OK, 5 rows affected (0.01 sec)
sql> select * from t_order;
+----------------------------------+---------+---------+
| order_id | user_id | status |
+----------------------------------+---------+---------+
| 48e10218c7414bdbaf640aea2c079d32 | 12 | FAIL |
| adcb6343fb43424baed8f297832d6897 | 9 | FAIL |
| d01fe0d8f99744949f6f734803a6fbad | 1 | SUCCESS |
| 0a52a963254f4c889924fcef27afa497 | 16 | FAIL |
| 0bee54f2ee8a4af8bb09250f01b2565b | 15 | FAIL |
+----------------------------------+---------+---------+
定义并使用键生成器,会消耗 SphereEx-DBPlusEngine 的资源,经评估测试会有 60%~70% 左右的性能损耗,对于高并发、密集插入的场景需要关注。
内置分布式 ID #
UUID #
SphereEx-DBPlusEngine 内置 UUID 算法,可生成 36 位随机字符串。
- 与 MySQL 原生 UUID() 区别
- 字段类型不同。如果原生 MySQL 是使用 BINARY 类型插入的,则使用 SphereEx-DBPlusEngine 无法插入,需定义为 VARCHAR 才可以。此处需关注未来用户迁移系统过程中的改造成本(数据类型需变化)。
- 数据分配不均衡。在 HASH 分布策略下使用 UUID 数据分布是不均衡的。
NanoID #
SphereEx-DBPlusEngine 内置 NanoID 算法,相较于 UUID 其具备更小、更安全、更快等优势。
Snowflake #
SphereEx-DBPlusEngine 内置 Snowflake 算法,相较于 UUID 其具备更小和有序性等特点。
- 原理
在同一个进程中,它首先是通过时间位保证不重复,如果时间相同则是通过序列位保证。同时由于时间位是单调递增的,且各个服务器如果大体做了时间同步,那么生成的主键在分布式环境可以认为是总体有序的,这就保证了对索引字段的插入的高效性。例如 MySQL 的 Innodb 存储引擎的主键。

- 格式
使用雪花算法生成的主键,二进制表示形式包含 4 部分,从高位到低位分表为:1bit 符号位、41bit 时间戳位、10bit 工作进程位以及 12bit 序列号位。
- 符号位(1bit)
预留的符号位,恒为零。
- 时间戳位(41bit)
41 位的时间戳可以容纳的毫秒数是 2 的 41 次幂,一年所使用的毫秒数是:365 * 24 * 60 * 60 * 1000。通过计算可知:Math.pow(2, 41) / (365 * 24 * 60 * 60 * 1000L);
结果约等于 69.73 年。SphereEx-DBPlusEngine 的雪花算法的时间纪元从 2016 年 11 月 1 日零点开始,可以使用到 2086 年,相信能满足绝大部分系统的要求。
- 工作进程位(10bit)
该标志在 Java 进程内是唯一的,如果是分布式应用部署应保证每个工作进程的 id 是不同的。该值默认为0,可通过属性设置。
- 序列号位(12bit)
该序列是用来在同一个毫秒内生成不同的 ID。如果在这个毫秒内生成的数量超过 4096 (2 的 12 次幂),那么生成器会等待到下个毫秒继续生成。
- 时钟回拨
服务器时钟回拨会导致产生重复序列,因此默认分布式主键生成器提供了一个最大容忍的时钟回拨毫秒数。如果时钟回拨的时间超过最大容忍的毫秒数阈值,则程序报错;如果在可容忍的范围内,默认分布式主键生成器会等待时钟同步到最后一次主键生成的时间后再继续工作。最大容忍的时钟回拨毫秒数的默认值为 0,可通过属性设置。
- 限制条件
使用 Snowflake 算法,SphereEx-DBPlusEngine 集群规模不能超过 1024 个计算节点。
对象:库内计算 #
针对数据库场景的内置计算对象,如存储过程、触发器、函数等,SphereEx-DBPlusEngine 提供有限支持。对于原始数据库内部对象,SphereEx-DBPlusEngine 可通过直接透传下发方式支持。对于在数据分片、读写分离等场景下,不支持上述对象。
异常说明 #
针对分布式对象执行 DDL 操作,在极端情况下会出现在不同计算节点看到元数据不一致的情况。针对这种情况可通过在对应计算节点执行 REFRESH DATABASE METADATA db_name FROM GOVERNANCE CENTER; 命令手工完成元数据刷新。具体参见DistSQL。