198 lines
6.4 KiB
JavaScript
198 lines
6.4 KiB
JavaScript
/**
|
||
* 领主赏记录表迁移脚本
|
||
* 从 MySQL goods_king_rank 表迁移到 SQL Server goods_king_ranks 表
|
||
*/
|
||
|
||
const mysql = require('mysql2/promise');
|
||
const sql = require('mssql');
|
||
|
||
// MySQL 配置
|
||
const mysqlConfig = {
|
||
host: '192.168.195.16',
|
||
port: 1887,
|
||
user: 'root',
|
||
password: 'Dbt@com@123',
|
||
database: 'youdas',
|
||
charset: 'utf8mb4'
|
||
};
|
||
|
||
// SQL Server 配置
|
||
const sqlServerConfig = {
|
||
server: '192.168.195.15',
|
||
port: 1433,
|
||
user: 'sa',
|
||
password: 'Dbt@com@123',
|
||
database: 'honey_box',
|
||
options: {
|
||
encrypt: false,
|
||
trustServerCertificate: true
|
||
}
|
||
};
|
||
|
||
// 批量大小
|
||
const BATCH_SIZE = 1000;
|
||
|
||
async function createTable(pool) {
|
||
console.log('创建 goods_king_ranks 表...');
|
||
|
||
const createTableSql = `
|
||
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='goods_king_ranks' AND xtype='U')
|
||
BEGIN
|
||
CREATE TABLE goods_king_ranks (
|
||
id INT IDENTITY(1,1) PRIMARY KEY,
|
||
user_id INT NOT NULL,
|
||
goods_id INT NOT NULL,
|
||
count INT NOT NULL DEFAULT 0,
|
||
z_nums INT NOT NULL DEFAULT 0,
|
||
money DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||
order_list_id INT NOT NULL DEFAULT 0,
|
||
addtime INT NOT NULL DEFAULT 0,
|
||
end_time INT NOT NULL DEFAULT 0,
|
||
CONSTRAINT pk_goods_king_ranks PRIMARY KEY CLUSTERED (id)
|
||
);
|
||
|
||
CREATE INDEX ix_goods_king_ranks_user_id ON goods_king_ranks(user_id);
|
||
CREATE INDEX ix_goods_king_ranks_goods_id ON goods_king_ranks(goods_id);
|
||
CREATE INDEX ix_goods_king_ranks_user_goods ON goods_king_ranks(user_id, goods_id);
|
||
|
||
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'领主赏记录表,记录领主占领和挑战信息', @level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'goods_king_ranks';
|
||
END
|
||
`;
|
||
|
||
await pool.request().query(createTableSql);
|
||
console.log('表创建完成');
|
||
}
|
||
|
||
async function getSourceCount(mysqlConn) {
|
||
const [rows] = await mysqlConn.execute('SELECT COUNT(*) as count FROM goods_king_rank');
|
||
return rows[0].count;
|
||
}
|
||
|
||
async function getTargetCount(pool) {
|
||
const result = await pool.request().query('SELECT COUNT(*) as count FROM goods_king_ranks');
|
||
return result.recordset[0].count;
|
||
}
|
||
|
||
async function migrateData(mysqlConn, sqlPool) {
|
||
const sourceCount = await getSourceCount(mysqlConn);
|
||
console.log(`源表记录数: ${sourceCount}`);
|
||
|
||
if (sourceCount === 0) {
|
||
console.log('源表无数据,跳过迁移');
|
||
return;
|
||
}
|
||
|
||
// 清空目标表
|
||
console.log('清空目标表...');
|
||
await sqlPool.request().query('TRUNCATE TABLE goods_king_ranks');
|
||
|
||
// 开启 IDENTITY_INSERT
|
||
await sqlPool.request().query('SET IDENTITY_INSERT goods_king_ranks ON');
|
||
|
||
let offset = 0;
|
||
let migratedCount = 0;
|
||
|
||
while (offset < sourceCount) {
|
||
console.log(`迁移进度: ${offset}/${sourceCount}`);
|
||
|
||
// 从 MySQL 读取数据
|
||
const [rows] = await mysqlConn.execute(
|
||
`SELECT id, user_id, goods_id, count, z_nums, money, order_list_id, addtime, end_time
|
||
FROM goods_king_rank
|
||
ORDER BY id
|
||
LIMIT ? OFFSET ?`,
|
||
[BATCH_SIZE, offset]
|
||
);
|
||
|
||
if (rows.length === 0) break;
|
||
|
||
// 批量插入到 SQL Server
|
||
const table = new sql.Table('goods_king_ranks');
|
||
table.create = false;
|
||
table.columns.add('id', sql.Int, { nullable: false });
|
||
table.columns.add('user_id', sql.Int, { nullable: false });
|
||
table.columns.add('goods_id', sql.Int, { nullable: false });
|
||
table.columns.add('count', sql.Int, { nullable: false });
|
||
table.columns.add('z_nums', sql.Int, { nullable: false });
|
||
table.columns.add('money', sql.Decimal(10, 2), { nullable: false });
|
||
table.columns.add('order_list_id', sql.Int, { nullable: false });
|
||
table.columns.add('addtime', sql.Int, { nullable: false });
|
||
table.columns.add('end_time', sql.Int, { nullable: false });
|
||
|
||
for (const row of rows) {
|
||
table.rows.add(
|
||
row.id,
|
||
row.user_id || 0,
|
||
row.goods_id || 0,
|
||
row.count || 0,
|
||
row.z_nums || 0,
|
||
row.money || 0,
|
||
row.order_list_id || 0,
|
||
row.addtime || 0,
|
||
row.end_time || 0
|
||
);
|
||
}
|
||
|
||
const request = sqlPool.request();
|
||
await request.bulk(table);
|
||
|
||
migratedCount += rows.length;
|
||
offset += BATCH_SIZE;
|
||
}
|
||
|
||
// 关闭 IDENTITY_INSERT
|
||
await sqlPool.request().query('SET IDENTITY_INSERT goods_king_ranks OFF');
|
||
|
||
// 重置自增序列
|
||
const maxIdResult = await sqlPool.request().query('SELECT MAX(id) as maxId FROM goods_king_ranks');
|
||
const maxId = maxIdResult.recordset[0].maxId || 0;
|
||
await sqlPool.request().query(`DBCC CHECKIDENT ('goods_king_ranks', RESEED, ${maxId})`);
|
||
|
||
console.log(`迁移完成,共迁移 ${migratedCount} 条记录`);
|
||
}
|
||
|
||
async function validate(mysqlConn, sqlPool) {
|
||
console.log('\n验证迁移结果...');
|
||
|
||
const sourceCount = await getSourceCount(mysqlConn);
|
||
const targetCount = await getTargetCount(sqlPool);
|
||
|
||
console.log(`源表记录数: ${sourceCount}`);
|
||
console.log(`目标表记录数: ${targetCount}`);
|
||
|
||
if (sourceCount === targetCount) {
|
||
console.log('✓ 记录数一致');
|
||
} else {
|
||
console.log('✗ 记录数不一致!');
|
||
}
|
||
}
|
||
|
||
async function main() {
|
||
let mysqlConn = null;
|
||
let sqlPool = null;
|
||
|
||
try {
|
||
console.log('连接 MySQL...');
|
||
mysqlConn = await mysql.createConnection(mysqlConfig);
|
||
console.log('MySQL 连接成功');
|
||
|
||
console.log('连接 SQL Server...');
|
||
sqlPool = await sql.connect(sqlServerConfig);
|
||
console.log('SQL Server 连接成功');
|
||
|
||
await createTable(sqlPool);
|
||
await migrateData(mysqlConn, sqlPool);
|
||
await validate(mysqlConn, sqlPool);
|
||
|
||
console.log('\n迁移任务完成!');
|
||
} catch (error) {
|
||
console.error('迁移失败:', error);
|
||
process.exit(1);
|
||
} finally {
|
||
if (mysqlConn) await mysqlConn.end();
|
||
if (sqlPool) await sqlPool.close();
|
||
}
|
||
}
|
||
|
||
main();
|