CodeGym /课程 /SQL SELF /事务隔离级别入门

事务隔离级别入门

SQL SELF
第 39 级 , 课程 4
可用

想象一下你在咖啡馆打工,一个服务员在厨房查蛋糕库存,另一个在帮新客户下蛋糕订单。在理想情况下,他们都应该看到一样的蛋糕数量,这样就不会出错,比如“重复预订”。但现实中并发操作可能会带来各种问题。

下面是三种常见的糟心情况:

  1. Dirty Read(脏读): 一个查询能看到另一个还没提交的更改。如果这些更改被回滚了,第一个查询就像刚面试的大学生一样天真。

  2. Non-Repeatable Read(不可重复读): 一个查询两次读取同一数据,但中间有人把它改了。这就像你去火车站看时刻表,过一分钟回来发现车次被取消了。或者你找钱的时候票被别人买走了 :)

  3. Phantom Read(幻读): 一个查询看到一部分行,但两次执行之间有人插入了新行,结果就变了。这就像你公司投标输了,结果除了你和市长老婆的标书,其他全被取消了。

事务隔离级别

现在我们知道了这些问题,是时候看看PostgreSQL给我们解决方案了——事务隔离级别。这就像给并发事务之间定规则。隔离级别越高,事务之间互不干扰的保证就越强。但代价就是“服务速度”会变慢,也就是性能会下降。

PostgreSQL里的隔离级别

  1. Read Uncommitted(读取未提交数据):

    • 允许读取还没提交的更改(对,就是脏读的典型代表)。
    • 在PostgreSQL里其实是按Read Committed实现的,纯正的Read Uncommitted并不支持。PostgreSQL拒绝实现它,因为太不靠谱了。
  2. Read Committed(读取已提交更改):

    • 防止脏读。
    • 事务只能看到执行命令时已经提交的数据。
    • 但还是可能出现Non-Repeatable ReadPhantom Read
  3. Repeatable Read(可重复读):

    • 保证你读到的数据在事务期间不会变。
    • 防止脏读和不可重复读。
    • 但幻读还是有可能。
  4. Serializable(可串行化):

    • 保证所有事务像是一个接一个顺序执行的。
    • 防止所有三种问题:脏读、不可重复读和幻读。
    • 最严格——也是最慢——的隔离级别。

为什么事务隔离很重要?

想象一下一个电商数据库,上千用户同时下单。如果隔离级别没选好,可能会遇到一堆冲突:比如商品“消失”了,或者订单重复。

选对隔离级别能帮你搞定并发事务,平衡性能和数据完整性。比如:

  • 分析系统一般选最低的隔离级别(比如Read Committed),因为数据精度不是那么关键。
  • 金融系统更喜欢Serializable级别,避免计算出错或操作重复。

隔离级别的使用例子

  1. Read Committed

这个级别保证你不会读到可能被回滚的数据。

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;

-- 读取账户数据。
SELECT balance FROM accounts WHERE account_id = 1;

-- 如果有别的事务更新了余额,这里的数据会立刻刷新。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Repeatable Read

这个级别保证你读到的数据在整个事务期间都不会变。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;

-- 读取账户数据。
SELECT balance FROM accounts WHERE account_id = 1;

-- 就算有别的事务更新了余额,你也看不到变化。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;
  1. Serializable

在这个级别下,事务就像系统里只有你一个人一样。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;

-- 读取账户数据。
SELECT balance FROM accounts WHERE account_id = 1;

-- 任何别的事务想改这些数据,都得等你事务结束。
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

COMMIT;

怎么选隔离级别?

选隔离级别要看你的需求:

  • 如果速度比精度重要,而且你能接受幻读——选Read Committed
  • 如果精度重要,但还想要高性能——用Repeatable Read
  • 如果你要100%保证数据正确,哪怕慢点——那就Serializable

注意!高隔离级别可能导致锁和性能下降。合理的做法是性能和数据一致性之间找个平衡点。

1
调查/小测验
事务入门第 39 级,课程 4
不可用
事务入门
事务入门
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION