数据库上线&迭代上线
上线是啥?迭代上线是啥?
数据库上线: 线上数据库的初始化, 其实就是/sql/init.sql
的生成
数据库 迭代上线: 将开发环境的数据库变动同步至线上, 主要是 同步数据库结构 和 系统数据到 线上数据库
注意: 业务数据是不需要同步 到线上的。
数据库上线
方案1: 使用Navicat导出init.sql
方案2: 使用Javascript导出init.sql
package.json
{
"dependencies": {
"dotenv": "16.0.2",
"knex": "^1.0.1",
"mysql": "^2.18.1",
"mysqldump": "^3.2.0"
},
"scripts": {
"dumpSql": "node ./dumpSql.js"
}
}
.env
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=123456
dumpSql.js
'use strict';
/**
* - 如果使用code runner 运行, 则将env配置到 '../.env'
* - 如果使用node xxx.js 运行, 则将env配置到 './jianghujs-script-util/.env'
*/
require('dotenv').config();
const mysqldump = require('mysqldump')
const Knex = require('knex')
const fs = require("fs");
const path = require('path')
const connection = {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
};
/**
* 导出 sql
* @param database 数据库
* @param noDataTables 不导出数据的表,如 log 相关表
* @param clearFields 导出前清除的表的字段
* @param sqlFile 导出文件
* @param replace 关键字替换
* @returns {Promise<void>}
*/
async function dumpSql({ database, noDataTables, sqlFile, replace, isIgnoreAllBizTable, isIgnoreAllBizTableData }) {
connection.database = database;
const knex = Knex({
client: 'mysql',
connection,
});
const startTime = new Date().getTime();
const res = await mysqldump({
connection,
dump: {
data: {
format: false
},
schema: {
table: {
dropIfExist: true,
},
},
trigger: {
dropIfExist: false,
},
}
});
let content = '';
res.tables.forEach(tableData => {
if (isIgnoreAllBizTable && !tableData.name.startsWith('_')) {
return;
}
if (noDataTables.includes(tableData.name) || (isIgnoreAllBizTableData && !tableData.name.startsWith('_'))) {
// content += tableData.schema + '\n' + (tableData.triggers && tableData.triggers.join('\n') || '') + '\n\n\n'
content += tableData.schema + '\n\n\n'
} else {
// content += tableData.schema + '\n' + (tableData.data || '') + '\n' + (tableData.triggers && tableData.triggers.join('\n') || '') + '\n\n\n'
content += tableData.schema + '\n' + (tableData.data || '') + '\n\n\n'
}
})
replace.forEach((item) => {
content = content.replace(new RegExp(/DROP TRIGGER IF EXISTS (\w*);/, 'g'), 'DROP TRIGGER IF EXISTS `$1`;')
content = content.replace(new RegExp(item.key, 'g'), item.value)
})
// 干掉init.sql trigger的注释
content = content.replace(new RegExp(/# ------------------------------------------------------------\n# TRIGGER DUMP FOR: .*?\n# ------------------------------------------------------------\n/, 'g'), "");
content = content.replace(new RegExp(/# ------------------------------------------------------------\n# DATA DUMP FOR TABLE: .*?\n# ------------------------------------------------------------\n/, 'g'), "");
fs.writeFileSync(sqlFile, content);
const endTime = new Date().getTime();
console.log(`导出${database}结束, useTime: ${(endTime - startTime) / 1000.00}/s, sqlFile: ${sqlFile}`)
await knex.destroy();
}
// 不导出数据部分的表
let noDataTables = [
"_cache",
"_resource_request_log",
"_user_session",
"_record_history",
"duoxing_chat_session",
"duoxing_message_history",
"_file",
"article_history",
"_user"
];
// 导出前清理表中的无用字段
let replace = [
// 前缀处理成模板
// { key: 'jianghujs_demo_enterprise_', value: '{{dbPrefix}}'},
// 抹掉 utf8 相关配置
{ key: ' COLLATE utf8mb4_bin', value: '' },
{ key: ' COLLATE utf8', value: '' },
{ key: ' COLLATE = utf8mb4_bin', value: '' },
{ key: ' COLLATE = utf8', value: '' },
{ key: ' DEFAULT CHARSET = utf8mb4_bin', value: '' },
{ key: ' DEFAULT CHARSET = utf8mb4', value: '' },
{ key: ' DEFAULT CHARSET = utf8', value: '' },
{ key: ' CHARACTER SET utf8mb4_bin', value: '' },
{ key: ' CHARACTER SET utf8mb4', value: '' },
{ key: ' CHARACTER SET utf8', value: '' },
];
(async () => {
const currentProjectDir = path.join(__dirname, '..');
const projectList = [
{ database: 'my_basic', projectName: 'my-basic', isIgnoreAllBizTableData: true },
]
for (const project of projectList) {
const projectNoDataTables = project.projectNoDataTables || [];
await dumpSql({
database: project.database,
sqlFile: `${currentProjectDir}/sql/init.${project.projectName}.sql`,
noDataTables: [...noDataTables, ...projectNoDataTables],
replace,
isIgnoreAllBizTable: project.isIgnoreAllBizTable,
isIgnoreAllBizTableData: project.isIgnoreAllBizTableData,
});
}
})()
运行node ./dumpSql.js
,脚本就会将init.sql
导出来
注意:_user数据比较隐私, 所以你需要手动导入
INSERT INTO `_user` (`id`, `userId`, `username`, `clearTextPassword`, `password`, `md5Salt`, `userStatus`, `userType`, `operation`, `operationByUserId`, `operationByUser`, `operationAt`) VALUES (1, 'admin', '系统管理员', '123456', '38d61d315e62546fe7f1013e31d42f57', 'Xs4JSZnhiwsR', 'active', NULL, 'insert', 'admin', '系统管理员', '2022-09-15T23:46:04+08:00');
数据库迭代上线
迭代上线我们 使用 navicat 的 结构同步
和 数据同步
功能
注意⚠️:结构同步时 只需同步以下的选项:
注意⚠️:数据同步时只需同步某些系统配置表,同步时勾选如下(可以通过右键取消全选后再选中这些表):