Transaction Commands

MULTI-&-EXEC

Redis transactions group commands to execute atomically. No other client can run commands in between. MULTI starts, EXEC runs, DISCARD cancels.

You'll Learn

  • MULTI/EXEC transaction basics
  • WATCH for optimistic locking
  • DISCARD to cancel transactions
  • When transactions vs Lua scripts
Free Download

See Your Data, Not Terminal Text

Redimo visualizes every Redis data type beautifully. Edit inline, undo mistakes, stay safe in production.

1. What Are Redis Transactions?

Redis transactions guarantee that a group of commands executes as a single, uninterrupted sequence. No other client can run commands in between your transaction commands.

Note: Redis transactions are not like SQL transactions. There's no rollback if a command fails mid-transaction. All commands run, and you get individual results.

Basic Transaction

MULTI           # Start transaction
OK
SET user:1001:name "John"
QUEUED          # Command queued, not executed yet
INCR user:1001:visits
QUEUED
EXEC            # Execute all queued commands
1) OK           # Result of SET
2) (integer) 1  # Result of INCR

2. MULTI: Start Transaction

MULTI marks the start of a transaction block. Subsequent commands are queued instead of executed immediately.

Transaction Flow

# Without transaction - commands execute immediately
SET balance:1001 100
SET balance:1002 50
# Another client could read inconsistent state here

# With transaction - all or nothing
MULTI
SET balance:1001 100
SET balance:1002 50
EXEC
# Both changes visible atomically

QUEUED Response

After MULTI, every command returns QUEUED instead of its actual result. The real results come after EXEC.

3. EXEC: Execute Transaction

EXEC runs all queued commands and returns an array of results, one per command.

Reading Results

MULTI
GET user:1001:name
GET user:1001:email
INCR user:1001:visits
EXEC
1) "John"              # GET result
2) "john@example.com"  # GET result
3) (integer) 42        # INCR result

Important: No Rollback

If command #2 fails (e.g., wrong type error), commands #1 and #3 still execute. Redis returns the error in the results array, but doesn't undo anything.

4. DISCARD: Cancel Transaction

Changed your mind? DISCARD flushes all queued commands and exits transaction mode.

Canceling a Transaction

MULTI
SET balance:1001 0
SET balance:1002 0
# Wait, I don't want to do this!
DISCARD
OK
# Nothing happened, balances unchanged

5. WATCH: Optimistic Locking

WATCH monitors keys for changes. If any watched key changes before EXEC, the transaction aborts (EXEC returns nil).

Check-and-Set Pattern

# Transfer $50 from account A to B, only if A has enough
WATCH balance:A
GET balance:A
"100"

# Now start transaction
MULTI
DECRBY balance:A 50
INCRBY balance:B 50
EXEC

# If another client modified balance:A between WATCH and EXEC:
# EXEC returns (nil) - transaction aborted
# You retry the whole operation

Why WATCH?

Without WATCH, two clients could both read balance=100, both think they can deduct 50, and both succeed - resulting in -50 balance. WATCH prevents this race condition.

WATCH in Practice

# Increment if value < 100 (atomic check-and-set)
WATCH counter
val = GET counter
if val < 100:
    MULTI
    INCR counter
    EXEC
else:
    UNWATCH  # Cancel watch without transaction

# If EXEC returns nil, another client changed counter
# Retry from WATCH

6. Common Patterns

Atomic Transfer

# Move item from one set to another atomically
MULTI
SREM user:1001:cart item:5001
SADD user:1001:purchased item:5001
EXEC

Batch Update

# Update multiple fields atomically
MULTI
HSET user:1001 lastLogin 1705312245
HSET user:1001 loginCount 42
LPUSH user:1001:activity "login"
LTRIM user:1001:activity 0 99
EXEC

Conditional Update with WATCH

def reserve_inventory(product_id, quantity):
    while True:
        redis.watch(f"inventory:{product_id}")
        current = int(redis.get(f"inventory:{product_id}") or 0)
        
        if current < quantity:
            redis.unwatch()
            return False
        
        pipe = redis.pipeline(True)
        pipe.decrby(f"inventory:{product_id}", quantity)
        try:
            pipe.execute()
            return True
        except WatchError:
            continue  # Retry

7. Transactions vs Lua Scripts

Both provide atomicity, but they work differently:

Transactions (MULTI/EXEC)

  • • Commands queued, executed in sequence
  • • Can't use results mid-transaction
  • • WATCH for optimistic locking
  • • Client sends all commands, server executes
  • • Good for simple atomic batches

Lua Scripts (EVAL)

  • • Script runs atomically on server
  • • Can use results within script
  • • No need for WATCH (single-threaded)
  • • Server executes logic
  • • Good for complex conditional logic

When to Use What

# Transaction: Simple batch of known commands
MULTI
SET a 1
SET b 2
EXEC

# Lua: Need to read then write based on value
EVAL "
  local val = redis.call('GET', KEYS[1])
  if tonumber(val) > 10 then
    return redis.call('INCR', KEYS[1])
  end
  return val
" 1 counter

8. Error Handling

Understanding how errors work in transactions:

Syntax Errors (Pre-EXEC)

MULTI
SET key value
INCR  # Missing key argument - syntax error
(error) ERR wrong number of arguments
SET other value
EXEC
(error) EXECABORT Transaction discarded because of previous errors
# Nothing executed

Runtime Errors (During EXEC)

SET mykey "hello"  # It's a string

MULTI
SET other "value"
INCR mykey  # Can't INCR a string - runtime error
SET another "value"
EXEC
1) OK           # SET succeeded
2) (error) ERR value is not an integer
3) OK           # SET succeeded
# Partial execution - no rollback!

No Rollback

Redis transactions don't have rollback. If command #2 fails, commands #1 and #3 still run. Design your transactions assuming partial failure is possible (or use Lua scripts for true atomicity with logic).

9. CLI vs Redimo

CLI Challenges

  • • Hard to verify transaction results visually
  • • WATCH races require careful retry logic
  • • No visual diff of before/after state

Redimo Benefits

  • • See key values before and after operations
  • • Inline editing respects data integrity
  • • Visual confirmation of changes
  • • Undo support for accidental changes

Quick Reference

CommandPurpose
MULTIStart transaction block
EXECExecute all queued commands
DISCARDCancel transaction, flush queue
WATCH keyMonitor key for changes
UNWATCHStop watching all keys

Start Using Transactions

Transactions ensure your multi-step operations don't interleave with other clients.
See your data changes clearly with Redimo.

Download Redimo - It's Free

Continue Learning

Free Download

Stop Fighting with CLI.
Visualize Your Data.

Redimo makes every Valkey and Redis command easier. Visual data, inline editing, Safe Mode for production.