MySQL事务底层原理:undo/redo日志、MVCC与锁机制全解析

1. 事务到底在解决什么问题

很多刚接触数据库的朋友会觉得事务这东西有点虚——平时写个增删改查,加不加事务好像都能跑,业务也没出过什么大乱子。但只要你经历过一次线上对账不平、库存扣成负数、或者转账转了一半系统崩了,你就会明白事务不是锦上添花,而是数据库能用在生产环境的底线。

事务要解决的核心问题就一句话:一组操作要么全做,要么全不做,中间不能被打断,也不能只做一半。听起来简单,但要在高并发、随时可能宕机、磁盘还可能写坏的现实环境里把这句话兑现,背后是一整套相当精巧的机制。

我拿一个最经典的场景来说。用户 A 给用户 B 转 100 块,数据库层面至少是两条语句:A 的账户减 100,B 的账户加 100。这两条语句之间如果出了任何岔子——程序抛异常了、数据库进程被杀了、服务器断电了——只要有一条没执行,钱就凭空消失或者凭空多出来。事务就是把这俩操作捆成一个不可分割的整体,数据库向你保证:这个整体要么完整生效,要么像从来没发生过一样。

这里有个容易被忽略的点:事务保证的是数据库层面的原子性,它管不了你业务代码里的逻辑。比如你在事务里先查余额再扣款,查和扣之间如果有别的并发请求插进来,照样可能出问题,那是隔离级别要管的事。所以理解事务,得把 ACID 四个特性拆开看,它们各自解决不同维度的问题,又互相配合。

ACID 这四个字母大家都会背,但真正理解它们之间的关系,是后面所有讨论的基础。原子性(Atomicity)管的是"全或全无",一致性(Consistency)其实是目的而不是手段——它是说事务执行前后数据库的完整性约束不能被破坏,比如唯一索引不能冲突、外键不能悬空。隔离性(Isolation)管的是并发事务之间互不干扰,持久性(Durability)管的是提交之后数据不能丢。这四个里面,原子性和持久性靠日志实现,隔离性靠锁和版本控制实现,一致性则是前三个共同作用的结果。

我个人的经验是,面试或者技术讨论里,能把 ACID 讲清楚的人不少,但能说清楚"原子性具体靠什么日志、持久性又靠什么日志、两者为什么不能合并成一种"的人就不多了。这篇文章就打算把这些底层的东西一层层剥开,从日志讲到锁,从隔离级别讲到 MVCC,尽量让你看完之后,脑子里能有一张完整的图,而不是零散的知识点。

2. 原子性和持久性:两种日志撑起的两根柱子

2.1 undo log 与原子性的实现逻辑

原子性说白了就是"反悔"的能力。事务执行到一半发现不行了,得能把已经做的改动撤回来。数据库实现这个"反悔"靠的是undo log,也就是回滚日志。

undo log 记录的是逻辑上的反向操作。注意,它不是记录数据页的物理变化,而是记录"如果要撤销这条操作,应该怎么做"。比如你执行了一条UPDATE account SET balance = balance - 100 WHERE id = 1,undo log 里记的不是"把第 X 页第 Y 个字节改回原值",而是记了一条"把 id=1 的 balance 加回 100"这样的反向语句。这个区别很关键,后面讲 MVCC 的时候还会用到。

为什么用逻辑日志而不是物理日志?因为逻辑日志更省空间,而且能支持一些物理日志做不到的事情,比如回滚的时候可以基于当前数据状态重新计算。物理日志你得精确记录每个字节的变化,数据页稍微挪个位置就全乱了。

undo log 还有一个很多人不知道的用途:它不只服务于回滚,还服务于 MVCC 的快照读。当你用可重复读隔离级别的时候,一个事务读到的可能是历史版本的数据,这些历史版本就是从 undo log 里翻出来的。所以 undo log 在事务提交之后不能立刻删,得等没有事务再需要这些历史版本了才能清理。这也是为什么长事务特别危险——一个跑了半小时没提交的事务,会让 undo log 一直堆积,磁盘空间蹭蹭往上涨,还可能拖慢整个系统的读性能。

提示:生产环境一定要监控长事务。我见过一个案例,某个定时任务忘了提交事务,跑了几个小时,undo 表空间从几个 G 涨到几十个 G,最后把磁盘写满了,整个实例挂掉。排查的时候用information_schema.innodb_trx看trx_started就能找到元凶。

