本文章是在复习Redis事务时,看到码哥字节公众号的《腾讯二面:Redis事务支持ACID么》这篇文章时触发的一个整理想法。
本文章结构照搬码哥字节的那篇文章,并加入个人观点
什么是事务的ACID
- 原子性:这个好解释要么全做要么全不做
- 持久性:事务一旦提交,对数据库数据的修改是永久
- 隔离性:两个事务之间是隔离的,互不影响
- 一致性:事务结束后,数据库的完整性没有被破坏
持久性和原子性这两个概念,没什么好说的,我特别想解释一下隔离性和一致性的概念
隔离性理解
隔离这个词在新冠出来后,大家都不陌生,就是把你单独放在一个空间里,事务隔离性就是将每个事务放在各自的空间内运行,保证其互不影响。
对于事务来说,能够互相影响的原因是他们操作共享的数据。对于一个共享数据A来说。事务A的对其的操作是否影响事务B对共享数据操作,若有影响,影响规则又是如何。这就是隔离性中的另一个概念叫隔离级别。
小结: 所谓的隔离性,从实际角度出发的话。就是考虑当操作同一个数据时,事务之间对同一条数据的操作应该是隔离的,但具体的隔离程度也是有响应的级别的。
一致性理解
在我大学的教科书上说:数据库从一个一致性状态->另一个一致性状态。然后又举了个转账的例子。 在码哥字节的文章中
一致性2点内容:
- 事务执行的SQL或者操作不能触犯数据库中的主键、字段类型约束。
- 事务执行需要满足用户自定义完整性,就是转账的例子。
分析:
- 不触犯数据库完整性约束,就是说你事务里的SQL不能是错误的,这点Mysql等数据库会校验
- 用户自定义完整性。即所有事务逻辑,应该是符合业务逻辑的。这个只能是程序员自己控制保证。
原子性是实现一致性的基础:
- 对于用户自定义完整性,系统层面能做的只是保证你的事务要么全做要么全不做。系统会认为你的事务提交过来就是符合逻辑的。
- 写了错的SQL的话,系统层面给你报错保证了数据库完整性,之后再用事务原子性回滚
小结: 数据库能提供的事务的一致性 只可保证事务中对数据的改变不触犯数据库完整性规范(主键、数据类型) 具体事务是否符合业务上的一致性约束,这个只能靠程序员保证
Redis的事务操作
这里我就不演示了,直接说几种事务执行情况
- 排队中出错后,无法提交事务
- 排队未出错,执行中某个出错,成功的就成功了
- watch命令可以在事务中保证事务中共享数据不被操作过
Redis事务原子性
- EXEC执行前报错,全部不执行,满足原子性
- EXEC执行了未执行完毕,Redis宕机了(开启了)。重启后修复,整个事务不被完成。也满足原子性
EXEC执行了且执行完毕,有命令执行错了,其他命令不回滚。不满足原子性
Redis事务隔离性
EXEC执行前,事务的隔离性只能靠Watch命令去保证,操作数据没人修改
- EXEC执行后,事务的隔离性是一定的,Redis会顺序且一步到位的执行完所有事务中的命令。即提交到Redis中的事务都是 串行的。
Redis事务持久性
不支持。Redis事务一致性
上面说了事务一致性就是不符合数据库定义规范的,一律不允许。Redis自然不会让 字符串类型进行+1操作。自然不会让String类型超过512M。这些操作Redis会给你一个大大的报错。所以可以这么说所有的数据库都可以保证数据库层面的一致性(完整性)。
对于业务的一致性,Redis是无法保证的,因为不保证事务的原子性。
总结
- 具备一定的原子性
- 具备隔离性
- 具备非业务层面的一致性
- 不具备持久性(或者说可能具备一定持久性)