本文是关于如何将MySQL项目迁移到华为GaussDB PG模式的详细教程。
背景:在当今的国际形势严峻,很多卡脖子的技术搞得我们国内奋发图强,以华为为代表的国产数据库。在很多国企的系统中已经开始迁移。国产数据库的重要性不言而喻。
本文整理总计了一下从MySQL迁移到华为的GaussDB PG模式。这两种数据库在核心上有很大的不同,因此这个迁移过程可能会遇到一些困难。本文将详细介绍如何进行这种迁移,包括数据迁移,表结构迁移,以及索引、触发器、存储过程和函数的迁移等步骤。无论你是数据库管理员,还是只是想要了解这个过程的人,都可以从本文中获得有用的信息。
GaussDB 是华为提供的一种数据库解决方案,它支持多种存储引擎和数据库模式。在 GaussDB 中,B 和 PG 分别是两种不同的数据库模式。
B 模式:这通常是基于 GaussDB 自己的原生存储引擎。这种模式可能提供更多的高级特性和优化,特别是针对大规模、高并发的环境。
PG 模式:这是基于 PostgreSQL 的模式。如果你的应用或系统已经在使用 PostgreSQL,或者你需要一个与 PostgreSQL 兼容的解决方案,那么这可能是更好的选择。
如果使用PG模式,在3.x版本可以直接使用pgSQL的驱动我们项目亲测
在代码中创建连接之前任意位置隐含装载:Class.forName(“org.postgresql.Driver”);
在JVM启动时参数传递:java -Djdbc.drivers=org.postgresql.Driver jdbctest
这些文件都是不同版本的OpenGauss JDBC驱动,用于Java应用程序连接到OpenGauss数据库。
当使用opengaussjdbc.jar时,上面的Driver类名相应修改为“com.huawei.opengauss.jdbc.Driver”。
文件名称 | 说明 | 文件大小 | 最后修改时间 |
---|---|---|---|
gsjdbc200.jar | 针对某些版本的Java(如Java 2.0)的OpenGauss JDBC驱动 | 909 kB | 2023/3/27 00:43:23 |
gsjdbc4.jar | 针对Java 4或更高版本的OpenGauss JDBC驱动 | 896 kB | 2023/3/27 00:43:23 |
opengaussjdbc.jar | 通用的OpenGauss JDBC驱动 | 909 kB | 2023/3/27 00:43:23 |
兼容性:如果你需要与 PostgreSQL 兼容,那么 PG 模式可能是更好的选择。
性能需求:对于特定的高性能或大规模需求,B 模式可能提供更多的优化选项。
特性需求:某些高级功能可能只在特定的模式下可用。
团队经验:如果你的团队有更多的 PostgreSQL 经验,那么 PG 模式可能更适合;反之亦然。
迁移和集成:考虑到数据迁移和系统集成的复杂性和成本,选择一个与现有系统更兼容的模式。
成本:不同的模式可能有不同的成本结构,包括授权费用和运维成本。
项目迁移数据库类型可是一个大工程,在迁移之初一定要做好充分的调研。建议在确定模式之前,进行性能和兼容性测试,以确保你的选择能满足业务和技术需求。
在 GaussDB 的 PG 模式下,虽然它已经做出了很大的努力来实现对 PostgreSQL 的兼容,但仍然可能存在一些与 MySQL 不兼容的情况。如果你在迁移过程中遇到了这样的问题,以下是一些处理建议:
了解两种数据库的差异:首先,你需要理解 MySQL 和 OpenGauss(GaussDB 的 PG 模式)在 SQL 语法、数据类型、函数、存储过程等方面的差异。这将帮助你更好地理解迁移过程中可能出现的问题。
使用数据库迁移工具:对于大规模的数据库迁移,手动修改 SQL 语句可能并不现实。你可以考虑使用数据库迁移工具,如 AWS DMS(Database Migration Service)或 Azure Database Migration Service,这些工具可以自动处理一些常见的不兼容问题。
手动修改 SQL 语句:对于一些特定的不兼容问题,你可能需要手动修改你的 SQL 语句。例如,MySQL 使用 AUTO_INCREMENT
在表定义中创建自增字段,而 OpenGauss 使用 SERIAL
数据类型。对于这样的差异,你需要手动修改你的表定义。
修改应用代码:在某些情况下,你可能需要修改你的应用代码来适应新的数据库。例如,如果你的应用依赖于 MySQL 的特定功能(如全文搜索或地理空间查询),你可能需要重新实现这些功能以使用 OpenGauss 的等价功能。
以下是在GaussDB PG(OpenGauss)和MySQL之间的一些主要的SQL语法不兼容性。这个列表包含了一些主要的不同之处,但并不是全部的不兼容性。在进行迁移之前,建议深入对比和测试以确保兼容性。
MySQL | OpenGauss | 备注 |
---|---|---|
AUTO_INCREMENT |
SERIAL |
序列生成器 |
SHOW TABLES |
\dt |
查看所有表 |
SHOW DATABASES |
\l |
查看所有数据库 |
LIMIT n OFFSET m |
LIMIT n OFFSET m 或 FETCH FIRST n ROWS ONLY OFFSET m |
分页查询 |
DESCRIBE table or DESC table |
\d table |
描述表结构 |
CONCAT(str1, str2, ...) |
`str1 | |
SUBSTRING(str, pos, len) |
SUBSTRING(str FROM pos FOR len) |
子字符串 |
LENGTH(str) |
LENGTH(str) 或CHAR_LENGTH(str) |
字符串长度 |
CURDATE() |
CURRENT_DATE |
当前日期 |
NOW() |
CURRENT_TIMESTAMP |
当前时间 |
RAND() |
RANDOM() |
生成随机数 |
IFNULL(exp, replace_exp) |
COALESCE(exp, replace_exp) |
判断表达式是否为空 |
ISNULL(exp) |
exp IS NULL |
判断表达式是否为空 |
` 作为标识符引用符 |
" 作为标识符引用符 |
标识符引用符 |
存储过程使用 BEGIN 和 END |
存储过程使用 $$ |
存储过程定义 |
TRUNCATE TABLE 不可在事务中 |
TRUNCATE TABLE 可在事务中 |
清空表数据 |
REPLACE INTO |
INSERT ... ON CONFLICT DO UPDATE |
插入冲突更新 |
REGEXP |
~ |
正则表达式搜索 |
CREATE DATABASE 不支持所有者 |
CREATE DATABASE 支持所有者 |
创建数据库 |
ENUM 类型 |
无对应,可用 CHECK 约束代替 |
类型不一致 |
SET 类型 |
无对应,可用 ARRAY 类型代替 |
类型不一致 |
YEAR 类型 |
无对应,可用 INTERVAL YEAR 或 DATE 类型代替 |
类型不一致 |
UNSIGNED 类型 |
无对应,需注意数值范围 | 类型不一致 |
ZEROFILL 类型 |
无对应,需在应用层处理 | 类型不一致 |
SHOW CREATE TABLE |
pg_dump -t table -s |
查看表创建语句 |
ENGINE = InnoDB |
无对应 | 存储引擎 |
CHARSET = utf8mb4 |
ENCODING = UTF8 |
字符集 |
COLLATE = utf8mb4_bin |
COLLATE "C" |
排序规则 |
分区表 | 分区表 | 分区定义语法不同 |
CREATE USER |
CREATE ROLE |
创建用户 |
REVOKE ALL PRIVILEGES |
REVOKE ALL |
撤销权限 |
GRANT SELECT ON *.* |
GRANT SELECT ON ALL TABLES IN SCHEMA |
授予权限 |
/*!50003 CREATE*/ |
CREATE OR REPLACE |
创建或替换 |
LOCK TABLES |
LOCK TABLE |
锁表 |
UNLOCK TABLES |
COMMIT |
解锁 |
KILL QUERY |
CANCEL |
取消查询 |
SHOW PROCESSLIST |
SELECT * FROM pg_stat_activity |
查看进程列表 |
LOAD DATA INFILE |
COPY |
数据导入 |
SELECT INTO OUTFILE |
COPY TO |
数据导出 |
RENAME COLUMN |
ALTER COLUMN RENAME |
重命名列 |
RENAME INDEX |
ALTER INDEX RENAME |
重命名索引 |
RENAME DATABASE |
无对应 | 重命名数据库 |
ALTER DATABASE 不支持修改所有者 |
ALTER DATABASE 支持修改所有者 |
修改数据库所有者 |
ALTER DATABASE 支持修改字符集和排序规则 |
ALTER DATABASE 不支持修改字符集和排序规则 |
修改数据库字符集和排序规则 |
ALTER TABLE 支持一次修改多个列 |
ALTER TABLE 一次只能修改一个列 |
修改表列 |
ALTER TABLE 支持一次添加多个索引 |
ALTER TABLE 一次只能添加一个索引 |
添加表索引 |
ALTER TABLE 支持一次删除多个索引 |
ALTER TABLE 一次只能删除一个索引 |
删除表索引 |
ALTER TABLE 支持修改存储引擎 |
ALTER TABLE 不支持修改存储引擎 |
修改表存储引擎 |
ALTER TABLE 支持修改字符集和排序规则 |
ALTER TABLE 不支持修改字符集和排序规则 |
修改表字符集和排序规则 |
ALTER TABLE 支持修改自增值 |
ALTER TABLE 不支持修改自增值 |
修改表自增值 |
序号 | 描述 | MySQL | GaussDB PG |
---|---|---|---|
1 | 插入并在存在时更新 | REPLACE INTO 或 INSERT … ON DUPLICATE KEY UPDATE … | INSERT … ON CONFLICT DO UPDATE … |
2 | 使用 LIMIT 进行分页查询 | SELECT … LIMIT offset, count | SELECT … LIMIT count OFFSET offset |
3 | 单行插入返回插入的 ID | INSERT INTO …; SELECT LAST_INSERT_ID(); | INSERT INTO … RETURNING id; |
4 | 单行更新返回更新的行 | UPDATE …; SELECT …; | UPDATE … RETURNING *; |
5 | 单行删除返回删除的行 | DELETE …; SELECT …; | DELETE … RETURNING *; |
6 | 随机获取一行记录 | SELECT … ORDER BY RAND() LIMIT 1 | SELECT … ORDER BY RANDOM() LIMIT 1 |
7 | 索引字段查询优化 | SELECT * FROM table USE INDEX(index) WHERE column = value | SET enable_seqscan TO OFF; SELECT * FROM table WHERE column = value; SET enable_seqscan TO ON; |
8 | 使用全文索引搜索 | MATCH(column) AGAINST(‘text’) | to_tsvector(column) @@ to_tsquery(‘text’) |
9 | 查询特定范围的行 | SELECT * FROM table LIMIT x, y | SELECT * FROM table LIMIT y OFFSET x |
10 | 使用存储过程 | CALL procedure_name() | SELECT * FROM procedure_name() |
11 | 事务处理 | START TRANSACTION; COMMIT; ROLLBACK; | BEGIN; COMMIT; ROLLBACK; |
12 | 创建临时表 | CREATE TEMPORARY TABLE table_name | CREATE TEMP TABLE table_name |
13 | MySQL使用反引号(``)引用表名和列名 | SELECT column FROM table |
SELECT “column” FROM “table” |
14 | 时间和日期函数 | DATE(), NOW(), YEAR(), MONTH(), DAY(), HOUR(), MINUTE(), SECOND() | CURRENT_DATE, CURRENT_TIME, DATE_PART(‘year’, column), DATE_PART(‘month’, column), DATE_PART(‘day’, column), DATE_PART(‘hour’, column), DATE_PART(‘minute’, column), DATE_PART(‘second’, column) |
15 | 字符串连接函数 | CONCAT(column1, column2) | column1 |
16 | 对分组的限制 | SELECT … FROM … GROUP BY … WITH ROLLUP | SELECT … FROM … GROUP BY … ROLLUP(…) |
17 | 对NULL的处理 | SELECT IFNULL(column, 0) FROM table | SELECT COALESCE(column, 0) FROM table |
18 | 判断是否为空 | SELECT column IS NULL FROM table | SELECT column IS NULL FROM table |
19 | 日期加减操作 | SELECT DATE_ADD(date, INTERVAL 1 DAY) FROM table | SELECT date + INTERVAL ‘1 day’ FROM table |
20 | 创建自增主键 | CREATE TABLE table (id INT AUTO_INCREMENT, PRIMARY KEY (id)) | CREATE TABLE table (id SERIAL PRIMARY KEY) |
21 | 使用正则表达式匹配数据 | SELECT column REGEXP ‘pattern’ FROM table | SELECT column ~ ‘pattern’ FROM table |
22 | 计算平均值 | SELECT AVG(column) FROM table | SELECT AVG(column) FROM table |
23 | 计算最大值 | SELECT MAX(column) FROM table | SELECT MAX(column) FROM table |
24 | 计算最小值 | SELECT MIN(column) FROM table | SELECT MIN(column) FROM table |
25 | 计算总和 | SELECT SUM(column) FROM table | SELECT SUM(column) FROM table |
26 | 计算记录数 | SELECT COUNT(column) FROM table | SELECT COUNT(column) FROM table |
27 | 使用内置数学函数 | SELECT ABS(column), CEIL(column), FLOOR(column), ROUND(column) FROM table | SELECT ABS(column), CEILING(column), FLOOR(column), ROUND(column) FROM table |
28 | 使用内置字符串函数 | SELECT CHAR_LENGTH(column), LOWER(column), UPPER(column), REVERSE(column) FROM table | SELECT LENGTH(column), LOWER(column), UPPER(column), REVERSE(column) FROM table |
29 | 使用内置日期函数 | SELECT CURRENT_DATE(), CURRENT_TIME(), DATE_FORMAT(date, ‘format’) FROM table | SELECT CURRENT_DATE, CURRENT_TIME, TO_CHAR(date, ‘format’) FROM table |
30 | 使用内置转换函数 | SELECT CAST(column AS type) FROM table | SELECT CAST(column AS type) FROM table |
在华为GaussDB PG模式迁移MySQL项目中,这个过程可能会涉及到数据、表结构、索引、触发器、存储过程和函数的迁移。以下是一些具体步骤:
准备工作:
步骤1: 数据迁移
步骤2: 表结构迁移
步骤3: 索引、触发器、存储过程和函数的迁移
注意:这些步骤可能需要一些SQL知识,并且在迁移过程中可能会遇到一些问题,比如数据类型不匹配、编码问题等,需要根据实际情况进行调整。
高斯数据库(GaussDB)。对于PG模式,可以使用PostgreSQL JDBC驱动来连接。
添加PostgreSQL JDBC驱动的Maven依赖:
<dependencies>
<dependency>
<groupId>org.postgresqlgroupId>
<artifactId>postgresqlartifactId>
<version>42.3.1version>
dependency>
dependencies>
可以使用以下Java代码来连接到GaussDB并执行查询。如果是使用持久化框架,比如MyBatis 或者MP 或者JPA hbernate 等就不需要手动创建连接。只需要换一下配置中的jdbc连接串
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
try {
// 加载驱动
Class.forName("org.postgresql.Driver");
// 连接数据库,注意URL的格式,包括服务器地址、端口、数据库名、SSL和其他参数
String url = "jdbc:postgresql://your_server:your_port/your_database?ssl=true&"
+ "sslfactory=org.postgresql.ssl.NonValidatingFactory";
Connection conn = DriverManager.getConnection(url, "your_user", "your_password");
// 创建一个Statement对象并执行SQL查询
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");
// 处理查询结果
while (rs.next()) {
System.out.println(rs.getString("your_column"));
}
// 关闭连接
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}