对比两种错误——排队阶段就能查出的语法错误和只有运行时才暴露的类型错误,看Redis事务分别怎么处理,理解为什么它没有传统数据库那种回滚机制。
一种是命令本身就不存在(排队阶段就能查出来),一种是命令合法但用错了类型(只有真的跑起来才知道)。
代码-- 场景A:排队时发一条根本不存在的命令 MULTI SET a 1 BOGUSCMD x SET b 2 EXEC -- 场景B:排队时全部合法,运行时才出错 MULTI SET counter 20 INCR counter LPUSH counter x -- counter是字符串,运行时才知道类型不对 SET another 1 EXEC
EXEC都没有返回结果数组,直接是一个错误。
结果BOGUSCMD x → -ERR unknown command 'BOGUSCMD'... EXEC → -EXECABORT Transaction discarded because of previous errors. GET a → (nil) GET b → (nil)
验证:哪怕SET a 1和SET b 2这两条命令完全没问题,结果是a和b都没有被设置——因为排队阶段就已经发现有一条命令语法不对,Redis把整个事务标记为"损坏",EXEC直接拒绝执行,一条都不跑。
这才是真正"没有回滚"要说明的场景。
结果EXEC → [+OK, :21, -WRONGTYPE Operation against a key holding the wrong kind of value, +OK] GET counter → "21"(生效了) GET another → "1"(也生效了)
每一步都是本文上面对比两种错误跑出来的原始结果。