2.2 redo log 与持久性的实现逻辑

持久性解决的是另一个方向的问题:事务提交了,数据就不能丢。但这里有个矛盾——如果每次提交都把数据页刷到磁盘,性能会惨不忍睹,因为随机写磁盘太慢了。数据库的解法是WAL(Write-Ahead Logging),先写日志再写数据。

redo log 记录的是物理层面的变化,比如"在某个表空间的某个数据页的某个偏移量处,写入了什么值"。它跟 undo log 的逻辑记录正好相反。为什么 redo 要用物理日志?因为崩溃恢复的时候,数据库需要快速重放,物理日志重放起来最直接、最快,不需要再做任何计算。

这里有个关键概念叫LSN(Log Sequence Number),可以理解成日志的全局递增编号。每个数据页上都有一个 LSN,记录这个页最后一次被修改时对应的日志位置。崩溃恢复的时候,数据库从检查点(checkpoint)开始往后重放 redo log,如果某个数据页的 LSN 已经大于等于要重放的日志 LSN,说明这个页已经刷过了,跳过就行。这个机制保证了恢复过程既完整又不会重复做无用功。

redo log 是循环写的,固定大小,比如默认两个文件各 48M,总共 96M(MySQL 8.0 之后可以动态调整)。写满了就得推进检查点,把脏页刷盘,腾出空间继续写。这就引出一个经典问题:如果 redo log 写满了,脏页又刷不动,数据库会卡住。所以 redo log 的大小设置很讲究,太小了会导致频繁刷脏页,太大了崩溃恢复时间会变长。

对比项undo logredo log
记录内容逻辑反向操作物理页变化
主要作用回滚、MVCC 快照读崩溃恢复、持久性
写入时机事务执行过程中事务执行过程中
生命周期提交后可能还需保留循环写,检查点后可覆盖
空间管理独立 undo 表空间固定大小循环使用

2.3 两阶段提交:redo 和 binlog 怎么保持一致

如果你只用过 InnoDB,可能不知道还有个binlog(归档日志)。redo log 是 InnoDB 引擎层的,binlog 是 MySQL 服务层的。redo log 循环写会被覆盖,binlog 是追加写、永久保留的,主要用来做主从复制和数据恢复。

问题来了:一个事务提交的时候,既要写 redo log,又要写 binlog,这俩怎么保证一致?如果 redo 写完了、binlog 没写完,主从就会不一致;如果 binlog 写完了、redo 没写完,崩溃恢复后主库数据又和从库对不上。

MySQL 的解法是两阶段提交。提交过程分成 prepare 和 commit 两个阶段:先写 redo log 并标记为 prepare 状态,然后写 binlog,最后把 redo log 标记为 commit 状态。崩溃恢复的时候,如果发现 redo log 是 prepare 状态,就去检查对应的 binlog 是否完整——完整就提交,不完整就回滚。这样无论在哪一步崩溃,主库和从库的数据都能保持一致。

这个机制理解起来不难,但实际运维里有个坑:sync_binlog和innodb_flush_log_at_trx_commit这两个参数的组合。前者控制 binlog 刷盘频率,后者控制 redo log 刷盘频率。两个都设成 1 是最安全的,每次提交都刷盘,但性能最差。很多互联网公司会设成sync_binlog=1、innodb_flush_log_at_trx_commit=2,牺牲一点持久性换性能——redo log 每秒刷一次,宕机可能丢一秒的数据,但 binlog 是实时的,主从不会丢。这个取舍要看业务能不能接受丢那一秒。

3. 隔离性:并发事务之间的博弈

3.1 四种隔离级别与三种并发问题

隔离性要解决的是并发事务互相干扰的问题。SQL 标准定义了四种隔离级别,对应三种典型的并发问题。这三个问题我用一个转账场景串起来讲,比干巴巴的定义好理解。

脏读:事务 A 改了数据但还没提交,事务 B 就读到了这个未提交的值。如果 A 后来回滚了,B 读到的就是脏数据。比如 A 把余额从 100 改成 200 还没提交,B 读到 200 就以为钱多了,结果 A 回滚,B 白高兴一场。

