MySQL:
- BEGIN:显式地开启一个事务;
- COMMIT:提交事务,将对数据库进行的所有修改变成为永久性的;
- ROLLBACK:结束用户的事务,并撤销正在进行的所有未提交的修改;
Redis:
- MULTI:标记事务的开始;
- EXEC:执行事务的commands队列;
- DISCARD:结束事务,并清除commands队列;
Redis之坑:理解Redis事务 中我们通过类比MySQL的BEGAIN ,COMMIT ,ROLLBACK 来理解Redis的事务命令。但是显然,它们有着本质区别。
默认状态
MySQL:
- MySQL会默认开启一个事务,且缺省设置是自动提交,即,每成功执行一个SQL,一个事务就会马上 COMMIT。所以不能Rollback。
Redis:
- Redis默认不会开启事务,即command会立即执行,而不会排队。并不支持Rollback(详情可见:Redis之坑:理解Redis事务 )
使用方式
MySQL:包含两种
- 用 BEGIN, ROLLBACK, COMMIT,显式开启并控制一个新的 Transaction。
- 执行命令SET AUTOCOMMIT=0,用来禁止当前会话自动commit,控制默认开启的事务 。
Redis:
- 用 MULTI, EXEC, DISCARD,显式开启并控制一个Transaction(注意:这里没有强调“新的”,因为默认是不会开启事务的)。
实现原理
很容易理解,Redis与MySQL中事务的区别其根本原因就是实现不同方式造成的。
MySQL:
- MySQL实现事务,是基于UNDO/REDO日志 。
- UNDO日志 记录修改前 状态,ROLLBACK 基于UNDO日志实现;
- REDO日志 记录修改后 的状态 ,COMMIT 基于REDO日志实现;
- 在MySQL中无论是否开启事务,SQL都会被立即执行并返回执行结果。只是**事务开启 **后执行后的状态 只是记录在REDO日志 ,执行COMMIT 之后,数据才会被写入磁盘 。
int insertSelective = serviceOrderMapper.insertSelective(s);复制代码
所以,上述代码,insertSelective 将会被立即赋值(无论是否开启事务,只是结果或未被写入磁盘 ):
insertSelective = 受影响的行数;复制代码
Redis:
- Redis实现事务,是基于COMMANDS队列 。
- 如果没有开启事务,command 将会被立即执行并返回执行结果,并且直接写入磁盘;
- 如果事务开启,command 不会被立即执行,而是排入队列并返回排队状态 (具体依赖于客户端(例如:spring-data-redis)自身实现)。调用EXCE 才会执行COMMANDS队列 。
boolean a = redisTemplate.opsForZSet().add("generalService