MySQL事务隔离与MVCC:从ReadView到间隙锁的并发控制全解析
1. 为什么要搞懂事务隔离和MVCC先回答一个很多开发者问过我的问题隔离级别和MVCC到底值不值得花时间啃我的答案是值得而且越早啃越省事。MySQL的InnoDB引擎是默认存储引擎是不是单行读还是批量导入最终都会落在事务和并发控制这层。搞懂MVCC不仅仅是应付面试更多时候是线上出问题了比如死锁、脏读、可重复读失效你得能快速定位到是哪儿出了问题。没有这套底层认知你就只能靠重启试试加索引试试这种碰运气的办法。这篇我不会按教科书那套讲法讲而是从实际使用场景出发把事务隔离级别、ReadView机制、undo log版本链、当前读快照读这些概念串成一个完整链路。看完你至少能做到能说清楚RR级别下为什么不会幻读、RC和RR在底层有什么区别、什么时候读不到刚提交的数据、死锁日志该怎么看。2. 事务隔离级别的本质2.1 隔离级别到底隔离了什么事务的ACID大家应该都熟悉其中IIsolation就是隔离性。并发事务同时执行时隔离性决定了你的事务能看到多少别人的操作。太低会出乱子太高会让并发性能大幅下降这是个取舍问题。要理解隔离级别先得搞清楚它要解决的三类问题脏读读到别的事务还没提交的数据。对方如果回滚了你就等于读了一个假数据。不可重复读同一条数据事务内前后读了两次结果不一样其他事务修改并提交了。幻读同一个查询条件事务内前后查了两次结果集的行数不一样其他事务插入或删除了记录。MySQL的InnoDB提供了四种隔离级别隔离级别脏读不可重复读幻读READ UNCOMMITTED可能可能可能READ COMMITTED不可能可能可能REPEATABLE READ不可能不可能可能InnoDB实际解决SERIALIZABLE不可能不可能不可能2.2 REPEATABLE READ下的幻读到底是解决了还是没解决有个很容易踩坑的知识点MySQL官方文档说RR级别存在幻读可能但InnoDB在大多数场景下通过MVCC加间隙锁把幻读解决了。这个大多数场景很微妙。快照读普通的SELECT在RR下永远不会幻读因为MVCC通过ReadView保证了每次读到的都是事务开始时的快照。但如果你的场景里出现了当前读加锁的SELECT ... FOR UPDATE、UPDATE、DELETE幻读就可能钻空子。举个例子-- 事务A START TRANSACTION; SELECT * FROM user WHERE id 100 FOR UPDATE; -- 此时锁住了id 100的间隙 -- 事务B INSERT INTO user(id, name) VALUES(105, new); -- 阻塞直到事务A提交如果事务A的查询条件没有建立索引InnoDB的间隙锁锁的是整个索引范围还能防住。但如果条件没走索引间隙锁锁的是主键索引的所有间隙效果差异很大这也是为什么建议大范围更新前检查执行计划。我之前遇到过这样一个线上问题某表在RR级别下一个事务内先查了一次快照然后另一个事务插入了一条符合条件的新数据并提交第一个事务再执行当前读居然读到了这条新数据。表面上是幻读但严格来说是快照读和当前读在RR下读的不是一个版本链。所以排查问题的时候先确认你执行的是不是当前读。2.3 实际开发中隔离级别怎么选默认的REPEATABLE READRR对大部分业务是够用的因为InnoDB在MVCC上做的优化让RR的并发性能损失没那么大。但有一个场景我建议切换到READ COMMITTEDRC高并发下的热点行更新。原因很简单RR下的间隙锁范围更大锁冲突概率更高很容易出现死锁。RC下没有间隙锁只有行锁冲突面和等待时间都会降下来。很多大流量系统比如秒杀、库存扣减都主动切到RC再用分布式锁或者乐观锁去保证业务一致性。不过要注意RC有它的代价——不可重复读。典型场景就是统计类SQL事务内多次做SUM查询如果期间有别的事务提交了数据每次查的结果可能都不一样。业务方必须能接受这种不一致否则就得考虑对汇总表加锁或干脆用SERIALIZABLE。3. MVCC底层机制全拆解3.1 一条记录怎么变成多个版本MVCCMulti-Version Concurrency Control叫多版本并发控制。核心思想不是加锁去阻塞读和写而是每条记录维护多个历史版本让读写不互相等待。读读随便并发读写大概率也并发只有写写才需要真正的锁。InnoDB在聚簇索引主键索引的记录里隐藏了三个核心字段DB_TRX_ID最后一次修改这条记录的事务ID。DB_ROLL_PTR回滚指针指向undo log里上一个版本的位置。DB_ROW_ID没有主键时内部生成的自增行ID有主键则无该字段。你每修改一条记录InnoDB不会直接覆盖旧值而是先把旧值写进undo log然后把DB_ROLL_PTR指向这个旧版本最后更新DB_TRX_ID和新的数据值。这样一来同一条逻辑记录就在undo log里串成了一条版本链表。从一个实际更新来感受下这个过程-- 假设初始记录id1, nameA, trx_id100 -- 事务200执行UPDATE user SET nameB WHERE id1; -- 发生的事 1. 先把id1的旧值nameA, trx_id100copy到undo log 2. 更新聚簇索引记录nameBDB_TRX_ID200 3. DB_ROLL_PTR指向undo log中的旧版本此时如果要回滚InnoDB顺着DB_ROLL_PTR链路找到最老的版本直接恢复数据即可。不需要额外存一份变更前快照这就是undo log承担的责任。3.2 ReadView是快照读的透视镜每个事务开始快照读时会生成一个ReadView它决定了你在这个事务里能看到哪个版本的数据。ReadView的核心字段就四个m_ids生成ReadView时当前系统内活跃事务ID的列表。min_trx_idm_ids里最小的事务ID。max_trx_id生成ReadView时系统分配给下一个事务的ID注意这不是活跃事务的最大ID是未来事务的起点。creator_trx_id创建这个ReadView的事务自己的ID。判断一条记录对当前事务是否可见逻辑如下条件可见性结论DB_TRX_ID creator_trx_id可见自己改的当然能看见DB_TRX_ID min_trx_id可见修改记录的事务已提交DB_TRX_ID max_trx_id不可见记录是未来事务改的DB_TRX_ID在m_ids中不可见修改事务仍在活跃未提交DB_TRX_ID不在m_ids中可见修改事务已提交如果当前版本的记录不可见就顺着DB_ROLL_PTR往下找下一个版本继续用同样的规则判断直到找到可见版本。找不到那就返回空。用生活化的例子ReadView就像你在餐厅点菜时拿到的号码牌你进场时已经在场的客人活跃事务的账单状态你看不到你进场之后才来的客人他们点的菜端上来之前你也看不见只有你进场之前就已经结账离开的客人他们点什么你完全看得见。3.3 RC和RR的核心差异ReadView的创建时机这是面试也常考的也是理解MVCC的最关键差异。READ COMMITTED级别下每个快照读语句执行时都会生成一个新的ReadView。正因为每次快照都重新拍一张照片所以事务内两次相同的SELECT可能看到不同的结果——这就是不可重复读。REPEATABLE READ级别下事务内第一次执行快照读时生成ReadView之后整个事务内所有的快照读都复用这一个ReadView不再更新。于是你始终看到的是同一个版本——这就是可重复读。这里有一个值得注意的细节RR下如果事务一开始没有执行快照读而是在执行了当前读比如UPDATEInnoDB会为这个当前读生成一个ReadView后续的快照读也会沿用这个ReadView。我实习时遇到过一次问题就是因为先做了一次UPDATE才做SELECT结果跟预期完全不一样后来追踪发现就是这个原因。再说清楚一点快照读本身是不加锁的MVCC读当前读是加锁的读取。前者的可见性是靠ReadView决定的后者是直接读最新版本并且加锁。4. undo log版本链与回滚实操4.1 undo log的两种类型undo log其实分两种INSERT undo log插入操作产生的。因为插入的记录对别的事务不可见未提交前回滚时直接删除这条记录的聚簇索引即可。这种undo log在事务提交后就可以直接清理不需要参与MVCC版本链判断。UPDATE undo log更新和删除操作产生的。删除本质上也是一种更新打删除标记。这种undo log要保留到没有任何事务的ReadView还需要看到它时才能被purge线程清理。我一直提醒团队里新人大事务是undo log膨胀的第一元凶。一个事务里UPDATE几百万行事务迟迟不提交这些版本的undo log就全部不能清理。线上表现就是ibdata1文件疯狂涨甚至磁盘被打满。所以OLTP系统里大事务一定要拆批控制在几千行一个事务提交一次。4.2 长事务和死锁的联动长事务本身不只是日志膨胀的问题还会加剧死锁。因为MVCC下写操作的锁要一直持有到事务提交才能释放长事务意味着锁持有时间拉长两个事务互相等待的概率直线上升。排查长事务可以直接用SELECT * FROM information_schema.INNODB_TRX\G重点看这几列trx_id事务ID看是否过于偏大偏大说明是较新的事务。trx_started事务开始时间和当前时间差超过几秒就要警惕。trx_rows_locked锁了多少行数值异常大说明扫描了很多行。trx_query当前正在执行的SQL判断事务挂在哪条语句上。如果某个连接长时间不提交trx_query可能显示为空因为事务已经执行完但没提交。这种情况光靠这条SQL看不出业务逻辑需要去应用端查这个连接在干什么。4.3 手动模拟一个版本链直观感受MVCC想彻底理解版本链我建议你自己动手模拟一次-- 会话1 START TRANSACTION; UPDATE user SET nameB WHERE id1; -- 先不提交 -- 会话2 START TRANSACTION; UPDATE user SET nameC WHERE id1;此时如果会话2执行更新它会被阻塞因为会话1持有id1的行锁。但如果你把两句话的顺序反过来先会话2更新并提交再会话1更新并提交最后这条记录只有一个版本链前一个版本的undo log很快就会被清理。更直观的方式是-- 查询最近的事务ID分配情况 SELECT TRX_ID, TRX_STARTED FROM information_schema.INNODB_TRX;然后结合SHOW ENGINE INNODB STATUS的TRANSACTIONS段落可以看到每个事务的undo log条目数和锁等待。建议把两三个客户端开起来交叉执行上面这些SQL实际体验比对着一堆文档想象要深得多。5. 当前读与快照读什么时候用哪个5.1 两种读的边界很多人分不清当前读和快照读但这两者的语义完全不同。快照读普通SELECT不加锁读的是ReadView可见的版本。不阻塞任何写操作写操作也不阻塞它。当前读SELECT ... FOR UPDATE、SELECT ... LOCK IN SHARE MODE、UPDATE、DELETE、INSERT在特定条件下。读的是最新已提交的数据版本并且对记录加锁。举例说明-- 会话1 START TRANSACTION; SELECT * FROM user WHERE id1; -- 得到 nameB假设这是旧版本 -- 会话2 START TRANSACTION; UPDATE user SET nameD WHERE id1; COMMIT; -- 会话1再次执行快照读 SELECT * FROM user WHERE id1; -- RR下还是nameBRC下就变成nameD但如果会话1改成当前读SELECT * FROM user WHERE id1 FOR UPDATE; -- 无论RR还是RC都会读到nameD这就是为什么很多读不到刚提交数据的问题最后都发现是快照读和当前读混用了。5.2 UPDATE为什么需要先读最新版本当前读必须读最新版本是因为写操作要在最新数据上做修改。如果允许基于旧版本做修改那后提交的事务覆盖先提交事务的修改就会出现丢失更新问题。这就是MVCC加锁配合的真正意义MVCC管读的可见性锁管写的串行化。两者结合在保证多版本的前提下不让写操作损坏数据。5.3 实际业务中怎么分配读写模式大体原则报表类查询数据量大读多写少优先用快照读不加锁性能最好。订单扣减库存这类操作必须在最新数据上判断用当前读。先查后改的复合操作比如先查余额再扣款尽量把查和改合并成一条UPDATE条件语句减少竞态窗口。对于读后写的并发控制最简单有效的方式是版本号字段乐观锁每次更新时检查版本号是否匹配匹配才更新。UPDATE account SET balance balance - 100, version version 1 WHERE id 1 AND version 5;返回影响行数为1则更新成功为0则版本冲突重试即可。这种方式比间隙锁可控得多。6. 间隙锁与RR下幻读的真实防线6.1 什么是间隙锁间隙锁锁的不是具体某条记录而是两个索引记录之间的空隙。比如表里现在主键id有1和5两条记录那(1,5)这个区间就是一个间隙。事务在RR下对id3这条不存在的记录加锁时实际上锁的是(1,5)这个间隙任何尝试往这个间隙里插入数据的操作都会被阻塞。间隙锁和行锁配合构成了Next-Key Lock临键锁它锁的是记录本身前面的间隙。这样设计的目的就是防止幻读你第一次查id 1的记录时锁住了(1,正无穷)这个范围别人就没法在这个范围里插入新行。6.2 间隙锁的边界条件真的很多间隙锁并不是灵丹妙药它的生效条件很苛刻查询条件必须有索引否则InnoDB会锁全表的所有间隙性能灾难。如果查询条件是普通索引非唯一锁的范围会变成一个排他区间包含相邻的范围比单一条件锁的多。唯一索引的等值查询在找到目标记录后会把对应间隙锁升级为行锁没有幻读问题不需要间隙锁。我之前排查过一个死锁案例两条UPDATE语句一条走唯一索引一条走普通索引update了同一批数据但因为加锁顺序不同直接死锁。日志里可以清楚看到一条holding间隙锁另一条waiting行锁交叉等待。6.3 RR必用的场景和推荐做法如果你的业务确实存在先查询一个范围然后根据查询结果做插入的场景又不想出现幻读RR默认就会帮你把间隙锁加上。这种场景下没必要手动处理直接用事务加当前读即可。但如果是高并发系统我建议优先考虑RC乐观锁不要依赖间隙锁做并发控制。原因很实际间隙锁的并发度太低了锁范围大冲突概率高死锁率也高。很多阿里系的数据库中间件默认把隔离级别切到RC不是没有原因的。下面是一个排查死锁的快速SQL记录一下备用SHOW ENGINE INNODB STATUS\G -- 看LATEST DETECTED DEADLOCK段落 -- 重点关注 -- 1. 两个事务各自的SQL -- 2. 各自持有的锁和等待的锁 -- 3. lock_type和index name死锁日志里最容易忽略的是table handle和index name。如果发现锁的是二级索引而不是主键大概率是SQL没有走索引或者索引设计不合理加索引往往比改代码更有效。7. 常见问题排查实录7.1 问题1RR下读到了自己修改的旧数据现象事务A里先UPDATE了某条记录然后同事务里SELECT发现还是旧值。原因这个现象的根本原因往往不是MVCC而是UPDATE的WHERE条件没走索引锁全表但更新到了目标记录。然后SELECT用的快照读ReadView生成在UPDATE之前所以看到的是旧版本。解决确认UPDATE执行计划确保索引命中或者SELECT也改成当前读强制读取最新版本。7.2 问题2一条SQL扫描了太多行但锁却很少现象慢SQL日志里Rows_examined非常高但INNODB_TRX里trx_rows_locked很小。原因InnoDB对扫描过的每一行都会加锁但innodb行锁是不到提交不释放如果SQL走的是覆盖索引可能在索引层面扫描大量记录但实际加锁落地到主键上的行数少所以锁数量看着少但CPU和内存的消耗其实很大。解决优化索引尽量让SQL定位到精确的记录范围减少扫描行数。例如大范围查询改成基于主键的分批查询。7.3 问题3长事务导致undo膨胀现象磁盘空间被打满ibdata1或者undo文件异常增长。原因长事务持有旧版本的ReadView导致undo log版本链无法清理。MySQL的purge线程必须等到所有活跃事务的ReadView都看不到这些旧版本后才能清理。解决找到长事务并处理掉然后在应用层加事务超时控制。最直接的方式是SELECT trx_id, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec FROM information_schema.INNODB_TRX WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) 5;发现超时事务直接kill连接别犹豫。业务代码里也要加事务超时保护避免连接池里的连接长期挂着未提交事务。7.4 问题4RC下同一个事务内SUM结果不一致现象统计SQL在事务里跑了两遍数值对不上。原因RC下每个快照读都生成新的ReadView不可重复读在RC下是允许的甚至可能读到中间状态。解决如果统计结果必须一致事务改成RR级别或者把统计SQL放到一个事务的最开始保证读的是同一个ReadView再或者让统计SQL走当前读加锁但不推荐并发性能太差。8. 我的实操心得文章最后分享两个实际经验。第一排错MVCC问题先不要急着看代码先看binlog和慢查询日志搞清楚出问题的时候对应的SQL走了什么索引、事务执行了多长时间。极多事务隔离问题最终都落在索引没走对或者长事务上。第二在自己的学习环境里多开几个客户端实践是最好的老师。创建一个简单的user表插几行数据然后按上面说的步骤模拟脏读、不可重复读、幻读、死锁。每个现象都亲手复现一遍远比背十篇讲义有用。我面试别人时比较看重的是他能不能用自己的话解释清快照读和当前读的区别这比背出四个隔离级别的定义更能反映水平。希望这篇能帮你在MySQL并发这条路上少踩几个坑。如果你在复现的过程中遇到什么奇怪的现象也欢迎一起交流讨论。

