<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>写给老婆的系列 on Code Now</title>
    <link>https://blog.0xnullpath.cc/tags/%E5%86%99%E7%BB%99%E8%80%81%E5%A9%86%E7%9A%84%E7%B3%BB%E5%88%97/</link>
    <description>Recent content in 写给老婆的系列 on Code Now</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sun, 09 Mar 2025 16:16:44 +0000</lastBuildDate>
    <atom:link href="https://blog.0xnullpath.cc/tags/%E5%86%99%E7%BB%99%E8%80%81%E5%A9%86%E7%9A%84%E7%B3%BB%E5%88%97/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>讲给老婆的数据系统设计-ACID事务</title>
      <link>https://blog.0xnullpath.cc/posts/note-snippet-3-%E8%AE%B2%E7%BB%99%E8%80%81%E5%A9%86%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1-acid%E4%BA%8B%E5%8A%A1/</link>
      <pubDate>Sun, 09 Mar 2025 16:16:44 +0000</pubDate>
      <guid>https://blog.0xnullpath.cc/posts/note-snippet-3-%E8%AE%B2%E7%BB%99%E8%80%81%E5%A9%86%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1-acid%E4%BA%8B%E5%8A%A1/</guid>
      <description>&lt;h2 id=&#34;为什么会有事务&#34;&gt;为什么会有事务&lt;/h2&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;  &lt;p&gt;“在数据系统的残酷现实中，很多事情都可能出错：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;数据库软件、硬件可能在任意时刻发生故障（包括写操作进行到一半时）。&lt;/li&gt;&#xA;&lt;li&gt;应用程序可能在任意时刻崩溃（包括一系列操作的中间）。&lt;/li&gt;&#xA;&lt;li&gt;网络中断可能会意外切断数据库与应用的连接，或数据库之间的连接。&lt;/li&gt;&#xA;&lt;li&gt;多个客户端可能会同时写入数据库，覆盖彼此的更改。&lt;/li&gt;&#xA;&lt;li&gt;客户端可能读取到无意义的数据，因为数据只更新了一部分。&lt;/li&gt;&#xA;&lt;li&gt;客户之间的竞争条件可能导致令人惊讶的错误。”&#xA;&amp;mdash; 《数据密集型应用系统设计》&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;在并发编程中，我们常常会关注多线程/进程/协程对同一块内存进行修改时候的正确性，这个时候我们因为了原子变量和锁来实现临界区去解决这个问题。在实际生活和开发中更多是操作主体总是会通过一系列的操作来完成一件事，这个时候我们也希望能提供类似于原子变量的工作来讲我们一系列操作进行保护，从而防止出现多个主体操作的非预期情况。&lt;/p&gt;&#xA;&lt;p&gt;想象一下，你在用手机银行给朋友转账。这个过程其实有两步：从你的账户扣钱，然后把钱加到朋友的账户上。那么问题来了：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;如果只完成一半怎么办？【原子】&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;假设银行系统在扣完你的钱后突然断电了，没能把钱加到朋友账户上。这时候钱就凭空消失了！你的账户少了钱，但朋友并没有收到。&lt;/p&gt;&#xA;&lt;p&gt;事务就是为了解决这个问题：&lt;strong&gt;它确保一组相关操作要么全部完成，要么一个都不做&lt;/strong&gt;。就像是给这些操作绑了个保险绳，不让它们半途而废。&lt;/p&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;多人同时操作怎么办？【隔离】&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;想象你和家人共用一个银行账户，账户里有1000元。你在商场准备刷卡买800元的东西，同一时间，你爱人在超市也想用这个账户买500元的菜。&lt;/p&gt;&#xA;&lt;p&gt;如果系统没有适当控制，可能会出现这种情况：系统先检查账户有1000元（够付800元），然后你老婆那边系统也检查有1000元（够付500元）。结果你们俩同时消费了1300元，超出了账户里的1000元！&lt;/p&gt;&#xA;&lt;p&gt;事务能够解决这个问题，&lt;strong&gt;它会确保在一个人操作的时候，其他人要么看到操作前的状态，要么看到操作后的状态，不会看到中间状态，避免大家操作冲突&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;数据会不会突然丢失？【持久】&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;假设你正在网上填写一个很长的表单，好不容易填完提交，系统提示&amp;quot;保存成功&amp;quot;，但第二天你登录发现信息不见了！原来是系统在显示成功后，还没来得及真正保存到硬盘上就崩溃了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;事务确保一旦系统告诉你&amp;quot;操作成功&amp;quot;，那么即使下一秒系统崩溃，你的数据也不会丢失&lt;/strong&gt;。它就像是给你的重要资料上了一个保险锁。&lt;/p&gt;&#xA;&lt;p&gt;总结来说事务模型就是为多种操作提供原子化/隔离性/持久性的一个编程模型。也就是事务的ACID模型。 【A：Atomicity，C：Consistency，I：Isolation，D：Durability】&lt;/p&gt;&#xA;&lt;h2 id=&#34;acid事务特性&#34;&gt;ACID事务特性：&lt;/h2&gt;&#xA;&lt;h3 id=&#34;原子性&#34;&gt;原子性：&lt;/h3&gt;&#xA;&lt;p&gt;这个原子性其实是计算机中“原子”概念的衍生，计算机的原子性指一个操作或者数据没有中间状态，只有开始和结束，没有中间状态。而事务提到的原子其实是有中间状态，但是中间状态对于其他的操作主体是无法干预的，同时如果中止，则在事务中所有操作都会被回滚。DDIA书中更多的称为&lt;strong&gt;可中止性（abortability）&lt;/strong&gt;：“能够在错误时中止事务，丢弃该事务进行的所有写入变更的能力”&lt;/p&gt;&#xA;&lt;h3 id=&#34;一致性&#34;&gt;一致性：&lt;/h3&gt;&#xA;&lt;p&gt;事务一致性是ACID特性中最为核心却也最容易被误解的概念。从形式化的角度看，一致性指的是事务执行前后，数据库必须从一个一致性状态转变为另一个一致性状态。所谓一致性状态，是指数据库中的数据满足所有预定义的完整性约束(integrity constraints)。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;实体完整性(Entity Integrity)&lt;/strong&gt;: 通过主键约束实现，确保每个实体具有唯一标识&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;参照完整性(Referential Integrity)&lt;/strong&gt;: 通过外键约束实现，保证实体间引用关系的有效性&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;域完整性(Domain Integrity)&lt;/strong&gt;: 通过数据类型、CHECK约束等实现，确保属性值满足预定义规则&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;用户定义完整性(User-Defined Integrity)&lt;/strong&gt;: 通过触发器、存储过程等实现特定业务规则&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;一致性可被视为一个不变量(invariant)的保持过程，它确保数据库状态转换符合业务规则和领域逻辑。与原子性和隔离性不同，一致性的保证不仅依赖于数据库系统本身，还需要应用程序正确实现业务逻辑。同时原子性、隔离性和持久性是实现一致性的技术手段&lt;/p&gt;&#xA;&lt;h3 id=&#34;隔离性&#34;&gt;隔离性：&lt;/h3&gt;&#xA;&lt;p&gt;隔离性指的是两个事务之间的操作和中间状态和变量互相看不见，即使一个用户做了一个写操作其他用户也看不到。&lt;/p&gt;&#xA;&lt;pre class=&#34;mermaid&#34;&gt;&#xA;  sequenceDiagram&#xA;    participant User1 as User 1&#xA;    participant DB as Database&#xA;    participant User2 as User 2&#xA;&#xA;    &#xA;    User1-&amp;gt;&amp;gt;DB: get counter&#xA;    DB--&amp;gt;&amp;gt;User1: 42&#xA;    &#xA;    Note over User1: [42 + 1 = 43]&#xA;    &#xA;    User2-&amp;gt;&amp;gt;DB: get counter&#xA;    DB--&amp;gt;&amp;gt;User2: 42&#xA;    &#xA;    Note over User2: [42 + 1 = 43]&#xA;    &#xA;    User1-&amp;gt;&amp;gt;DB: set counter = 43&#xA;    DB--&amp;gt;&amp;gt;User1: ok&#xA;    &#xA;    User2-&amp;gt;&amp;gt;DB: set counter = 43 &#xA;    DB--&amp;gt;&amp;gt;User2: ok&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;p&gt;最简单的时间就是事务之间完全串行，这样的话就会完全保证事务之间完全是看不到中间状态，但是在实际情况情况下为了提高效率，一般会将隔离优化为4个等级：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
