首页/数据/数据库速查/MULTI/EXEC 事务(入队与执行)
Redis 运维与场景124 条

MULTI/EXEC 事务(入队与执行)

MULTI 之后命令先入队,EXEC 时按顺序原子执行(执行期间不被其他客户端命令插入);DISCARD 放弃事务。注意:Redis 事务没有回滚,运行时错误不影响已执行部分。

数据库速查数据更新于 2026-10-13

MULTI/EXEC 是什么

MULTI 开启一个事务,之后的命令先入队,EXEC 时按顺序一次性执行,执行期间不会被其它客户端的命令插入,这一段因此是原子的。DISCARD 放弃事务。要特别记住一点:Redis 事务没有回滚,运行时错误只影响出错的那一条命令,其余命令照常生效。

基本信息

命令MULTI / EXEC / DISCARD / WATCH / UNWATCH
原子边界命令序列不被打断,但不保证全部成功
入队错误命令名或参数个数错误,EXEC 整队拒绝并返回 EXECABORT
运行时错误单条失败,其它命令继续执行
乐观锁WATCH 监视键,被改动则 EXEC 返回 nil

典型使用场景

  • 需要多条命令不被穿插执行的组合操作
  • 用 WATCH 实现乐观锁:库存扣减、订单状态流转
  • 批量写入时减少往返次数,同时保持不被打断
  • 需要在一个往返里完成读改写但不想引入 Lua 的场景
  • 交互式调试时用 DISCARD 丢弃误入队的命令

用法与边界

用法与边界
MULTI
SET account:1 900
INCRBY account:2 100
EXEC                    # 返回数组:[OK, 100]

MULTI
INCRBY                  # 参数个数错误
EXEC                    # (error) EXECABORT:整队被拒绝

WATCH stock:sku1        # 乐观锁:被改动则 EXEC 返回 nil
GET stock:sku1
MULTI
DECR stock:sku1
EXEC                    # (nil) 代表需要重试

命令与语义

命令说明注意
MULTI开启事务,后续命令入队入队阶段看不到彼此的执行结果
EXEC按序执行入队命令返回数组,按入队顺序对应
DISCARD清空入队命令连接立刻恢复普通模式
WATCH监视键,变动则放弃事务必须在客户端实现重试逻辑
错误类型入队错误整队拒绝,运行时错误单条失败两种都不是回滚
MULTI 里的命令无法看到彼此的结果,需要「先读后写并根据读到的值决定下一步」时,必须改用 WATCH 或 Lua 脚本。
不要把 Redis 事务当数据库事务用:部分成功是正常状态;业务要么能容忍这种不一致,要么把逻辑放进 Lua 保证整段脚本原子执行。
事务执行是阻塞式的:入队命令越多、单条越重,累积的延迟尖刺越明显。把大量大 key 操作塞进一个 EXEC 是常见的线上毛刺来源。

易错点

  • 以为 EXEC 报错会回滚:Redis 没有回滚,已执行命令的结果会保留
  • 把需要读结果的逻辑放进 MULTI:命令之间无法通信,逻辑必然出错
  • WATCH 之后没有重试机制:EXEC 返回 nil 就静默失败,扣减凭空丢失
  • 用事务替代 Lua 做复杂逻辑:事务缺少条件分支与中间结果判断能力

数据来源与参考

  • Redis 官方文档: Transactions
  • Redis 官方文档: MULTI

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