迁移篇 | MatrixOne与MySQL全面对比

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注解中对字段进行处理:

#原项目配置
@ApiModelProperty(value = "设备启用:0;设备禁用:1")
private Boolean disable;

#切换MatrixOne后修改的配置
@ApiModelProperty(value = "设备启用:0;设备禁用:1")
@TableField(value = "`disable`")
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 数据库时,驱动使用 http://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 数据库,使用驱动 http://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 迁移结果

针对项目的迁移,主要从便捷性和性能两方面进行说明:

  1. 首先对于迁移的便捷性而言,旧版本的MatrixOne由于没有对各个数据库可视化工具进行适配,迁移过程稍显麻烦,无法借助工具进行数据表的迁移,需要自己手动对数据库的建表语句进行调整,如果在数据表比较多的情况下,迁移起来会相对耗时。
    对于新版的MatrixOne,适配了数据库可视化工具后,整个迁移过程还是比较方便的,跟普通的MySQL数据库迁移步骤相同。
  2. 对于迁移后的性能而言,针对普通事务操作,MatrixOne执行效率与MySQL相差无几。但对于大数据量的查询,MatrixOne基于 OLAP 特性,查询效率相较于MySQL而言提升了 5 倍左右,且相同资源下未出现 SQL 结果查询不出来的情况。

当前项目运行稳定,系统状态良好,尚未出现其他稳定性问题,后续我司也计划将更多MySQL相关的业务迁移至MatrixOne。

最后,感谢迁移过程中 MatrixOne 社区提供的帮助,祝愿社区在2024年越来越好。

关于MatrixOne

MatrixOne 是一款基于云原生技术,可同时在公有云和私有云部署的多模数据库。该产品使用存算分离、读写分离、冷热分离的原创技术架构,能够在一套存储和计算系统下同时支持事务、分析、流、时序和向量等多种负载,并能够实时、按需的隔离或共享存储和计算资源。 云原生数据库MatrixOne能够帮助用户大幅简化日益复杂的IT架构,提供极简、极灵活、高性价比和高性能的数据服务。

MatrixOne企业版和MatrixOne云服务自发布以来,已经在互联网、金融、能源、制造、教育、医疗等多个行业得到应用。得益于其独特的架构设计,用户可以降低多达70%的硬件和运维成本,增加3-5倍的开发效率,同时更加灵活的响应市场需求变化和更加高效的抓住创新机会。在相同硬件投入时,MatrixOne可获得数倍以上的性能提升。

MatrixOne秉持开源开放、生态共建的理念,核心代码全部开源,全面兼容MySQL协议,并与合作伙伴打造了多个端到端解决方案,大幅降低用户的迁移和使用成本, 也帮助用户避免了供应商锁定风险。

关键词:超融合数据库、多模数据库、云原生数据库、国产数据库

相关推荐
林的快手37 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
HEU_firejef1 小时前
Redis——缓存预热+缓存雪崩+缓存击穿+缓存穿透
数据库·redis·缓存
是芽芽哩!2 小时前
【Kubernetes 指南】基础入门——Kubernetes 基本概念(二)
云原生·容器·kubernetes
KELLENSHAW2 小时前
MySQL45讲 第三十七讲 什么时候会使用内部临时表?——阅读总结
数据库·mysql
m0_663234012 小时前
云原生是什么
云原生
SelectDB2 小时前
飞轮科技荣获中国电信星海大数据最佳合作伙伴奖!
大数据·数据库·数据分析
weisian1513 小时前
Redis篇--常见问题篇7--缓存一致性2(分布式事务框架Seata)
redis·分布式·缓存
小刘鸭!3 小时前
Hbase的特点、特性
大数据·数据库·hbase
凡人的AI工具箱3 小时前
每天40分玩转Django:Django表单集
开发语言·数据库·后端·python·缓存·django