【sqlite3】MySQL8转sqlite3需要对sql做的一些处理
问题来源
最近编写我的kook机器人的时候,发现MySQL对于这种低访问频次的应用并不友好,经常出现断连的问题,具体到python中的报错如下
1 | pymysql.err.InterfaceError: (0, '') |
出现这种报错,就可以认为是MySQL那端因为自身策略中断了和你的应用的链接。因为我的机器人和MySQL是在同一台主机上,肯定不是网络本身问题导致的。
所以我需要将MySQL数据库换成sqlite3数据库。
MySQL转sqlite3
导出MySQL中的数据
好在我的机器人使用的是python的peewee这个ORM库,只需要修改底层的DB引擎就能快速在MySQL和sqlite3之间切换。我们要解决的只是怎么把MySQL8.0.30的数据导入到sqlite3中。
本文测试使用的版本为:
MySQL 8.0.30
和sqlite3 3.44.0
首先是从MySQL将数据库里面的所有数据导出为sql文件,因为我安装了1panel服务器面板,所以可以直接使用面板的备份功能,再把备份好的tar下载下来(里面就是sql文件)
这里给出用命令行来处理的方式,一般使用的工具为mysqldump,在安装MySQL的时候这个工具应该就会连带安装。我的MySQL是用docker安装的,docker容器内的终端也有这个命令工具。
1 | [root@RainYun-8aNbbsmA:~/docker]# docker exec -it mysql /bin/bash |
导出整个数据库的数据到sql的命令如下
1 | mysqldump -u username -ppassword dbname > dbname.sql; |
比如我有个testdb数据库,将其导入testdb.sql的命令如下,这里我直接使用了root用户来处理。
1 | mysqldump -uroot -p123456 testdb > testdb.sql |
因为在命令行使用密码被认为是不安全的,所以键入如上命令的时候会有一个警告,可以忽略它。
1 | mysqldump: [Warning] Using a password on the command line interface can be insecure. |
ls查看一下,当前路径上已经有我们需要的sql数据文件了。
docker内文件拷贝到宿主机
因为我现在的这个操作是在一个docker容器里面,我还需要将其从docker中拷贝出来,方法有两个
- 将sql文件拷贝到docker的持久化目录中(即映射到了宿主机的目录中);
- 使用docker copy命令;
对于1panel安装的MySQL容器而言,你可以在容器的详细设置里面看到映射路径的关系。
如果使用docker cp命令,格式如下
1 | docker cp 容器ID:容器内路径 宿主机路径 |
这里的容器ID可以是容器的名字,也可以是docker ps命令查看到的容器CONTAINER ID
;mysqldump命令弄出来的sql文件是在容器内的根目录上。
1 | ## docker cp mysql:/testdb.sql ~/testdb.sql |
修改sql文件
MySQL导出的sql文件不能直接被sqlite3识别,在我的机器人数据库中遇到如下几个问题,需要修改sql文件。
- 用peewee创建sqlite数据库时生成的create table语句替换MySQL导出的sql文件内部已有的建表语句;
- 删除sql文件中的
LOCK TABLES
和UNLOCK TABLES;
,因为sqlite不支持; - sql文件中的转义字符
\"
替换成"
。因为在sqlite3中不需要进行此转义。如果不修改,那么在sqlite3中list的json字符串中就会留有\"
导致无法被json.loads
(猜测sqlite3中'
的优先级高于"
)
首先是把python中peewee使用的数据库模型改成sqlite,然后启动一下这个机器人,此时peewee就会创建一个db文件。
1 | sqlite3 数据库文件名.db |
进入该db文件后执行如下查询命令,能看到sqlite3的建表语句,将其替换掉MySQL中导出sql里面的建表命令。
1 | SELECT sql FROM sqlite_master WHERE type='table'; |
如果你用的不是peewee这种ORM库,则还需要自行修改建表命令为sqlite3的命令(可以问问gpt让他帮你改一下,或者自己重写一个)。比如在sqlite3中就不支持表后跟随的AUTO_INCREMENT=4728
语句。
文件导入到sqlite3
sqlite3的导入命令格式如下,左侧是数据库文件名字,右侧是需要导入的源sql文件。为了避免文件名编码问题,建议使用全英文名字。
1 | sqlite3 数据库名字.db < 需要导入的文件.sql |
这个命令成功的时候不会有任何输出,使用如下命令进入导入后生成的db文件中
1 | sqlite3 数据库名字.db |
不出意外的话,所有数据就已经导入到这个新的数据库文件中了,检查一下和MySQL中的数据库有没有不一样的地方吧!
The end
有更多问题,欢迎评论留言讨论。