不可重复读:事务 A 第一次读余额是 100,事务 B 把余额改成 200 并提交,事务 A 再读一次变成 200。同一个事务里两次读结果不一样,这就是不可重复读。它的问题在于事务内的逻辑可能因此错乱。

幻读:事务 A 查"余额大于 100 的账户有几条",得到 3 条;事务 B 插入了一条余额 150 的记录并提交;事务 A 再查一次变成 4 条。多出来的那条就像幻觉一样,所以叫幻读。幻读和不可重复读的区别在于:不可重复读是同一行数据变了,幻读是结果集的行数变了。

隔离级别脏读不可重复读幻读
读未提交可能可能可能
读已提交不可能可能可能
可重复读不可能不可能InnoDB 下基本不可能
串行化不可能不可能不可能

MySQL 的 InnoDB 默认隔离级别是可重复读,而且通过 MVCC 加间隙锁,在绝大多数场景下把幻读也解决了。这一点和 SQL 标准不太一样,标准里可重复读是允许幻读的。所以经常有人问"MySQL 可重复读到底能不能防幻读",答案是:快照读靠 MVCC 防住了,当前读靠间隙锁防住了,但如果你在事务里混用快照读和当前读,还是可能踩坑,这个后面细说。

3.2 MVCC:不加锁也能读一致的秘密

MVCC(多版本并发控制)是 InnoDB 实现隔离性的核心武器。它的核心思想是:读操作不加锁,而是去读一个历史快照。这样读和写就不会互相阻塞,并发性能大幅提升。

每个 InnoDB 的行记录里,除了用户数据,还藏着几个隐藏字段:DB_TRX_ID记录最后修改这行的事务 ID,DB_ROLL_PTR指向 undo log 里的历史版本,DB_ROW_ID是行 ID(没有主键时用)。当你读一行数据时,InnoDB 会拿当前事务的Read View去判断这个版本能不能看见。

Read View 里有几个关键信息:当前活跃的事务 ID 列表、最小活跃事务 ID、下一个要分配的事务 ID。判断规则大致是:如果行的DB_TRX_ID小于最小活跃事务 ID,说明修改它的事务早就提交了,可见;如果大于等于下一个事务 ID,说明是未来才开始的,不可见;如果在活跃列表里,说明还没提交,不可见。不可见的话就顺着DB_ROLL_PTR去 undo log 里找上一个版本,直到找到一个可见的版本。

这里有个非常重要的区别:读已提交和可重复读生成 Read View 的时机不同。读已提交是每次 SELECT 都生成一个新的 Read View,所以能看到别人刚提交的数据;可重复读是事务开始时生成一次,整个事务都用这一个,所以两次读结果一样。这就是为什么可重复读能防不可重复读——不是数据没变,而是你看到的快照没变。

注意:MVCC 只对快照读(普通 SELECT)生效。如果你用了SELECT ... FOR UPDATE、SELECT ... LOCK IN SHARE MODE、或者 UPDATE/DELETE,这些都是当前读,读的是最新数据,并且要加锁。很多幻读的坑就出在事务里混用了快照读和当前读。

3.3 锁机制:当前读背后的秩序维护者

快照读靠 MVCC,当前读就得靠锁了。InnoDB 的锁按粒度分,有表锁和行锁;按模式分,有共享锁(S 锁)和排他锁(X 锁);行锁里还有记录锁、间隙锁、临键锁三种形态。

记录锁锁的是一条具体的索引记录。间隙锁锁的是两条记录之间的空隙,防止别人往里面插数据。临键锁是记录锁加间隙锁的组合,锁住一条记录和它前面的间隙。InnoDB 在可重复读级别下,默认用的就是临键锁,这也是它能防幻读的关键——你没法在我锁住的范围内插入新记录。

间隙锁有个反直觉的地方:它锁的是间隙,不同事务可以对同一个间隙加间隙锁,它们不冲突。因为间隙锁的目的是防止插入,而不是互斥。两个事务都给 (5, 10) 这个间隙加了锁,它们可以共存,但谁都别想往里插 id=7 的记录。这个特性导致间隙锁的冲突判断比记录锁复杂得多。