相关新闻

MySQL事务隔离级别与MVCC底层机制实战解析

MySQL事务隔离级别与MVCC底层机制实战解析

干了十几年后端,数据库相关的坑没少踩,尤其是MySQL的事务隔离级别和MVCC这块。面试的时候能把这俩概念背得滚瓜烂熟的人不少,可真到了线上出问题,能不看文档、不看报错堆栈,直接定位到根因的,就没那么多了。…

2026/10/13 7:54:17 阅读更多 →
Oracle 19c补丁静默安装全指南:p6880880 ZIP包结构与OPatch避坑实战

Oracle 19c补丁静默安装全指南:p6880880 ZIP包结构与OPatch避坑实战

简介:本资源是Oracle数据库19c官方补丁p6880880的完整安装包,专为64位Linux系统设计,面向DBA、运维工程师及Oracle数据库高级使用者,用于修复已知安全漏洞、提升系统稳定性与性能表现,尤其适用于生产环境定期维护与合规…

2026/10/13 7:54:17 阅读更多 →
Qt连接MySQL报错驱动未加载?一文讲透QMYSQL驱动编译部署

Qt连接MySQL报错驱动未加载?一文讲透QMYSQL驱动编译部署

很多人第一次遇到 Qt 连接 MySQL 的“驱动未加载”报错时,第一反应都是去翻代码:是不是连接参数写错了?是不是主机名不对?等到把QSqlDatabase相关的代码检查了三遍,才慢慢意识到问题可能根本不在业务代码里&#xff0c…

