数据库上线&迭代上线
上线是啥?迭代上线是啥?
数据库上线: 线上数据库的初始化, 其实就是/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.1DB_PORT=3306DB_USER=rootDB_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 的 结构同步 和 数据同步功能
注意⚠️:结构同步时 只需同步以下的选项:
注意⚠️:数据同步时只需同步某些系统配置表,同步时勾选如下(可以通过右键取消全选后再选中这些表):