4
votes

According to Redis documentation, lua scripts execute atomically. I assumed that this also means that scipts run as transactions, that is, all write commands in a script either succeed or fail. However I noticed, that write command changes do persist, even if script later returned an error.

For example, after running the following from redis cli, the key "k" has value "1", even though the script itself returns an error about access to global variable:

eval "redis.call(\"set\",KEYS[1],1) return x>1" 1 "k"

Is this expected? I'm I missing something? I'm running version 2.8.12 on Windows.

3
Atomically means the script either works or not, not that it's transaction based. - codingbunny
Or, put differently, there is no rollback - Itamar Haber
This is what I was thinking: "The script either works or not", but completely, not partially. "There is no rollback" explains it better. Wish it was in the docs. - Konstantin

3 Answers

1
votes

What they mean by "atomic" is actually closer to isolation than atomicity: Lua scripts are never concurrent with other Lua scripts or commands.

The exact wording is:

Redis guarantees that a script is executed in an atomic way: no other script or Redis command will be executed while a script is being executed. This semantics is very similar to the one of MULTI / EXEC. From the point of view of all the other clients the effects of a script are either still not visible or already completed.

1
votes

As far as I know there is no rollback in Redis. All the changes are done in RAM and are written to disk after a Lua script is finished, but it does not matter if it is finished Ok or with an error, data are written anyway. Try Tarantool instead if you want the real transactions with NoSQL database: http://tarantool.org/doc/book/box/atomic.html

0
votes

You can stop redis server on lua error. Example:

local status, res = pcall(function()
    --your code here
end);

if not status then redis.call("SHUTDOWN", "NOSAVE"); end;
return res;

But actually I don't know if redis can log into AOF-file commands executed before error (I guess it can't because redis can log commands only after script execution is complete I think).

Also you can add usedWriteCommands variable and call SHUTDOWN NOSAVE only if there was commands changed data.