2026/10/13 7:53:16 阅读更多 →

最新新闻

基于PaddleOCR与PyQt5的GUI车票识别系统设计与实现

基于PaddleOCR与PyQt5的GUI车票识别系统设计与实现

简介:这是一套基于GUI的OCR车票识别完整毕业设计项目,面向计算机视觉、机器学习方向的本科生及入门开发者,重点解决车票日期、车次、座位号等关键信息的自动提取与可视化操作问题。压缩包共82个文件,整体约4.01MB,包含…

2026/10/13 8:37:52 阅读更多 →
Prim算法详解:最小生成树的原理、实现与工程实践

Prim算法详解:最小生成树的原理、实现与工程实践

1. “Prime算法”到底在讲什么先把这个名字聊透。“Prime算法”在计算机与数据结构的语境下,最常被对应到两条线:一条是图论里求最小生成树的经典贪心算法——Prim算法,另一条则是素数(Prime Number)相关的数论算法&am…

2026/10/13 8:37:52 阅读更多 →
改限制不如改记录:AI内容安全审查记录实战解析

改限制不如改记录:AI内容安全审查记录实战解析

我先不跟你聊那些参数、榜单、跑分,最近这轮更新日志读下来,真正值得关心的变化往往藏在模型之外的“运行记录”里。不少团队把“每日AI观察”的焦点,从“这次又收紧了多少条限制规则”,转向了“审查记录到底长什么样”。我最近正…

