MySQL和Redis事务的比较(图文)
本篇文章给大家带来的内容是关于MySQL和Redis事务的比较(图文),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
简言:一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
从标题来看,既然都是事务,那之间有什么区别?来一一解开,先从两个数据库说去。
MySQL 属于 关系型数据库 , Redis 属于 非关系型数据库,两者对事务有着不同的解释。
(相关推荐:MySQL教程,Redis教程)Redis[1] Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:批量操作在发送 EXEC 命令前被放入队列缓存。收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。一个事务从开始到执行会经历以下三个阶段:开始事务。命令入队。执行事务。单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。操作错误看着有点儿绕口,那就实际执行一下 看一下结果。127.0.0.1:6379> multiOK127.0.0.1:6379> set tr_1 233QUEUED127.0.0.1:6379> lpush tr_1 666QUEUED127.0.0.1:6379> set tr_2 888QUEUED127.0.0.1:6379> exec1) OK2) (error) WRONGTYPE Operation against a key holding the wrong kind of value3) OK在上面的事务中,设置了一个 key 为 tr_1 的字符串数据,然后又通过 lpush 来添加元素,这很明显是错误的操作方式,当我们提交事务候出现了一个操作错误,这时候我们来看看 tr_1 的值是什么。127.0.0.1:6379> get tr_1"233"通过 get 命令来的tr_1 内容还是 233 ,并没有变,那再看一下其他的。127.0.0.1:6379> keys *1) "tr_2"2) "tr_1"127.0.0.1:6379> get tr_2"888"127.0.0.1:6379>这里可以看到 tr_2 存在,并打印了值,这时候我们发现,即使出现了操作错误 ,但是错误并没有致使执行停止,错误之后的语句也执行了并成功执行,似乎符合上面提到的 中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。语法错误NO~,这时候还有另外一种情况 语法错误127.0.0.1:6379> multiOK127.0.0.1:6379> set tr_1 233QUEUED127.0.0.1:6379> lpush tr_1 666QUEUED127.0.0.1:6379> set(error) ERR wrong number of arguments for 'set' command127.0.0.1:6379> set 233(error) ERR wrong number of arguments for 'set' command127.0.0.1:6379> set tr_2 888QUEUED127.0.0.1:6379> exec(error) EXECABORT Transaction discarded because of previous errors.127.0.0.1:6379> keys *(empty list or set)当我们执行到 set时没有给任何参数,第二次执行时故意少给了一个参数。可以看到报了 语法错误,最后提交事务,也告诉了我们事务因为错误被丢失了,接着用 keys *检索发现确实如此。文档释义这里可以官方文档中提到的
关于 Redis 暂时看到这里 接下来看到 MySQLMySQL众所周知,MySQL 只有 InnoDB 引擎支持 事务,在启用 MySQL 事务之前需要先停掉自动提交测试表结构 user列类型注释idint(11) 自动增量主键IDmoneyint(11) [0]金钱titlevarchar(500) NULL称呼在这里来模拟一个转账的操作:A给B转100元。
步骤解析 A+100 元,B -100元,即两步虽然很简单,简单走一下流程。
可以看到,没有问题,那么我们从中人为的制造一些问题呢?操作错误列类型注释idint(11) 自动增量moneyint(11) unsigned [0]titlevarchar(500) NULL这里我们把 money 字段变成了无符号,即不能小于 0,并且,调整数据库中的数据如下。`SELECT * FROM `user` LIMIT 50` (0.000 秒)修改idmoneytitle编辑110000A编辑20B接着执行下面的 SQLselect version();SET AUTOCOMMIT=0;begin;select * from user where title in ('A','B') for update;update user setmoney = money + 1000 where title = 'A';update user set money = money - 1000 where title = 'B';select * from user where title in ('A','B');commit;
问题出现了,这里报出了错误,但是可以看到 前面的 SQL 已经是已执行的了,结果已经发生了变化,从这里看,似乎和 Redis 的处理差不多,除了错误之后语句继续执行。但是 值的注意的是, 在我们实际开发中,这种情况程序会直接抛出异常,以供我们在 catch 块中执行 rollback ,以回滚操作确保数据完整,即使是单独使用 MySQL 命令行 我们也可以用存储过程来对异常进行回滚。语法错误刚刚看到 Redis 当遇到 语法错误 时会自动丢弃事务,阻止提交,那 MySQL 呢?
答案:不会,MySQL 在顺序执行时,如果未对异常进行处理,总会将成功执行的的提交,而不会触发自动终止,但是我们可以在程序执行时进行放弃提交。Redis 为什么没有回滚?Redis 的官方文档给出了这样的解释总结数据库自动回滚条件操作错误语法错误MySQL''Redis''但是 MySQL 支持手动回滚,实际开发过程中可以自行手动对已提交的操作进行回滚操作,更加友好。以上就是MySQL和Redis事务的比较(图文)的详细内容,更多请关注小潘博客其它相关文章!