sqlite3只小巧轻便,但是并不支持并发访问,但网站并发量较大时候,数据库请求队列边长,有可能导致队列末尾去数据库操作超时,从而操作失败。因此需要切换到支持并发访问的数据库。
切换数据库需要将老的数据导出,再导入到新的数据库中,但是sqlite3和mysql的数据库并不完全兼容,需要做部分调整才能正常导入到mysql中。
需要忽略如下语句:
BEGIN TRANSACTION
COMMIT
sqlite_sequence
CREATE UNIQUE INDEX
PRAGMA foreign_keys=OFF
并做如下替换
"tablename/field" => `tablename/field`
布尔值 't' => 1, 'f' => 0
AUTOINCREMENT => AUTO_INCREMENT
varchar => varchar(255)
CREATE TABLE table... => DROP TABLE table; CREATE TABLE table...
为了尽可能减少切换数据库所需时间,需要对导出的sql文件做点优化,将多条插入语句合并成一条。
INSERT INTO table VALUES('val1');
INSERT INTO table VALUES('val2'); => INSERT INTO table VALUES('val1'), ('val2'), ('val3');
INSERT INTO table VALUES('val3');
并在插入语句前设置
SET AUTOCOMMIT=0;
采用这两项优化之后可以大幅度加快导入速度。
上述这些改动可以采用脚本完成,bash不够灵活,python字符串处理效率比较低,所以我最终选用perl,处理速度与用bash命令差不多,同时也能很容易实现复杂的处理逻辑。
处理之后的sql文件导入到mysql中可能会出现如下错误
原因是合并多条语句最终会有很多单条语句长度超过默认的max_allowed_packet值(16M),可以将其设置为mysql允许的最大值(1G),
SET GLOBAL max_allowed_packet=209715200;
最后放上最终的转化脚本 sqlite2mysql.pl