还有一个经典问题:没有索引的更新会锁全表。因为 InnoDB 的行锁是加在索引上的,如果你 UPDATE 的 WHERE 条件没有走索引,它就得扫描所有记录,把每一条都锁上,效果等同于锁表。我见过不少线上事故就是这么来的——一张几百万行的表,一个没走索引的 UPDATE,直接把整个表锁死,所有请求排队。所以生产环境里,UPDATE 和 DELETE 的 WHERE 条件一定要走索引,这是铁律。

4. 实操中怎么观察和验证事务行为

4.1 用两个会话亲手复现隔离级别差异

光看理论容易忘,我建议你开两个 MySQL 客户端会话,亲手把四种隔离级别跑一遍。下面这套操作我带着新人做过很多次,效果比看十遍文档都好。

先建一张测试表:

CREATE TABLE t_account ( id INT PRIMARY KEY, balance INT NOT NULL ) ENGINE=InnoDB; INSERT INTO t_account VALUES (1, 100);

然后开两个会话,分别叫 A 和 B。把隔离级别设成读未提交:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

A 会话开启事务并更新但不提交:

-- 会话 A BEGIN; UPDATE t_account SET balance = 200 WHERE id = 1;

B 会话去读:

-- 会话 B SELECT balance FROM t_account WHERE id = 1;

你会看到 B 读到了 200,这就是脏读。然后把隔离级别改成读已提交,重复上面的操作,B 就读到 100 了,脏读被挡住。接着在 A 提交后,B 再读一次,读已提交下会变成 200,可重复读下还是 100。这样一步步对比,四种级别的差异就非常直观了。

4.2 查看当前事务和锁等待的实用命令

线上排查事务问题,有几个命令是必须掌握的。第一个是看当前正在跑的事务:

SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx ORDER BY trx_started;

trx_started越早说明事务跑得越久,trx_query能看到它当前在干什么。如果发现一个事务跑了几分钟还没结束,基本可以判定是长事务,得赶紧找对应线程处理。

第二个是看锁等待:

SELECT * FROM performance_schema.data_lock_waits;

这个表能告诉你谁在等谁的锁。MySQL 8.0 之前用的是information_schema.innodb_lock_waits,8.0 之后换成了 performance_schema 里的表。配合performance_schema.data_locks能看到具体的锁信息,包括锁的类型、锁在哪个索引上、锁的模式是什么。

第三个是看引擎状态:

SHOW ENGINE INNODB STATUS;

这个输出信息量巨大,里面有最近一次死锁的详细信息,包括两个事务各自持有什么锁、在等什么锁、执行的 SQL 是什么。死锁排查基本就靠它。

提示:SHOW ENGINE INNODB STATUS的输出里,LATEST DETECTED DEADLOCK那一段是排查死锁的黄金信息。但要注意它只保留最近一次死锁,如果死锁频繁发生,最好开启死锁日志记录到错误日志里,方便事后分析。

4.3 死锁的成因与规避思路

死锁是并发事务互相等对方释放锁造成的。最典型的场景是两个事务以相反的顺序更新同一批记录。比如事务 A 先更新 id=1 再更新 id=2,事务 B 先更新 id=2 再更新 id=1,两边各持有一把锁又都在等对方的锁,就死锁了。

InnoDB 有死锁检测机制,发现死锁后会主动回滚其中一个事务(通常是修改行数少的那个),让另一个继续。所以死锁本身不可怕,可怕的是频繁死锁导致大量事务被回滚,业务成功率下降。

规避死锁的思路有这么几条。第一,固定加锁顺序。所有事务都按同一个顺序访问资源,比如都按 id 升序更新,就不会出现交叉等待。第二,缩短事务长度。事务越长,持有锁的时间越久,冲突概率越大。第三,减少加锁范围。能用唯一索引精确定位的,就别用范围条件。第四,必要时降级隔离级别。读已提交没有间隙锁,死锁概率会低一些,但代价是可能幻读。

死锁成因典型场景规避手段
加锁顺序相反两事务交叉更新多行统一按主键升序操作
事务过长事务里夹杂远程调用拆分事务,先算后写
范围锁冲突范围更新加间隙锁精确条件,走唯一索引
索引缺失无索引更新锁全表补索引,避免全表扫描

5. 几个容易踩坑的实战细节

5.1 长事务为什么是万恶之源

