从单 Agent 到跨 Agent 的 Skills 管理
2026/10/1 8:25:20
UPDATE users SET name='John' WHERE id=100000000000000看似简单,但其执行过程涉及索引查找、行锁、Redo/Undo 生成、Buffer Pool 修改等多层机制。
✅核心原则:
即使 UPDATE 未命中任何行,仍会走完整执行流程(含锁和日志)。
UPDATE、表名、SET 子句、WHERE 条件users表存在name、id列是否存在UPDATE权限WHERE id=...→选择主键索引(聚簇索引)⚠️关键点:
主键查询是 InnoDB 最高效的路径(O(log n) B+ 树搜索)。
id=100000000000000的 16KB 页id=100000000000000Affected rows: 0💡为什么仍需锁?
即使记录不存在,InnoDB 可能加间隙锁(Gap Lock)防止幻读(取决于隔离级别)。
id=100000000000000对应的记录(前一个id, 后一个id)(99999999999999, 100000000000001))id=100000000000000⚠️死锁风险:
高并发下,间隙锁可能引发死锁(需应用层重试)。
name='OldName'ROLLBACK时恢复旧值💡即使 name 未变:
InnoDB 仍会生成 Undo(因无法预知值是否相同)。
name字段从旧值改为'John'// 聚簇索引变更MLOG_REC_UPDATE_IN_PLACE:page_id=12345,offset=200,data="John"// Undo Log 变更MLOG_WRITE_STRING:undo_page=67890,offset=100,data="OldName"fsync()确保 Redo 落盘⚠️Double Write Buffer:
脏页刷盘时,先写双写区 → 防页断裂。
| 环节 | 潜在瓶颈 | 优化方向 |
|---|---|---|
| 主键查找 | Buffer Pool 未命中 → 磁盘 I/O | 增大innodb_buffer_pool_size |
| 行锁竞争 | 高并发更新同一行 | 应用层队列化 |
| Redo 刷盘 | fsync延迟高 | 使用 NVMe SSD |
| Undo 积累 | 长事务阻塞 Purge | 避免大事务 |
UPDATEusersSETname='John'WHEREid=100ANDname='John';SELECT判断,避免无效 UPDATE。-- 当前锁等待SELECT*FROMinformation_schema.INNODB_LOCKS;-- 事务状态SELECT*FROMinformation_schema.INNODB_TRX;EXPLAINUPDATEusersSETname='John'WHEREid=100000000000000;-- 输出: type=const, key=PRIMARYSHOWGLOBALSTATUSLIKE'Innodb_os_log_written';-- 对比 UPDATE 前后增量确保主键高效:
减少无效更新:
// 应用层判断if($oldName!=='John'){$db->update('users',['name'=>'John'],['id'=>$id]);}批量更新替代单条:
UPDATEusersSETname=CASEidWHEN1THEN'A'WHEN2THEN'B'ENDWHEREidIN(1,2);监控长事务:
-- 查找运行超过 60 秒的事务SELECT*FROMinformation_schema.INNODB_TRXWHERETIME_TO_SEC(TIMEDIFF(NOW(),trx_started))>60;💡一句话:
主键 UPDATE 是 InnoDB 的拿手好戏,
但再快的操作,也快不过“不操作”。