tidis icon indicating copy to clipboard operation
tidis copied to clipboard

Question: Multi/exec transaction behavior

Open rohitjoshi opened this issue 7 years ago • 8 comments

See the below example where I initiated a transaction with setting two hash values. First one successful and 2nd failed. I thought a transaction would roll back 1st operation because 2nd failed. but that's not the case.

127.0.0.1:5379> multi
OK
127.0.0.1:5379> hsetnx key1 field3 val3
QUEUED
127.0.0.1:5379> hsetnx key1 field1 val2
QUEUED
127.0.0.1:5379> exec
1) (integer) 1
2) (integer) 0
127.0.0.1:5379> hget key1 field3
"val3"
127.0.0.1:5379>

rohitjoshi avatar Jul 06 '18 14:07 rohitjoshi

No. I think hsetnx return 0 is not a failure. multi/exec command behave gurantee all command executed in atomic without any error.

yongman avatar Jul 06 '18 14:07 yongman

hsetnx key1 field1 val2 returned 0 because field1 already exist. So I guess it executes atomically but doesn't roll-back previous operation if subsequent failed.

rohitjoshi avatar Jul 06 '18 14:07 rohitjoshi

hsetnx return 0 is not error, it just return a value 0, we treat it as normal. multi/exec acts the same as redis.

yongman avatar Jul 06 '18 14:07 yongman

yes, it seems redis doesn't honor nx when multi/exec used. As you can see below, the initial value for key1 is val1 and when set to val2 with NX, it should have failed. Without multi/exec, it honors NX

Multi/Exec:

> multi
OK
> set key1 val1 nx
QUEUED
> exec
1) OK
> get key1
"val1"
> multi
OK
> set key1 val2 nx
QUEUED
> exec
1) OK
> get key1
"val2"

Here is without multi/exec:

> set key1 val1 nx
OK
> get key1
"val1"
> set key1 val2 nx
(nil)
> get key1
"val1"

rohitjoshi avatar Jul 06 '18 14:07 rohitjoshi

My use-case is insert two key-val pair atomically and rollback if either one fails.

e.g .

set hash1 token1 NX
set token1 val1 NX

now if I try to insert either hash1 or token1 as a key, it should roll back

e.g. below hash2 toke1 would be successful but token1 val2 should fail which means it should roll back hash2 token1 as well.

set hash2 token1 NX
set token1 val2 NX

May be I can modify tidis code to add a custom function for this behavior.

rohitjoshi avatar Jul 06 '18 14:07 rohitjoshi

@yongman can I consider return 0 is failed operation? It may not be an error but data are not stored.

127.0.0.1:5379> hsetnx k1 f1 v1
(integer) 1
127.0.0.1:5379> hsetnx k1 f1 v1
(integer) 0
127.0.0.1:5379> hsetnx k1 f2 v1
(integer) 1
127.0.0.1:5379> hsetnx k1 f2 v1
(integer) 0

rohitjoshi avatar Jul 06 '18 15:07 rohitjoshi

I think ERR will be rollbacked, and the value returned should be handled in some logical level code other than in a database.

Of cause you can use your own version of tidis for your own use case.

yongman avatar Jul 06 '18 15:07 yongman

For your case, I think tidis could add another group commands begin/commit/rollback, start a new transaction in begin other than start a new transaction in exec, return execute value other than QUEUED, so you can choose to commit or rollback in your logic.

yongman avatar Jul 06 '18 16:07 yongman

Please refer to https://github.com/tidb-incubator/tidis

yongman avatar Sep 20 '22 05:09 yongman