工作日大半夜发文……

背景是给服务器额外弄了块云数据盘,并且兴致冲冲格成了 XFS,于是就想装个 PostgreSQL 玩玩,顺便就想把一些项目原本放在 SQLite3 中的数据迁移到正规的数据库

本来下班前已经完成了 SQLite3 到 PostgreSQL 的迁移,但是发现博客里有些插件会在 sql 里写 int(10) 这种东西,然后在只认 integer 的 PostgreSQL 上就光荣挂掉了(其实主要影响了可以忽略不计的阅读量统计,以及评论发表,虽然也没啥评论

想一想还是用 MySQL 吧。于是上手五年没碰过的 MySQL,上来就遇到 MySQL8 默认鉴权方式的坑,最后在 Google 的帮助下才把 root@localhost 的鉴权改成了老的方式让 php 能用

然后新的问题又出现了,SQLite3 生成的 dump 文件里表名、字段名都是双引号 ",但是 MySQL 里只认 ` 不认 ",本来想写一个正则替换了事结果发现事情并没有那么简单:可能还是误改到了 values 里面的一些东西,反正最后直接是 php 报错了

索性就写个脚本逐条拷贝算了(需要先运行 install.php 生成表结构):

const util = require('util')
const mysql = require('mysql')
const sqilte3 = require('sqlite3')

const dbpath = '/data/www/blog/usr/blog.db'
/** @type Promise<sqilte3.Database> */
const linkSqlite = new Promise((res, rej) => {
  const db = new sqilte3.Database(dbpath, err => {
    err ? rej(err) : res(db)
  })
})

const con = mysql.createConnection({
  user: 'root',
  database: 'typecho',
})

const query = util.promisify(con.query.bind(con))
const connect = util.promisify(con.connect.bind(con))

{(async () => {
  await connect()
  const lite = await linkSqlite
  const all = util.promisify(lite.all.bind(lite))
  const tbs = await query('show tables')
  for (const tb of tbs) {
    const table = Object.values(tb)[0]
    await query(`delete from ${table}`)
    const cols = await query(`show columns from ${table}`)
    const keys = cols.map(x => x.Field)
    const datas = await all(`select * from ${table}`)
    let cnt = 0
    for (const data of datas) {
      cnt++
      const sql = mysql.format(
        `insert into \`${table}\` (${
          keys.map(k => `\`${k}\``).join(',')
        }) values (${
          keys.map(() => '?').join(',')
        })`,
        keys.map(k => data[k])
      )
      await query(sql)
    }
    console.log('insert to', table, 'count', cnt)
  }
  con.destroy()
})()}

顺利收工,睡觉!