事物的隔离级别

事务的隔离级别是数据库管理系统(DBMS)为了保证事务操作的一致性和并发性而提供的一种机制,用于定义多个事务并发执行时,数据访问的可见性程度。

在 SQL 标准中,事务隔离级别分为 4 种,由低到高分别为:


1. 读未提交(Read Uncommitted)

  • 特点:一个事务可以读取另一个事务未提交的数据。
  • 可能出现的问题
    • 脏读(Dirty Read):读取到另一个事务尚未提交的修改数据,如果该事务回滚,读到的数据就会变成无效数据。
  • 性能:并发性能高,但数据安全性低。
  • 应用场景:几乎不用,数据一致性要求低的场景。
示例:

事务 A 修改数据未提交,事务 B 可以读取到 A 修改后的数据。


2. 读已提交(Read Committed)

  • 特点:一个事务只能读取另一个事务已提交的数据。
  • 解决的问题
    • 避免脏读
  • 可能出现的问题
    • 不可重复读(Non-repeatable Read):在同一事务内,读取同一数据两次,第二次读取时,数据被另一个事务修改,导致结果不一致。
  • 性能:是大多数数据库的默认隔离级别(如 Oracle)。
  • 应用场景:数据一致性要求一般的场景。
示例:
  • 事务 A 修改数据并提交,事务 B 读取时能看到事务 A 提交后的数据。

3. 可重复读(Repeatable Read)

  • 特点:同一事务内多次读取数据的结果是一样的,保证了数据的一致性。
  • 解决的问题
    • 避免脏读
    • 避免不可重复读
  • 可能出现的问题
    • 幻读(Phantom Read):在同一事务中,读取数据时,另一事务插入了新数据,导致结果集不一致。
  • 性能:大部分数据库支持(如 MySQL 的默认隔离级别)。
  • 应用场景:数据一致性要求高的场景。
示例:
  • 事务 A 读取数据,事务 B 修改数据并提交,事务 A 再次读取时,数据与第一次一致,但事务 B 插入新行会导致幻读。

4. 串行化(Serializable)

  • 特点:最高的隔离级别,事务顺序执行,避免所有并发问题。
  • 解决的问题
    • 避免 脏读不可重复读幻读
  • 性能:并发性能最低,事务必须一个接一个地执行,通常通过锁表实现。
  • 应用场景:对数据一致性要求极高的场景,如银行账户、金融交易等。
示例:
  • 所有事务按顺序执行,完全避免并发问题。

4 种隔离级别总结对比

隔离级别脏读不可重复读幻读性能
读未提交可能可能可能最高
读已提交避免可能可能
可重复读避免避免可能
串行化避免避免避免最低

事务隔离级别的选择

  1. 读未提交:适用于对性能要求极高且数据一致性要求极低的场景(几乎不用)。
  2. 读已提交:大部分应用的默认选择(Oracle 默认)。
  3. 可重复读:MySQL 的默认级别,适用于大多数业务场景。
  4. 串行化:适用于数据一致性要求极高的场景,但性能损耗大。

数据库的默认隔离级别

  • MySQL:默认隔离级别为 可重复读(Repeatable Read)
  • Oracle:默认隔离级别为 读已提交(Read Committed)
  • SQL Server:默认隔离级别为 读已提交(Read Committed)

总结

事务的隔离级别通过控制数据访问的并发性和一致性,解决了 脏读不可重复读幻读 等问题。在实际应用中,需要根据系统的性能和数据一致性要求选择合适的隔离级别。

以下是结合实际业务场景的事务隔离级别示例,帮助理解事务隔离级别及其在不同业务中的应用。


业务场景示例

假设有一个电商系统,包含订单管理库存管理两个模块,涉及用户下单、支付和库存扣减操作。将探讨不同事务隔离级别下可能出现的问题及其解决方案。

1. 读未提交(Read Uncommitted)

