Redis 事务支持回滚吗?
文章目录
Redis 事务支持回滚吗?
首选,Redis 事务不支持回滚
MySQL 在执行事务时,会提供回滚机制,当事务执行发生错误时,事务中的所有操作都会撤销,已经修改的数据也会被恢复到事务执行前的状态。Redis 中并没有提供回滚机制
官方解释
我们来查看 Redis 的官方文档来再来找一找答案:
文档地址:https://redis.io/topics/transactions
官方文档的解释如下:
大概的意思是,Redis 不支持事务回滚,因为支持回滚会对 Redis 的简单性和性能产生重大影响。因为事务回滚本身是一种复杂的功能,这和 Redis 追求的简单高效的设计主旨不符合。
虽然,Redis不支持事务回滚,但是 Redis 提供了 DISCARD 命令,不过这个命令只能用来主动放弃事务执行,把暂存的命令队列清空,起不到回滚的效果。
DISCARD 命令取消事务
下面是 DISCARD 命令用法:
#读取 num 的值666 127.0.0.1:6379> GET num "666" #开启事务 127.0.0.1:6379> MULTI OK #发送事务的第一个操作,对num 减1 127.0.0.1:6379> DECR num QUEUED #执行DISCARD命令,主动放弃事务 127.0.0.1:6379> DISCARD OK #再次读取值没有被修改 127.0.0.1:6379> GET num "666"
事务执行过程中,如果命令入队时没报错,而事务提交后,实际执行时报错了,正确的命令依然可以正常执行,所以这可以看出 Redis 并不一定保证原子性(原子性:事务中的命令要不全部成功,要不全部失败)。
比如下面这个测试案例:
#获取name原本的值 127.0.0.1:6379> GET name "yang" #开启事务 127.0.0.1:6379> MULTI OK #设置新值 127.0.0.1:6379(TX)> SET name yangyongli QUEUED #注意,这条命令是错误的 # expire 过期时间正确来说是数字,并不是‘10s’字符串,但是还是入队成功了 127.0.0.1:6379(TX)> EXPIRE name 10s QUEUED #提交事务,执行报错 #可以看到 set 执行成功,而 expire 执行错误。 127.0.0.1:6379(TX)> EXEC 1) OK 2) (error) ERR value is not an integer or out of range #可以看到,name 还是被设置为新值了 127.0.0.1:6379> GET name "yangyongli"