<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>事务 on 老张开工了</title>
    <link>/%E4%BA%8B%E5%8A%A1/</link>
    <description>Recent content in 事务 on 老张开工了</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sat, 15 Feb 2025 10:00:00 +0800</lastBuildDate>
    <atom:link href="/%E4%BA%8B%E5%8A%A1/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>事务与并发控制</title>
      <link>/posts/2025/02/transaction-and-concurrency/</link>
      <pubDate>Sat, 15 Feb 2025 10:00:00 +0800</pubDate>
      <guid>/posts/2025/02/transaction-and-concurrency/</guid>
      <description>数据库的并发控制决定了多个用户同时读写时，数据一致性和性能的平衡。PostgreSQL 使用 MVCC（多版本并发控制）来优雅地解决这个问题。&#xA;什么是事务？ 事务是一组 SQL 操作的逻辑单位，满足 ACID 特性：&#xA;原子性（A）：要么全部成功，要么全部回滚 一致性（C）：事务前后数据状态一致 隔离性（I）：并发事务互不干扰（程度可调） 持久性（D）：提交后数据不会丢失 基本事务控制 -- 准备测试数据 CREATE TABLE bank_accounts ( id SERIAL PRIMARY KEY, name VARCHAR(50) NOT NULL, balance NUMERIC(10,2) DEFAULT 0 CHECK (balance &amp;gt;= 0) ); INSERT INTO bank_accounts (name, balance) VALUES (&amp;#39;张三&amp;#39;, 10000), (&amp;#39;李四&amp;#39;, 5000), (&amp;#39;王五&amp;#39;, 20000); BEGIN / COMMIT / ROLLBACK -- 转账操作：张三转 1000 给李四 BEGIN; UPDATE bank_accounts SET balance = balance - 1000 WHERE name = &amp;#39;张三&amp;#39;; UPDATE bank_accounts SET balance = balance + 1000 WHERE name = &amp;#39;李四&amp;#39;; -- 检查余额是否正确（此时其他会话还看不到变化） SELECT * FROM bank_accounts ORDER BY id; -- 确认无误后提交 COMMIT; 回滚事务 BEGIN; UPDATE bank_accounts SET balance = balance - 50000 WHERE name = &amp;#39;张三&amp;#39;; -- ❌ 余额不足 -- 发现错误，回滚全部操作 ROLLBACK; -- 查看数据，发现数据变回事务开始前的状态 SELECT * FROM bank_accounts; SAVEPOINT 保存点 BEGIN; INSERT INTO bank_accounts (name, balance) VALUES (&amp;#39;赵六&amp;#39;, 3000); SAVEPOINT after_insert; UPDATE bank_accounts SET balance = balance + 5000 WHERE name = &amp;#39;张三&amp;#39;; -- 决定撤销这笔更新 ROLLBACK TO after_insert; -- 张三的余额不受影响，但赵六已插入 COMMIT; 隔离级别 SQL 标准定义了四个隔离级别，从低到高依次限制不同的并发问题：</description>
    </item>
  </channel>
</rss>
