使用经典ASP/Javascript ADODB实现MS Access表增量复制问题咨询
经典ASP站点GoDaddy数据库增量更新锁库问题解决方案
一、现有增量代码运行异常的常见原因
- 主键/唯一标识匹配逻辑错误:增量更新依赖每条记录的唯一不可变ID(比如自增ID、业务唯一编码),如果代码里用来判断「记录是否存在」的字段允许重复,会导致插入重复数据或者更新遗漏
- 新旧数据集对比逻辑性能差:如果直接在ASP层逐行遍历全量源数据查库判断,数据量大的时候会触发GoDaddy共享数据库的连接数/超时限制,看起来就像代码运行失败
- 事务使用不当:如果增量操作包了大事务,执行时间过长反而会触发锁表,和之前全量覆盖的问题一致
- 数据类型不匹配:经典ASP对数据类型校验弱,如果源数据里的数字、日期格式和数据库字段不匹配,更新/插入语句会静默失败
二、可落地的增量更新实现方案
2.1 前置准备
- 给所有需要更新的业务表加唯一标识字段和最后修改时间戳字段,比如
last_modified(datetime类型,默认值设为当前时间,更新数据时自动触发修改),作为增量判断的依据 - 每日刷新的源数据必须同步包含上述唯一标识和修改时间字段
2.2 数据库层优先的增量操作(性能最高,避免ASP层处理的性能问题)
推荐优先用这个方案,比ASP层逐行处理稳定性高很多,GoDaddy的SQL Server/MySQL都支持这种语法
如果是MySQL库
用INSERT ... ON DUPLICATE KEY UPDATE语法,单次语句完成新增+更新,不需要先查库判断:
INSERT INTO 目标表 (id, 字段1, 字段2, last_modified) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE 字段1 = VALUES(字段1), 字段2 = VALUES(字段2), last_modified = VALUES(last_modified);
如果是批量导入,可以先把当日全量源数据导入临时表temp_source,再一次性关联更新主表:
-- 先更新已存在的记录 UPDATE 主表 m INNER JOIN temp_source s ON m.id = s.id SET m.字段1 = s.字段1, m.字段2 = s.字段2, m.last_modified = s.last_modified WHERE s.last_modified > m.last_modified; -- 再插入新增的记录 INSERT INTO 主表 (id, 字段1, 字段2, last_modified) SELECT s.id, s.字段1, s.字段2, s.last_modified FROM temp_source s LEFT JOIN 主表 m ON s.id = m.id WHERE m.id IS NULL;
如果是SQL Server库
用MERGE语法完成单次合并操作:
MERGE 主表 m USING temp_source s ON m.id = s.id WHEN MATCHED AND s.last_modified > m.last_modified THEN UPDATE SET m.字段1 = s.字段1, m.字段2 = s.字段2, m.last_modified = s.last_modified WHEN NOT MATCHED BY TARGET THEN INSERT (id, 字段1, 字段2, last_modified) VALUES (s.id, s.字段1, s.字段2, s.last_modified);
2.3 避免锁库的补充优化
- 把原来的每日单批次全量操作,拆成每小时/每2小时的小批次增量操作,单次操作数据量小,锁表时间极短,不会触发站点崩溃
- 操作时间选站点访问低谷期(比如凌晨2-4点),GoDaddy共享数据库的负载也更低
- 如果还是出现锁问题,可以在更新前先执行
SET LOCK_TIMEOUT 1000(单位毫秒),如果拿不到锁就等待1秒后重试,最多重试3次就跳过当前批次,后续再补更
三、经典ASP代码调试注意事项
- 开启ASP的错误提示:在页面顶部加
<% On Error Resume Next %>,执行完SQL语句后判断Err.Number是否不为0,输出具体的错误信息和执行的SQL语句,方便定位语法错误 - 避免用Recordset做更新操作,直接用
Connection.Execute执行原生SQL,性能更高也更稳定 - 每执行100条操作就主动关闭再重开数据库连接,避免GoDaddy的连接超时限制
内容的提问来源于stack exchange,提问作者jay bee
相关产品推荐
相关产品推荐