长事务的危害我在前面提过,这里展开说说。一个长事务不提交,会带来三个连锁反应。undo log 无法清理,历史版本一直堆积,磁盘空间持续增长,同时快照读要遍历的版本链越来越长,读性能下降。锁持有时间过长,其他事务等锁等到天荒地老,连接池被占满,整个服务雪崩。主从延迟加剧,大事务在从库重放时间长,主从数据不一致的窗口拉大。

我处理过一个线上问题,某个报表查询事务忘了提交,跑了十几分钟,期间所有对相关表的更新全部阻塞,前端页面转圈转到用户投诉。后来加了事务超时配置innodb_lock_wait_timeout和max_execution_time才缓解。但根本解法还是代码层面保证事务尽快提交,别在事务里做网络请求、文件读写这些耗时操作。

5.2 可重复读下幻读的真实案例

很多人以为可重复读就万事大吉了,其实有个经典陷阱。假设你要做"先查有没有,没有就插入"的逻辑:

-- 事务 A BEGIN; SELECT * FROM t_user WHERE username = 'abc'; -- 快照读,没查到 -- 此时事务 B 插入了 username='abc' 并提交 INSERT INTO t_user (username) VALUES ('abc'); -- 当前读,插入成功 COMMIT;

如果 username 没有唯一索引,事务 A 的 INSERT 会成功,结果就是两条 abc 记录。因为 SELECT 是快照读,看不到 B 的插入;INSERT 是当前读,但插入本身不检查唯一性(没唯一索引的话)。这就是快照读和当前读混用导致的幻读。

解法有两个:要么给 username 加唯一索引,让 INSERT 直接报错;要么 SELECT 的时候用FOR UPDATE走当前读,提前把间隙锁住。生产环境里,这种"查了再插"的逻辑一定要配唯一索引兜底,别指望隔离级别能帮你兜住所有情况。

5.3 事务提交了但数据丢了是怎么回事

偶尔会有人问:明明事务提交成功了,为什么重启后数据没了?这种情况大概率是持久性配置的问题。前面说过innodb_flush_log_at_trx_commit这个参数,如果设成 0 或 2,redo log 不是每次提交都刷盘,宕机就可能丢数据。

设成 0 是每秒刷一次,设成 1 是每次提交都刷,设成 2 是每次提交写到操作系统缓存但不刷盘。设成 2 的时候,如果只是 MySQL 进程崩了,数据还在操作系统缓存里,不会丢;但如果操作系统也崩了或者断电,缓存里的数据就没了。所以对数据安全性要求高的业务,这个参数必须是 1。

还有一个隐蔽的坑:从库的持久性配置。主库设成 1 保证了数据不丢,但如果从库设成 0,主库宕机切到从库时,从库可能还没把最新的 redo log 刷盘,切换后就丢了。所以主从的持久性配置要一致,别只顾主库。

6. 把事务知识串成一张图

事务这块知识,零散看的时候觉得东西很多,但串起来其实就三条线。第一条是日志线:undo log 管回滚和 MVCC,redo log 管持久性,binlog 管复制,两阶段提交保证 redo 和 binlog 一致。第二条是隔离线:MVCC 管快照读,锁管当前读,Read View 的生成时机决定隔离级别,间隙锁决定能不能防幻读。第三条是实践线:长事务要监控,死锁要预防,持久性参数要配对,查了再插要加唯一索引。

我个人的体会是,事务这东西光看文档学不透,必须动手跑。开两个会话把隔离级别跑一遍,故意制造一次死锁看看日志,用SHOW ENGINE INNODB STATUS观察锁等待,这些操作做过一次,比看十篇文章都管用。而且事务的问题往往不是孤立出现的,它和索引、锁、日志、复制都有关联,理解的时候要有全局视角,别把它当成一个孤立的知识点。

最后分享一个我常用的排查套路:遇到事务相关的性能问题,先看innodb_trx找长事务,再看data_lock_waits找锁等待,最后看INNODB STATUS找死锁。这三板斧下去,大部分问题都能定位到。至于怎么解决,那就回到前面说的——缩短事务、统一加锁顺序、补索引、调参数,对症下药就行。

相关新闻

Java全栈面试高频考点与实战经验:从基础到微服务完整梳理

Java全栈面试高频考点与实战经验:从基础到微服务完整梳理