场景:用户下单时读取了未提交的库存数据,导致显示错误的库存。
  • 业务过程
    1. 用户A下单,开始一个事务,扣减商品库存(但未提交)。
    2. 用户B在此时查询库存,读取到未提交的数据,发现库存已经减少。
    3. 如果用户A的事务回滚,用户B看到的库存数据是错误的。
示例代码

用户A操作(扣减库存但未提交):

BEGIN;
UPDATE inventory SET stock = stock - 1 WHERE product_id = 1001;
-- 模拟未提交事务

用户B操作(查询库存):

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
SELECT stock FROM inventory WHERE product_id = 1001;
COMMIT;
风险

用户B查询到了用户A未提交的库存更新数据,导致脏读。这种情况下用户看到的库存数据并不准确。


2. 读已提交(Read Committed)

场景:用户支付时多次查询订单状态,导致不可重复读问题。
  • 业务过程
    1. 用户A查询订单状态为“待支付”。
    2. 另一个事务(如用户B或后台操作)修改订单状态为“已支付”并提交。
    3. 用户A再次查询订单状态,发现状态变为“已支付”。
示例代码

用户B操作(提交订单支付):

BEGIN;
UPDATE orders SET status = '已支付' WHERE order_id = 123;
COMMIT;

用户A操作(查询订单状态):

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SELECT status FROM orders WHERE order_id = 123; -- 第一次读取,状态是“待支付”

-- 等待用户B更新状态
SELECT status FROM orders WHERE order_id = 123; -- 第二次读取,状态变为“已支付”
COMMIT;
风险

用户A同一事务中两次查询订单状态,结果不一致,出现了不可重复读问题。


3. 可重复读(Repeatable Read)

场景:用户在购物车中多次读取商品价格,价格保持一致。
  • 业务过程
    1. 用户A将商品添加到购物车,读取商品价格为 100 元
    2. 另一个事务(如商家修改价格)将商品价格更新为 120 元
    3. 用户A再次读取商品价格,仍然显示 100 元,保证了一致性。
示例代码

商家操作(修改商品价格):

BEGIN;
UPDATE products SET price = 120 WHERE product_id = 1001;
COMMIT;

用户A操作(读取商品价格):

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT price FROM products WHERE product_id = 1001; -- 第一次读取价格 100 元

-- 等待商家修改价格
SELECT price FROM products WHERE product_id = 1001; -- 第二次读取价格依然是 100 元
COMMIT;
结果

可重复读 隔离级别下,用户A两次读取商品价格一致,避免了不可重复读问题。


4. 串行化(Serializable)

场景:防止多个用户同时下单导致超卖问题。
  • 业务过程
    1. 用户A查询库存,显示有 1 件
    2. 用户B也查询库存,显示有 1 件
    3. 两个用户同时下单,导致库存扣减为 -1,发生超卖。

串行化 隔离级别可以避免这种并发问题,因为事务按顺序执行。

示例代码

用户A操作(下单):

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT stock FROM inventory WHERE product_id = 1001; -- 查询库存 1 件
UPDATE inventory SET stock = stock - 1 WHERE product_id = 1001;
COMMIT;

用户B操作(下单):

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
SELECT stock FROM inventory WHERE product_id = 1001; -- 等待用户A事务完成
UPDATE inventory SET stock = stock - 1 WHERE product_id = 1001;
COMMIT;
结果

串行化 隔离级别下,用户B的事务必须等待用户A的事务完成后才能执行,避免了库存超卖问题。


总结:业务示例与风险对比

隔离级别业务场景示例问题
读未提交查询未提交库存脏读(读取未提交数据)
读已提交查询订单状态不可重复读(结果不一致)
可重复读查询商品价格幻读(新增数据影响结果集)
串行化防止库存超卖无并发问题,性能最低

实际业务选择

  1. 读已提交(Read Committed)
    • 大多数业务场景,如订单状态查询。
  2. 可重复读(Repeatable Read)
    • 解决不可重复读问题,如商品价格读取、银行账户查询。
  3. 串行化(Serializable)
    • 对数据一致性要求极高的业务场景,如库存扣减防止超卖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值