行会战结束给 2000 人发结算奖励,逐条 INSERT 走 2000 次独立事务:每次事务都要经历开启、写入、提交三步,提交本身是一次磁盘同步(F:\底层文件 的存储访问路径确认提交是 fsync 级开销),2000 次 fsync 就是 2000 次磁盘等待。批处理把 2000 条写入装进一个事务,一次开启一次提交,磁盘同步从 2000 次塌缩到 1 次——开销从"每条一份"变成"每批一份",这是批处理提速的本质。
批量写入器:攒批、整批事务提交、失败整批重试。示例代码如下:
local insertQueue = {}
local function queueReward(actorName, gold)
insertQueue[#insertQueue + 1] =
"INSERT INTO rewards VALUES('" .. actorName .. "'," .. gold .. ")"
end
local function flushRewards()
if #insertQueue == 0 then
return true
end
local batch = table.concat(insertQueue, ";")
local ok = pcall(execTransaction, "BEGIN;" .. batch .. ";COMMIT;")
if ok then
insertQueue = {}
end
return ok
end
调用侧攒批后统一冲刷示例代码如下:
for i, name in ipairs(warMembers) do
queueReward(name, i * 500)
end
flushRewards()
2000 条写入装进一个事务一次性提交,磁盘同步只有一次。
2000 条奖励写入:逐条事务约 4.2 秒(每条约 2 毫秒,大头是提交同步);单事务批量约 0.35 秒,快 12 倍。放大到万级(全服活动结算 10000 条):逐条约 21 秒已不可接受,批量约 1.7 秒。内存代价:批缓冲常驻约 200KB。失败语义变化要注意:批量事务里一条语法错误会让整批回滚,逐条模式只丢一条——失败粒度从条级变成批级,是批处理的代价。
三个不适用场景:一是单条写入的实时性要求高于吞吐(封禁名单插入必须立即可查),批缓冲的延迟不可接受;二是单条失败不能连累整批的场景(玩家自提交的数据),批级回滚会放大故障面,要么逐条、要么批内拆小批(每 200 条一个事务);三是数据源本身可重放(日志类),丢了重拉就行,批处理的失败处理反而多余。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
一、抛坑提问:三方增强插件直接 getmetatable(weapon) 拿到元表,把裁决之杖攻击改到 9999。元表能不能…
一、一行代码拆解:rawget(PriceList, name) —— 这一行绕过元表直达表本体,价目查询不走 __inde…
一、隐蔽陷阱:沙巴克守城名单清理离线成员,正序 for 循环里 table.remove(list, i),删一个后续整体前…
一、线上事故:运营要按供需公式浮动裁决之杖价格,某次把表达式字符串直接塞进裸 loadstring 执行,串里夹带未知全局调…
一、线上事故:红名洗白进度按 10 段槽位刷新,GM 修正过 PK 值的玩家带着 -8 的负值进来,进度槽算出 -2,进度条…
一、抛坑提问:烈火剑法连招表存着 4 段延时 {200, 400, 600, 900},算总窗要逐个相加。段数扩到 6 段,…