现代全栈框架使用 Prisma 从 SQLite 数据库迁移到 PostgreSQL

954 阅读5分钟

本文适合前端到全栈的小伙伴,Remix 和 Next.js 等开发者,适合数据迁移入门和小型数据量迁移。熟悉基本 SQL 以及 Prisma 基本操作,熟悉 SQLite 和 PostgreSQL 不同类型,对 python 有一些了解,最好熟悉 Docker 部署和服务端基本开发和部署经验。

一、为什么?

项目前期很多不确定。直接使用 sqlite 有很大的优势,轻量级,无需手动连接到本地或者远程数据库。但是随着需要线上部署我们就需要考虑迁移的问题了。

二、迁移数据量

迁移数据量不大,23 张表,不到 1000 数据量,本质上可以手动完成。但是为了能熟悉工具和熟悉经验还是要上工具。

  • SQLiteStudio 一个功能强大的 SQLite 操作工具。
  • Navicat 一个多功能的数据库管理工具支持各种类型的数据。
  • prisma studio prisma 浏览器管理数据工具。
  • pgAdmin pg 官方的数据管理软件,windows 随着下载安装。
  • pgloader 使用命令行一键迁移。
  • python + pandas python 平台的数据处理工具库。

三、准备好工具并做好技术选型

经过尝试:

  1. Navicat 在转换数据时候存在类型转换问题,例如 sqlite 时间转换之后变成了二进制。
  2. pgloader 适用于 deb 下的数据转换,windows 平台需要自己编译出 exe 文件,使用不友好。
  3. 本文选择 python + csv 文件 + pandas 方案进行手动管理,一来熟悉 python 清洗数据内容。

在开始迁移数据之前,我们需要了一些数据库的知识点以及 Prisma 对不同的数据库的支持情况。

3.1)SQLite 数据的特点

数据前过程中遇到最大的问题就是数据类型不一致问题,下面我们简单的回顾一下 SQLite 数据特点。这里关注 SQLite 与其他数据库不同的点:

  • SQLite 不提供枚举类型,但是可以 check 一个枚举类型。
  • SQLite 时间类型比较简单,包含Text/REAL/INTEGER/BLOB。
  • SQLite 没有原生的 boolean 类型,可以使用 0/1 模拟
  • SQLite 使用 INTEGER PRIMARY KEY AUTOINCREMENT 实现自动增长的主键。

3.2)PostgreSQL 数据类型的特点

  • PostgreSQL 提供枚举类型支持,非常方便
  • PostgreSQL 有专门的时间类型,这里
  • PostgreSQL 存在原生的布尔类型
  • PostgreSQL 原生支持自增长

3.3)Prisma Schema

  • Prisma 提供枚举类型支持,但是 SQLite 不可用
  • PostgreSQL DateTime 统一的时间类型
  • PostgreSQL Boolean
  • PostgreSQL @id + @default(autoincrement()) 属性修饰器修饰。

四、数据备份

在数据备份输出中,包含各种类型格式,sql 格式,csv 格式,json 格式等等,就使用频率使用 csv 文件还是偏多。

4.1)为什么不选择 sql 语句?

如果我们输出 sql 语句很大情况下是不能直接使用的,因为数据类型存在差异,工具可能也不能完美解决。这个时候能手动清洗数据库那就是完美。

4.2)输出 csv 文件

经过统计在数据备份中 csv 类型使用最为频繁的,python + pandas 等工具能够轻松的读取这种文本的数据类型。

因为我们数据表也就是二十多张并数据不大,使用数据库一次性导出 csv 不会花费很多时间。手动迁移数据库完全可行,并且可以基本熟悉使用 python + pandas 对数据进行简单的清洗。

当然如果你熟悉了 python 清洗数据流程,完成可是用编程操作,直接在数据库之间进行转换,必要进行输出。

五、Navicat Transfer

经过尝试 Navicat Transfer 存在数据库类型转换错误问题。其实中间还需要数据清洗。当然你可以尝试一下不同数据迁移的时候哪些数据类型是不符合自己的预期的方便自己清理。

六、Prisma + SQLite + PostgreSQL

6.1)使用 SQLite 初始化

cd your
npm install prisma --save-dev
npx prisma init --datasource-provider sqlite
npx prisma migrate dev --name init

安装、SQLite 初始化以及第一次迁移数据。然后就可以使用 Node.js + TS 进行操作了。

七、数据表关系

因为表之间是存在关联关系的,没有导入 被依赖的数据表时候,插入数据是会报错的。搞清楚插入数据先后关系是手动数据迁移的重要一环。

八、将数据操作交给

8.1)Prisma 重新创建数据库然后

我们在 PostgreSQL 中重新创建一个数据库 new_xxx

8.2)安装依赖

  • python py 脚本
  • pandas 数据操作
  • sqlalchemy 数据操作引擎
pip install pandas sqlalchemy

8.3)一个简单示例

创建一个文件:

touch index.py

下面使用 pandas 的 read_csv 方法读取 csv 文件并修改不符合要求的数据

import pandas as pd
from sqlalchemy import create_engine

# 创建数据库引擎
engine = create_engine('postgresql://yourname:password@host/db_name')

# 读取 CSV 文件
df = pd.read_csv('./your_db.csv')
print(df)

# 你要修改的数据 确保日期时间格式正确
df['createdAt'] = pd.to_datetime(df['createdAt'], format='%Y-%m-%d %H:%M:%S')
df['updatedAt'] = pd.to_datetime(df['updatedAt'], format='%Y-%m-%d %H:%M:%S')

# 将数据写入 PostgreSQL
df.to_sql('sys_role', engine, if_exists='append', index=False)

你甚至可以更加疯狂一点,在两个数据之间进行读取,这样就不需要文件系统输出文件了。

import pandas as pd
from sqlalchemy import create_engine

# 创建 SQLite 数据库引擎
engine_sqlite = create_engine('sqlite:///your_db.sqlite')

# 读取数据到 DataFrame
query = "SELECT * FROM your_table"
df = pd.read_sql_query(query, engine_sqlite)

# 将 createdAt 和 updatedAt 列转换为 datetime 格式
df['createdAt'] = pd.to_datetime(df['createdAt'])
df['updatedAt'] = pd.to_datetime(df['updatedAt'])

print(df)
engine_pg = create_engine('postgresql://yourname:password@host/db_name')
df.to_sql('sys_role', engine_pg, if_exists='append', index=False)

pandas 配合 sqlalchemy 提供的数据引擎能够很好的帮助我们进行数据访问与操作。当然你也可以是 python 的 jupyter notebook 可视化进行代码编写。

九、小结

本文基于 Prisma + SQLite/PostreSQL 从本地 SQLite 数据迁移到线上 PostreSQL 数据的探索, 尝试了市面上的各种工具,适合前端全栈的小伙伴。我们看到当熟悉了各种编程语言之后,能够帮我们更好的完成工作。希望这篇文章能够帮助到你。