脏读-不可重复读-幻影读

脏读,不可重复读,幻影读是数据库最常见、最基础的问题。

我参照 http://blog.youkuaiyun.com/alex197963/article/details/1580841 里的讲述,夹杂自己的实践写点。

 

前提:我说的是数据在隔离情况下,如何保证数据的可靠性,以及尽量保证数据库的性能。

 

 

 

事务场景 是这样的:
对于同一个银行帐户A内有200元,甲进行提款操作100元,乙进行转帐操作100元到B帐户。如果事务没有进行隔离可能会并发如下问题:

 

脏读---读取未提交的数据---Read uncommitted

要点:应用程序中,维护了不同的变量去同步数据库。

分析:既然是数据隔离,不会在同一事务。

      如果没有本地变量或缓存辅助,是不可能发生这种情况的,因为当前主流的数据库都是提交了之后,其他的访问才能知道。

      这个问题主要存在于应用程序中。举例,Hibernate的缓存可能会产生脏读。如,javabean修改但没有保存在数据库中时,操作的业务数据存在于内存中(Hibernate控制)。

      场景描述:数据库 银行帐户A内有200元。A读取时是200元(放在缓存里),取出100元(缓存中A账户的余额改为100元)。B要转账100元,如果余额在缓存中取,则缓存中的账户余额将变为0元。倘若A撤销刚才的取钱操作,账户将变为200元(如果以A查询出的200元为基础)。这样,A账户的最终金额将会是200或者0元,到底是谁,决定于谁提交,A提交账户是200,B提交账户将是0元(如果以B查询出的100元为基础)。但实际上应该为100元。

      解决方法:维护一个实例。

# 数据库事务隔离问题:不可重复和幻 ## 1. (Dirty Read) **定义**:事务A取了事务B**未提交**的修改数据,如果事务B回滚,事务A取的就是"数据"。 **示例**: ```sql -- 事务B BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 未提交 -- 事务A(此时取到未提交的修改) SELECT balance FROM accounts WHERE id = 1; -- 取到数据 ``` ## 2. 不可重复 (Non-repeatable Read) **定义**:事务A内**多次取**同一数据,期间事务B修改并提交了该数据,导致事务A前后取结果不一致。 **示例**: ```sql -- 事务A BEGIN; SELECT balance FROM accounts WHERE id = 1; -- 第一次取,返回1000 -- 事务B UPDATE accounts SET balance = 900 WHERE id = 1; COMMIT; -- 事务A SELECT balance FROM accounts WHERE id = 1; -- 第二次取,返回900(与第一次不同) COMMIT; ``` ## 3. 幻 (Phantom Read) **定义**:事务A按相同条件**多次查询**,期间事务B**新增或删除**了符合条件的数据并提交,导致事务A前后查询结果集不一致。 **示例**: ```sql -- 事务A BEGIN; SELECT * FROM accounts WHERE balance > 1000; -- 第一次查询返回2条记录 -- 事务B INSERT INTO accounts(id, balance) VALUES(3, 1500); COMMIT; -- 事务A SELECT * FROM accounts WHERE balance > 1000; -- 第二次查询返回3条记录(多出"幻影行") COMMIT; ``` ## 对比表格 | 问题类型 | 关键区别 | 典型隔离级别解决方案 | |----------------|----------------------------------|---------------------------| | | 取未提交数据 | READ_COMMITTED及以上 | | 不可重复 | 同一数据多次取结果不同 | REPEATABLE_READ及以上 | | 幻 | 结果集行数发生变化 | SERIALIZABLE |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值