幻影读以及如何避免

这同样是上次的培训材料,下面在这里共享出来,直接上材料的截图:(图片太小?在新标签页中打开吧!


如何避免呢? select for update



要注意,应用代码里嵌入for update时一定要注意,要准确使用这个功能。

允许不可重复(Non-repeatable Read)是指在一个事务内多次取同一行数据时,由于其他事务对该行进行了修改并提交,使得每次取的结果可能不同。这是数据库管理系统中的隔离级别之一,在某些场景下可能是可以接受的行为。 ### 数据库隔离级别的背景知识 为了保证并发环境下的数据一致性、完整性以及可靠性,SQL标准定义了四种不同的事务隔离级别: 1. **未提交 (Read Uncommitted)**:最低的隔离等级,一个事务可以看到另一个尚未提交的事务对数据所做的改动。这可能会导致脏(Dirty Reads)、不可重复(Non-Repeatable Reads)和(Phantom Reads),是最宽松也是最不安全的一种模式。 2. **已提交 (Read Committed)**:大多数商用系统默认采用这种隔离级别。它能防止脏的发生,即只能看到已经被其他事物成功提交后的变化,但仍可能出现不可重复幻影的问题。 3. **可重复 (Repeatable Read)**:在此隔离级别上,只要有一个事务首次访问某一行记录之后,其它任何事务都不能再对其进行更新操作直到前者结束为止,以此确保同一个事务内的所有查询都能得到一致的数据视图,避免了不可重复现象;然而,仍然存在幻影的风险。 4. **串行化 (Serializable)**:最高程度的隔离级别,完全杜绝了任何形式的一致性问题如脏、不可重复等。它通过强制实施严格的锁定策略来达到目的,但也因此牺牲了一部分性能效率。 ### 允许不可重复的影响 当选择“**已提交**”作为数据库系统的隔离级别时,实际上是选择了容忍一定程度上的“不可重复”。这意味着在同一事务中两次或更多次取同一条记录之间的时间里,如果有别的已完成的事物改变了这条记录的内容并且被提交,则第二次到的就是最新的版本而不是第一次所见到的那个旧值。 这种情况虽然破坏了绝对意义上的数据一致性原则,但在实际应用中并非总是需要追求极致的数据一致性。例如在一些对实时性和响应速度有较高需求的应用场合里,“允许不可重复”的做法能够提供更佳的整体吞吐量与用户体验。 #### 实际案例分析 假设我们有一张存储用户余额信息的表 `balance_table` ,当我们运行如下 SQL 查询时: ```sql BEGIN TRANSACTION; SELECT balance FROM balance_table WHERE user_id = 'alice'; UPDATE balance_table SET balance = balance + 100 WHERE user_id = 'bob'; -- 更新另一条记录不影响 alice 的余额显示 COMMIT; -- 同一事务再次取 Alice 的余额 SELECT balance FROM balance_table WHERE user_id = 'alice'; ``` 若此时另一位用户正好也完成了针对Alice账户的一个转账交易并提交,那么上述两个 SELECT 语句返回的结果就会不一样——这就是所谓的“不可重复”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值