Java全栈开发面试,我聊过的大概有二十多场,从刚毕业那会儿被问“重写和重载有什么区别”就开始冒汗,到后来能跟面试官在微服务架构上你来我往扯四十分钟。这中间最深的体会是:面试不是知识点的随机抽查,而是你技术体系…

2026/10/21 0:51:37 阅读更多 →
光谷激光1h工厂负荷数据:从清洗到储能容量配置的完整实战

光谷激光1h工厂负荷数据:从清洗到储能容量配置的完整实战

简介:这份资源聚焦光谷激光工厂的真实用电负荷,以1小时为采样粒度,面向从事能源管理、负荷预测与工业数据分析的工程师及学生。数据覆盖电压、电流、需量、电量、功率、温度及冻结表码等维度,可用于负荷趋势建模、能效对比、节能策…

2026/10/21 0:51:37 阅读更多 →
智能体上线前验收:从功能验证到可信度评估

智能体上线前验收:从功能验证到可信度评估

1. 项目概述:验收不是走流程,是给智能体做“上岗体检”“智能体上线前,怎么验收才不是‘看起来能用’”——这句话一出来,我就想起上个月在某实验室帮一个团队做交付复盘时的场景。他们花三个月搭了个任务调度型智能体&#xff0c…

2026/10/21 0:50:37 阅读更多 →

最新新闻

深入parakeet-redux架构:从24层TDT编码器到解码器的设计细节

深入parakeet-redux架构:从24层TDT编码器到解码器的设计细节

人工智能语音模型量化模型压缩 【免费下载链接】parakeet-redux 项目地址: https://ai.gitcode.com/hf_mirrors/moondream/parakeet-redux 点击查看 免费下载 🦜 parakeet-redux 是一个 1.58 bit 三值量化的自动语音识别(ASR)模型…

2026/10/21 1:25:00 阅读更多 →
戴森球计划工厂蓝图实战指南:3 条阶段线打通你的星际产线

戴森球计划工厂蓝图实战指南:3 条阶段线打通你的星际产线

戴森球计划工厂蓝图实战指南:3 条阶段线打通你的星际产线 【免费下载链接】FactoryBluePrints 游戏戴森球计划的**工厂**蓝图仓库 项目地址: https://gitcode.com/GitHub_Trending/fa/FactoryBluePrints FactoryBluePrints 是一个戴森球计划玩家可直接导入游…

2026/10/21 1:25:00 阅读更多 →
无名杀 noname 教程:浏览器直接玩,2000+ 武将的免费网页版三国杀

无名杀 noname 教程:浏览器直接玩,2000+ 武将的免费网页版三国杀

无名杀 noname 教程:浏览器直接玩,2000 武将的免费网页版三国杀 【免费下载链接】noname 项目地址: https://gitcode.com/GitHub_Trending/no/noname 无名杀(noname)是一个开源的网页版三国杀,把整个游戏放进浏…

2026/10/21 1:25:00 阅读更多 →
霞鹜文楷:免费商用的开源中文字体,排版与等宽一份搞定(新手向)

霞鹜文楷:免费商用的开源中文字体,排版与等宽一份搞定(新手向)

霞鹜文楷:免费商用的开源中文字体,排版与等宽一份搞定(新手向) 【免费下载链接】LxgwWenKai An open-source Chinese font derived from Fontworks Klee One. 一款开源中文字体,基于 FONTWORKS 出品字体 Klee One 衍生…

2026/10/21 1:25:00 阅读更多 →
DLSS Swapper 新手指南:免费 3 步完成游戏 DLSS 版本升级与回退

DLSS Swapper 新手指南:免费 3 步完成游戏 DLSS 版本升级与回退

DLSS Swapper 新手指南:免费 3 步完成游戏 DLSS 版本升级与回退 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper DLSS Swapper 是一款免费开源的 Windows 桌面工具,负责下载、管理并替换游戏里自…

2026/10/21 1:25:00 阅读更多 →
Apktool 安装与配置完整指南:APK 逆向工具从源码快速上手

Apktool 安装与配置完整指南:APK 逆向工具从源码快速上手

Apktool 安装与配置完整指南:APK 逆向工具从源码快速上手 【免费下载链接】Apktool A tool for reverse engineering Android apk files 项目地址: https://gitcode.com/GitHub_Trending/ap/Apktool 拿到一个闭源 APK,想改个字符串、挪个布局、动…

2026/10/21 1:23:59 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →