比较 | mysql | redis |
---|---|---|
开启 | start transaction | multi |
语句 | 普通sql | 普通命令 |
失败 | rollback 回滚 | discard 取消 |
成功 | commit 提交 | exec |
rollback和discard的区别:
如果已经执行了2条语句,第三条出错,rollback后,前面执行的语句都会影响,但是discard的话只是结束本次事务,前面的事务不会影响
注意:
在multi后面的语句,出错可能有2种:
1.语法有问题,这种exec时,会报错,所有语句不能执行
2.语法本身没错,但使用对象有问题,比如zadd 操作list对象,exec之后,会执行正确的语句,并跳过有不适当的语句
multi
redis 127.0.0.1:6379> clear
redis 127.0.0.1:6379> set wang 200
OK
redis 127.0.0.1:6379> set zhao 700
OK
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> decreby zhao 100
(error) ERR unknown command 'decreby'
redis 127.0.0.1:6379> decrby zhao 100
QUEUED
redis 127.0.0.1:6379> incyby wang 100
(error) ERR unknown command 'incyby'
redis 127.0.0.1:6379> incrby wang 100
QUEUED
redis 127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
注意:在exec之前如果遇到不对的语句会导致exec失败 事务也不执行
如果set的值是整形,但是事务中更换了类型的话,会导致当前的事务失败
demo: 购买车票, ticket-1 money-100 票只有一张,在multi之后和exec之前,这张票被人买走了,也就是ticket变成0,这种如何处理,如果还exec的话会出现负数
悲观想法: 给ticket上锁,只有我能操作
乐观想法: 查看ticket的值是否被修改
那么需要进行监控 watch
watch key1 key2 ...keyn 如果有一个改变,事务就取消
取消监视 unwatch
redis 127.0.0.1:6379> set ticket 1
OK
redis 127.0.0.1:6379> watch ticket
OK
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> decr ticket
QUEUED
redis 127.0.0.1:6379> decrby lisi 100
QUEUED
redis 127.0.0.1:6379> exec
(nil)
返回nil说明监控的ticket已经改变了,事务就取消了
另一个窗口进行ticket减少