Part 1
迁移背景
Skyable 自研了物联网私有云平台用于 IoT 设备的数据上报和协议解析,由于管理设备数量的增加导致设备上报的数据量越来越大,架构中原使用的 MySQL 数据库(分库分表)的部分业务在对设备上报信息进行相关的查询时,查询速度很慢,且会偶发出现查询不出来的情况,无法通过优化SQL来提升数据库性能,非常影响系统体验。为了尽可能少的调整业务,需要寻找一款高度兼容 MySQL 协议且能够支持大数据量查询的数据库进行切换,通过调研我们选择了 MatrixOne 数据库,选择的主要原因如下:
兼容MySQL协议 :完全兼容MySQL协议,项目中使用了 MyBatis、MyBatis Plus 作为 ORM 框架,只需通过少量的改动即可进行数据源的切换。
高可用 :MatrixOne 通过纠删码进行数据冗余校验,同步事务日志采用 Raft 协议,只有多数派写入成功,事务才能提交,这确保了数据的强一致性,即使少数副本发生故障也不影响数据的可用性,只需要 150% 的数据冗余即可实现高可用,更节省硬盘空间。
此外,MatrixOne 支持 K8s 部署高可用架构的集群,后期也可以使用 IoT 平台的 K8s 底座进行统一管理。
HTAP支持 :MySQL 的 OLAP 特性基于新一代 MySQL Heatwave 服务。要实现 OLAP 特性,必须单独部署一套 MySQL Heatwave 服务集群,增加了运维难度和系统复杂度。
MatrixOne 通过云原生化和存储、计算、事务分离的架构构建 HSTAP 超融合数据引擎,实现单一数据库系统支持 OLTP 与 OLAP,不需要额外的组件支持,降低了系统复杂度。
在调研前,我们模拟当前业务使用 MatrixOne 和 MySQL 进行了对比测试,测试发现 MatirxOne 的事务处理能力约为 MySQL 的 90%,但查询分析能力是 MySQL 的五倍以上,非常符合当前平台的业务需求。
Part 2
本地部署
IoT 私有云项目因为网络策略限制,不允许在Linux系统中使用外网,因此部署时使用 MatrixOne 提供的二进制包部署。MatrixOne的二进制包解压即用,部署非常简单,还提供了用于服务启停和运维的mo_ctl工具。以当前最新的 MatrixOne 1.1.0 为例,我们将所需的二进制包和 mo_ctl 工具上传至目标服务器,例如 /opt 目录:
[root@iot01 opt]# ll -h
total 51M
-rw-r--r-- 1 root root 6.8K Jan 1 21:44 install.sh
-rw-r--r-- 1 root root 72K Jan 1 21:44 mo_ctl.zip
-rw-r--r-- 1 root root 51M Dec 29 17:06 mo-v1.1.0-linux-x86_64.zip
下载地址分别为:
wget https://raw.githubusercontent.com/matrixorigin/mo_ctl_standalone/main/install.sh
wget https://github.com/matrixorigin/mo_ctl_standalone/archive/refs/heads/main.zip -O mo_ctl.zip
wget https://github.com/matrixorigin/matrixone/releases/download/v1.1.0/mo-v1.1.0-linux-x86_64.zip
解压 MatrixOne 安装包,并重命名解压后的目录:
[root@iot01 opt]# unzip mo-v1.1.0-linux-x86_64.zip
[root@iot01 opt]# mv mo-v1.1.0-linux-x86_64 matrixone
安装 mo_ctl 工具:
[root@iot01 opt]# bash +x ./install.sh mo_ctl.zip
为 mo_ctl 配置 matrixone 所在目录,例如:
mo_ctl set_conf MO_PATH="/opt"
MatrixOne 没有自带客户端,在本地需要使用 mysql client 来进行访问,若没有的需要提前准备,就绪后可直接通过 mo_ctl 工具启动MatrixOne 服务:
[root@node01 opt]# mo_ctl start
2024-01-01 21:58:09.606 UTC+0800 [INFO] No mo-service is running
2024-01-01 21:58:09.651 UTC+0800 [INFO] GO memory limit(Mi): 36050
2024-01-01 21:58:09.669 UTC+0800 [INFO] Starting mo-service: cd /opt/matrixone/ && GOMEMLIMIT=36050MiB /opt/matrixone/mo-service -daemon -debug-http :9876 -launch /opt/matrixone/etc/launch/launch.toml >/opt/matrixone/logs/stdout-20240101_215809.log 2>/opt/matrixone/logs/stderr-20240101_215809.log
2024-01-01 21:58:09.748 UTC+0800 [INFO] Wait for 2 seconds
2024-01-01 21:58:11.800 UTC+0800 [INFO] At least one mo-service is running. Process info:
root 10064 1 51 21:58 ? 00:00:01 /opt/matrixone/mo-service -daemon -debug-http :9876 -launch /opt/matrixone/etc/launch/launch.toml
2024-01-01 21:58:11.810 UTC+0800 [INFO] List of pid(s):
10064
2024-01-01 21:58:11.820 UTC+0800 [INFO] Start succeeded
MatrixOne 首次启动到服务就绪会需要10秒左右的时间,稍作等待后即可通过 mo_ctl 进行访问:
[root@node01 opt]# mo_ctl connect
2024-01-01 22:00:02.685 UTC+0800 [INFO] Checking connectivity
2024-01-01 22:00:02.708 UTC+0800 [INFO] Ok, connecting for user ...
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15021
Server version: 8.0.30-MatrixOne-v1.1.0 MatrixOne
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
MatrixOne 默认启用的用户名为 root,初始密码为 111,监听端口为 6001。使用 mo\_ctl 连接后即可进行后续的业务迁移和开发。
Part 3
迁移步骤
在 IoT 项目迁移初期,MatrixOne 版本刚迭代至 0.8 版本,验证迁移步骤有些许麻烦。后续反馈至 MatirxOne 社区后,社区的研发和支持同学也给予了大量的帮助,同时针对迁移过程中的问题及时合入了大量提升易用性的PR,以下为业务实际的迁移动作。
1. 创建数据库
首先根据项目,在MatrixOne中进行创建相关的数据库,这里针对cloud_server服务的数据库进行创建,建库示例如下:
# 原 MySQL建库语句
create database if NOT EXISTS `cloud_server` default character set utf8mb4 collate utf8mb4_unicode_ci;
# MatrixOne 建库语句
create database if NOT EXISTS `cloud_server`;
2. 表结构调整
对数据库建表语句进行调整,主要对MySQL的索引类型、表引擎、默认字符集等信息进行调整,下面针对cloud_server服务对MySQL数据表结构进行迁移,步骤如下:
Step 1 - 通过Navicat导出MySQL数据库相关表结构和数据:
Step 2 - MatrixOne 0.8 版本需要对 MySQL 中导出的建表语句进行调整,主要调整 MySQL 的索引类型、表引擎、默认字符集等信息。在反馈MatrixOne社区后,社区对关键字等进行了兼容,1.0+ 版本已不需要进行改写,可直接使用 MySQL 的建表在 MatrixOne 中进行建表,MatrixOne会自动忽视建表中MySQL独有的关键字。导出的MySQL语句示例如下:
-- MySQL语句
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for uds_service_info
-- ----------------------------
DROP TABLE IF EXISTS `uds_service_info`;
CREATE TABLE `uds_service_info` (
`service_id` bigint unsigned NOT NULL COMMENT '主键',
`service_name` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '服务名称',
`description` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '描述',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`memory_bytes` int(0) NULL DEFAULT NULL COMMENT '内存大小',
`instance_num` int(0) NULL DEFAULT 0 COMMENT '实例数',
`log_level` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '' COMMENT '日志级别',
`access_key` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'ACCESS KEY',
`access_secret` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'ACCESS SECRET',
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`service_id`) USING BTREE,
UNIQUE INDEX `dev_proj_srv_idx`(`service_name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '服务信息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of uds_service_info
-- ----------------------------
INSERT INTO `uds_service_info` VALUES (1, 'test-uds', '', 0, 536870912, 1, 'INFO', 'QtKMOYcQGMq8g3wnAAVAtQiG58GixniB', '9qq56Y0zmooOqQcTggSgq9lmqOOl13lrugq9Oy0gG9l05qOn6533qC6Q3VmfS6Gl', '2023-07-24 18:13:50', '2023-07-24 18:13:50');
INSERT INTO `uds_service_info` VALUES (2, 'uds-1', '', 81, 536870912, 1, 'INFO', 'TfMrNJ7porGaGf47NpkR43awlGrv9e8p', 'SkuWhvvBLWDODkLvh8zbLSOBfZWyXXLBL8SXLZb5ERX8kzLShhUNpXhuXpRuLLyp', '2023-08-09 14:44:16', '2023-08-09 14:44:16');
-- ----------------------------
-- Table structure for uds_service_version_info
-- ----------------------------
DROP TABLE IF EXISTS `uds_service_version_info`;
CREATE TABLE `uds_service_version_info` (
`version_id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '版本ID',
`service_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '服务ID',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`major_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '主版本号',
`minor_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '副版本号',
`patch_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '修订版本号',
`description` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '描述',
`image_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像ID',
`image_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像名称',
`memory_bytes` bigint(0) NULL DEFAULT NULL,
`instance_num` int(0) NULL DEFAULT NULL,
`log_level` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
`docker_service_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT 'docker服务ID',
`status` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '版本状态',
`image_status` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像状态',
`md5` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '文件MD5值',
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`version_id`) USING BTREE,
UNIQUE INDEX `serv_major_minor_patch_idx`(`service_id`, `major_version`, `minor_version`, `patch_version`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci COMMENT = '服务版本表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of uds_service_version_info
-- ----------------------------
INSERT INTO `uds_service_version_info` VALUES (1, 2, 81, '1', '0', '1', '测试', NULL, '192.168.110.244:5000/uds/81/uds-1:v1.0.1', 536870912, 1, 'INFO', NULL, 'init', 'downloadFail', NULL, '2023-08-10 13:49:40', '2023-08-10 13:49:40');
-- ----------------------------
-- Table structure for web_application
-- ----------------------------
DROP TABLE IF EXISTS `web_application`;
CREATE TABLE `web_application` (
`id` bigint unsigned NOT NULL COMMENT '主键',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`application_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '服务名称',
`language_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '语言类型',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `web_application_name`(`application_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for web_application_version
-- ----------------------------
DROP TABLE IF EXISTS `web_application_version`;
CREATE TABLE `web_application_version` (
`version_id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`web_application_id` int(0) NOT NULL COMMENT 'web服务ID',
`major_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '主版本',
`minor_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '副版本',
`patch_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修订版本',
`index_directory` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '首页位置',
`status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版本状态',
`image_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像状态',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
`image_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像ID',
`image_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像名称',
`docker_service_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '服务ID',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`version_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
修改后的MatrixOne语句如下:
-- MatrixOne语句
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for uds_service_info
-- ----------------------------
DROP TABLE IF EXISTS `uds_service_info`;
CREATE TABLE `uds_service_info` (
`service_id` bigint unsigned NOT NULL COMMENT '主键',
`service_name` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '服务名称',
`description` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '描述',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`memory_bytes` int(0) NULL DEFAULT NULL COMMENT '内存大小',
`instance_num` int(0) NULL DEFAULT 0 COMMENT '实例数',
`log_level` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT '' COMMENT '日志级别',
`access_key` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'ACCESS KEY',
`access_secret` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL COMMENT 'ACCESS SECRET',
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`service_id`) ,
UNIQUE INDEX `dev_proj_srv_idx`(`service_name`)
) COMMENT = '服务信息表';
-- ----------------------------
-- Records of uds_service_info
-- ----------------------------
INSERT INTO `uds_service_info` VALUES (1, 'test-uds', '', 0, 536870912, 1, 'INFO', 'QtKMOYcQGMq8g3wnAAVAtQiG58GixniB', '9qq56Y0zmooOqQcTggSgq9lmqOOl13lrugq9Oy0gG9l05qOn6533qC6Q3VmfS6Gl', '2023-07-24 18:13:50', '2023-07-24 18:13:50');
INSERT INTO `uds_service_info` VALUES (2, 'uds-1', '', 81, 536870912, 1, 'INFO', 'TfMrNJ7porGaGf47NpkR43awlGrv9e8p', 'SkuWhvvBLWDODkLvh8zbLSOBfZWyXXLBL8SXLZb5ERX8kzLShhUNpXhuXpRuLLyp', '2023-08-09 14:44:16', '2023-08-09 14:44:16');
-- ----------------------------
-- Table structure for uds_service_version_info
-- ----------------------------
DROP TABLE IF EXISTS `uds_service_version_info`;
CREATE TABLE `uds_service_version_info` (
`version_id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '版本ID',
`service_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '服务ID',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`major_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '主版本号',
`minor_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '副版本号',
`patch_version` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '修订版本号',
`description` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '描述',
`image_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像ID',
`image_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像名称',
`memory_bytes` bigint(0) NULL DEFAULT NULL,
`instance_num` int(0) NULL DEFAULT NULL,
`log_level` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL,
`docker_service_id` varchar(128) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT 'docker服务ID',
`status` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '版本状态',
`image_status` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '镜像状态',
`md5` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '文件MD5值',
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`version_id`) ,
UNIQUE INDEX `serv_major_minor_patch_idx`(`service_id`, `major_version`, `minor_version`, `patch_version`)
) COMMENT = '服务版本表';
-- ----------------------------
-- Records of uds_service_version_info
-- ----------------------------
INSERT INTO `uds_service_version_info` VALUES (1, 2, 81, '1', '0', '1', '测试', NULL, '192.168.110.244:5000/uds/81/uds-1:v1.0.1', 536870912, 1, 'INFO', NULL, 'init', 'downloadFail', NULL, '2023-08-10 13:49:40', '2023-08-10 13:49:40');
-- ----------------------------
-- Table structure for web_application
-- ----------------------------
DROP TABLE IF EXISTS `web_application`;
CREATE TABLE `web_application` (
`id` bigint unsigned NOT NULL COMMENT '主键',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`application_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '服务名称',
`language_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '语言类型',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) ,
UNIQUE INDEX `web_application_name`(`application_name`)
) ;
-- ----------------------------
-- Table structure for web_application_version
-- ----------------------------
DROP TABLE IF EXISTS `web_application_version`;
CREATE TABLE `web_application_version` (
`version_id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
`domain_id` int(0) NOT NULL COMMENT '主域ID',
`web_application_id` int(0) NOT NULL COMMENT 'web服务ID',
`major_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '主版本',
`minor_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '副版本',
`patch_version` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '修订版本',
`index_directory` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '首页位置',
`status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版本状态',
`image_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像状态',
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
`image_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像ID',
`image_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '镜像名称',
`docker_service_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '服务ID',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`version_id`)
) ;
SET FOREIGN_KEY_CHECKS = 1;
3. 表数据迁移
表结构调整完成后,执行调整后的SQL语句进行表的创建和表数据的导入,下面针对 cloud_server 服务对 MySQL 表结构数据进行迁移,执行调整后的sql文件,所有语句均可执行成功,执行完成后,查询相应的表数据是否已经成功导入,这里以 uds_service_info 演示表为例查看数据:
可以看到 MySQL 表中的数据已经成功导入到 MatrixOne 数据库中。
此外,1.0+ 版本的 MatrixOne 对各个数据库可视化工具进行了适配,数据迁移将更加便捷。我们选择以 Navicat 工具进行后续其他业务的迁移,仍以 cloud_server 服务相关的库表为例,操作步骤如下:
Step 1 - 首先,需要在MatrixOne中创建相应的数据库
create database if NOT EXISTS `cloud_server` default character set utf8mb4 collate utf8mb4_unicode_ci;
Step 2 - 借助Navicat中的 "工具" --> "数据传输" 功能对数据进行迁移
Step 3 - 选择需要迁移的源数据库和目标数据库后,点击"下一步"
Step 4 - 选择需要迁移源数据库中的哪些表,这里选择全部表,然后点击"开始"
Step 5 - 等待数据传输完成,传输完成后,查看MatrixOne数据库对应的表中数据是否正常迁移
可以看到数据已经正常迁移完成
4. 配置项目修改
数据迁移完成后,即可对项目中的数据源进行切换,只需对项目中的MySQL配置进行修改,修改数据库的IP、端口、用户名和密码即可,针对 cloud_server 中的配置修改如下:
#MySQL数据库配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/cloud_device?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: *********
#MatrixOne数据库配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.110.244:6001/cloud_device?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: *********
5. 启动项目
配置修改完成后,即可启动项目,针对cloud_server服务启动结果如下:
2023-12-28 09:56:28,617 INFO (TomcatWebServer.java:108)- Tomcat initialized with port(s): 8085 (http)
2023-12-28 09:56:28,632 INFO (DirectJDKLog.java:173)- Initializing ProtocolHandler ["http-nio-8085"]
2023-12-28 09:56:28,632 INFO (DirectJDKLog.java:173)- Starting service [Tomcat]
2023-12-28 09:56:28,632 INFO (DirectJDKLog.java:173)- Starting Servlet engine: [Apache Tomcat/9.0.37]
…………
2023-12-28 09:56:29,251 INFO (DruidDataSource.java:991)- {dataSource-1} inited
_ _ |_ _ _|_. ___ _ | _
| | |\/|_)(_| | |_\ |_)||_|_\
/ |
3.4.2
2023-12-28 09:56:33,416 INFO (InetUtils.java:170)- Cannot determine local hostname
2023-12-28 09:56:33,554 INFO (EndpointLinksResolver.java:58)- Exposing 18 endpoint(s) beneath base path '/actuator'
2023-12-28 09:56:33,618 INFO (XxlJobConfig.java:46)- >>>>>>>>>>> xxl-job config init.
…………
2023-12-28 09:56:37,857 INFO (FrameworkServlet.java:525)- Initializing Servlet 'dispatcherServlet'
2023-12-28 09:56:37,865 INFO (FrameworkServlet.java:547)- Completed initialization in 8 ms
服务能够正常启动成功。
6. 项目展示
项目启动后,我们可以看到系统流畅的运行,部分截图如下:
首页
设备授权列表
产品物模型
租户管理
Part 4
迁移问题
但是针对某些场景,我们在迁移的过程中,MatrixOne也有少量不兼容的问题,下面列出了我们在迁移过程中遇到的一些问题以及相应的解决办法。
MatrixOne数据库规范,表名不能以数字开头,而在我们系统中,为了区分多租户,使用租户ID对不同租户的表进行区分,例如设备表:1_device_info(1表示租户ID为1的租户)需调整为device_info_1;所以需要对表名及代码中涉及到的相关表进行调整。
项目中使用了xxl-job作为分布式定时任务服务,在执行XxlJobLogMapper.xml中 findFailJobLogIds 方法时,MatrixOne无法执行,需要对相应的SQL进行改造:
#xxl-job原SQL语句
<select id="findFailJobLogIds" resultType="long" >
SELECT id FROM `xxl_job_log`
WHERE !(
(trigger_code in (0, 200) and handle_code = 0)
OR
(handle_code = 200)
)
AND `alarm_status` = 0
ORDER BY id ASC
LIMIT #{pagesize}
</select>
#改造后的SQL语句
<select id="findFailJobLogIds" resultType="long" >
SELECT id FROM `xxl_job_log`
WHERE (
(trigger_code not in (0, 200) or handle_code != 0)
AND
(handle_code != 200)
)
AND `alarm_status` = 0
ORDER BY id ASC
LIMIT #{pagesize}
</select>
项目中跟MyBatis Plus整合时,类中使用了 disable 关键字作为类字段,切换到MatrixOne后执行相关的SQL时,被识别为关键字导致SQL执行报错,需要对代码进行相关的处理
# 在@TableField注解中对字段进行处理:
#原项目配置
private Boolean disable;
#切换MatrixOne后修改的配置
private Boolean disable;
# 在SQL中对该字段进行处理:
#原SQL语句
@Select({
" SELECT d.name, d.physical_device_id, d.status, d.disable
FROM cloud_device.device_info_${domainId} d WHERE d.physical_device_id = #{physicalDeviceId} "
})
#修改后的SQL语句
@Select({
" SELECT d.name, d.physical_device_id, d.status, d.`disable`
FROM cloud_device.device_info_${domainId} d WHERE d.physical_device_id = #{physicalDeviceId} "
})
INSERT ... ON DUPLICATE KEY UPDATE 用于在向数据库表中插入数据时,如果数据已经存在,则更新该数据,否则插入新的数据
用 Golang 语言连接 Matrixone 数据库时,驱动使用 github.com/go-sql-driver/mysql,执行该该类 SQL 语句时会报错:
_, err = db.Query("INSERT INTO m_user SET m_id=?, m_name=? ON DUPLICATE KEY UPDATE m_name=?;", 111, "aaaa", "bbbb")…………select failed: err[sql: expected 2 arguments, got 3]
目前先改造为通过先使用select查询有无数据,如果数据已经存在则使用update语句,否则使用insert插入新数据。
用 Golang 语言连接 Matrixone 数据库,使用驱动github.com/go-sql-driver/mysql,执行带 limit 的语句时报错:
_, err = db.Query("select * from device_info_2 limit ?,?", 0, 100)…………SQL syntax error: only int64 support in limit/offset clause
Part 5
迁移结果
针对项目的迁移,主要从便捷性和性能两方面进行说明:
首先对于迁移的便捷性而言,旧版本的MatrixOne由于没有对各个数据库可视化工具进行适配,迁移过程稍显麻烦,无法借助工具进行数据表的迁移,需要自己手动对数据库的建表语句进行调整,如果在数据表比较多的情况下,迁移起来会相对耗时。
对于新版的MatrixOne,适配了数据库可视化工具后,整个迁移过程还是比较方便的,跟普通的MySQL数据库迁移步骤相同。
对于迁移后的性能而言,针对普通事务操作,MatrixOne执行效率与MySQL相差无几。但对于大数据量的查询,MatrixOne基于 OLAP 特性,查询效率相较于MySQL而言提升了 5 倍左右,且相同资源下未出现 SQL 结果查询不出来的情况。
当前项目运行稳定,系统状态良好,尚未出现其他稳定性问题,后续我司也计划将更多MySQL相关的业务迁移至MatrixOne。
最后,感谢迁移过程中 MatrixOne 社区提供的帮助,祝愿社区在2024年越来越好。
关于MatrixOne
MatrixOne 是一款基于云原生技术,可同时在公有云和私有云部署的多模数据库。该产品使用存算分离、读写分离、冷热分离的原创技术架构,能够在一套存储和计算系统下同时支持事务、分析、流、时序和向量等多种负载,并能够实时、按需的隔离或共享存储和计算资源。 云原生数据库MatrixOne能够帮助用户大幅简化日益复杂的IT架构,提供极简、极灵活、高性价比和高性能的数据服务。
MatrixOne企业版和MatrixOne云服务自发布以来,已经在互联网、金融、能源、制造、教育、医疗等多个行业得到应用。得益于其独特的架构设计,用户可以降低多达70%的硬件和运维成本,增加3-5倍的开发效率,同时更加灵活的响应市场需求变化和更加高效的抓住创新机会。在相同硬件投入时,MatrixOne可获得数倍以上的性能提升。
MatrixOne秉持开源开放、生态共建的理念,核心代码全部开源,全面兼容MySQL协议,并与合作伙伴打造了多个端到端解决方案,大幅降低用户的迁移和使用成本,也帮助用户避免了供应商锁定风险。