Transaction

事务,很基础的概念,但有很多细节是大家忽略的或者平时很少注意到的。这里总结一下:
实验工程 (这工程的实验代码尚不完整,再更新看心情了😛)

ACID

先说ACID,工程里说自查度娘,还是算了吧,我还是解释一下吧,度娘不靠谱

  • 原子性(Atomicity) 操作原子性,同一个事务中要么所有操作都执行,要么都不执行。好理解
  • 一致性(Consistency) 一致性(经常和原子性混),原意是数据库从一个状态转换为另一个状态(完全不知所云哈?)。其实说的是写入数据必须复合数据库的相关约束,包括限制、级联、触发等(还不明白?)举个例:A外键关联B,一个事务试图插入B数据,但不插入与其关联的A记录,当然这是非法事务,它违反的就是一致性原则。
  • 隔离性(Isolation) 隔离型决定了,是否可以避免脏读、不可重复读、幻读,这个下面来深入说明,这个也很少有人关注过
  • 持久性(Durability) 持久性,这个强调的是commit后不要存在内存中,commit要求写入硬盘,当然也就不丢了

参考

单说隔离性

隔离级别 解决脏读取、重复读、幻读

  • DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是:READ_COMMITTED。
  • READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
  • READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
  • REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
  • SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
脏读 不可重复读 幻读
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE
  • 脏读(Dirty Read):A事务进行中读到了B事务尚未commit的数据
  • 不可重复读(Fuzzy/Non-Repeatable Read) : A事务进行中第一次读取,B事务提交更新数据,A事务再次读取,数据不一致
  • 幻读(Phantom Read):A事务读取了M跳数据,B事务插入数据N条提交,A事务再次读取发现为M+N条

个人推断,事务隔离级别应该和数据库锁相关,不可重复读需要行级锁,而幻读需要表级锁。这个需要进步一验证

注意:这里说的都是数据库自身问题,如果在开发过程中,我们使用的ORM框架自身还有数据对象状态问题,例如:临时态、持久态、游离态。这些不正常处理可能会造成事务内操作出错。

解决程序或数据库中类似的数据冲突问题,我们需要考虑程序锁或数据库错(无论怎样性能都将受到影响,需要合理设计),或者CAS操作(性能好,但是应用场景受限),这又将是个大话题,稍后再阐述吧。

进阶阅读

这个文章比我说的详细多了,pingcap团队的。 推荐阅读。

后续

近期公司需要将一套老系统进行微服务拆分并重构,花了一天的时间深入梳理一下ACID BASE 和 CAP,这些概念之前虽然都看过,但是现在再看又有更为深刻的理解了,温故而知新啊
这个部分内容专业、庞大又复杂,还是先推荐几篇别人的文章吧,如果可能,稍后再总结自己的想法
CAP、ACID、BASE理论及NWR实践策略详解
分布式服务化系统一致性的“最佳实干”