2026/10/13 8:37:52 阅读更多 →
终端显示‘impeccable‘?揭秘CLI认证成功标识与误搜根源

终端显示‘impeccable‘?揭秘CLI认证成功标识与误搜根源

1. 项目概述:一个被误读的 CLI 工具命名现象最近在多个技术社区和开发者群聊里,频繁看到“impeccable”这个词被当作某个命令行工具的名称反复提及——它既不是 npm 官方包、也不是主流开源组织发布的 CLI,更没有对应的 GitHub 仓库或文档站。…

2026/10/13 8:37:52 阅读更多 →
UG/NX教程筛选与学习路径:从版本匹配到建模、加工实战

UG/NX教程筛选与学习路径:从版本匹配到建模、加工实战

简介:这是一份整理50套UG(Unigraphics NX)学习教程下载地址的PDF文档,面向使用UG进行产品设计、模具设计、逆向工程及数控加工的工程师和学员,旨在解决教程资源分散、难以系统查找的问题。文档收录了从UG NX4.0到NX7.5…

2026/10/13 8:37:52 阅读更多 →
视频目标跟踪标注工具VATIC非Docker安装全攻略

视频目标跟踪标注工具VATIC非Docker安装全攻略

如果你要做目标检测或者视频目标跟踪,第一步往往不是调模型,而是先把训练数据准备好。标注一个视频里每个目标每一帧的位置,听起来不复杂,真做起来又磨人又容易出错。VATIC 就是干这个的开源视频标注工具:打开浏览器&a…

2026/10/13 8:36:51 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →