feat: 优化设备位置冲突检测和前端虚拟滚动
为设备表添加复合索引优化位置冲突检测性能 在设备位置检查中添加悲观锁防止竞态条件 添加 react-window 和 react-virtualized-auto-sizer 支持虚拟滚动
This commit is contained in:
@@ -103,6 +103,9 @@ const Device = sequelize.define(
|
||||
{ fields: ['createdAt'] },
|
||||
{ fields: ['status', 'type'] },
|
||||
{ fields: ['name'] },
|
||||
// 优化位置冲突检测的复合索引
|
||||
{ fields: ['rackId', 'position'] },
|
||||
{ fields: ['rackId', 'position', 'isIdle'] },
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -63,6 +63,8 @@ async function checkPositionAvailable(
|
||||
|
||||
if (transaction) {
|
||||
queryOptions.transaction = transaction;
|
||||
// 使用悲观锁防止竞态条件
|
||||
queryOptions.lock = transaction.LOCK ? transaction.LOCK.UPDATE : 'UPDATE';
|
||||
}
|
||||
|
||||
const existingDevices = await Device.findAll(queryOptions);
|
||||
@@ -126,6 +128,8 @@ async function checkBatchPositions(rackId, devices, excludeDeviceIds = [], trans
|
||||
|
||||
if (transaction) {
|
||||
queryOptions.transaction = transaction;
|
||||
// 使用悲观锁防止竞态条件
|
||||
queryOptions.lock = transaction.LOCK ? transaction.LOCK.UPDATE : 'UPDATE';
|
||||
}
|
||||
|
||||
const existingDevices = await Device.findAll(queryOptions);
|
||||
|
||||
@@ -1033,6 +1033,8 @@ async function checkPositionAvailable(
|
||||
|
||||
if (transaction) {
|
||||
queryOptions.transaction = transaction;
|
||||
// 使用悲观锁防止竞态条件
|
||||
queryOptions.lock = transaction.LOCK ? transaction.LOCK.UPDATE : 'UPDATE';
|
||||
}
|
||||
|
||||
const existingDevices = await Device.findAll(queryOptions);
|
||||
|
||||
@@ -95,6 +95,11 @@ const migrations = [
|
||||
description: '为 deviceFields 表添加 isSystem 字段,标记系统字段不可删除',
|
||||
migrate: migrateDeviceFieldsIsSystem,
|
||||
},
|
||||
{
|
||||
name: '设备位置索引优化',
|
||||
description: '为 devices 表添加复合索引,优化位置冲突检测和悲观锁性能',
|
||||
migrate: migrateDevicePositionIndexes,
|
||||
},
|
||||
];
|
||||
|
||||
async function runMigrations() {
|
||||
@@ -724,6 +729,48 @@ async function migrateIdleDeviceAndBusiness() {
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateDevicePositionIndexes() {
|
||||
const dialect = sequelize.getDialect();
|
||||
const tableName = 'devices';
|
||||
|
||||
if (!(await tableExists(tableName))) {
|
||||
console.log(` ${tableName} 表不存在,跳过`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(` → 为 ${tableName} 表添加复合索引 rackId_position...`);
|
||||
try {
|
||||
if (dialect === 'sqlite') {
|
||||
await sequelize.query(`CREATE INDEX IF NOT EXISTS devices_rackId_position ON ${tableName}(rackId, position)`);
|
||||
} else {
|
||||
await sequelize.query(`CREATE INDEX IF NOT EXISTS \`devices_rackId_position\` ON \`${tableName}\`(\`rackId\`, \`position\`)`);
|
||||
}
|
||||
console.log(' ✓ 索引创建成功');
|
||||
} catch (error) {
|
||||
if (error.message.includes('already exists') || error.message.includes('Duplicate key name')) {
|
||||
console.log(' → 索引已存在,跳过');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(` → 为 ${tableName} 表添加复合索引 rackId_position_isIdle...`);
|
||||
try {
|
||||
if (dialect === 'sqlite') {
|
||||
await sequelize.query(`CREATE INDEX IF NOT EXISTS devices_rackId_position_isIdle ON ${tableName}(rackId, position, isIdle)`);
|
||||
} else {
|
||||
await sequelize.query(`CREATE INDEX IF NOT EXISTS \`devices_rackId_position_isIdle\` ON \`${tableName}\`(\`rackId\`, \`position\`, \`isIdle\`)`);
|
||||
}
|
||||
console.log(' ✓ 索引创建成功');
|
||||
} catch (error) {
|
||||
if (error.message.includes('already exists') || error.message.includes('Duplicate key name')) {
|
||||
console.log(' → 索引已存在,跳过');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行迁移
|
||||
runMigrations().catch(error => {
|
||||
console.error('迁移执行失败:', error);
|
||||
|
||||
Reference in New Issue
Block a user