互联网技术02——脏读
脏读:
当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没提交到数据库中,这时另一个事务也访问这个数据,然后使用了这个数据。
对于多线程的同步和异步方法,如果考虑不周,就有可能发生脏读的错误。
例子:
package com.company;
/**
* Created by BaiTianShi on 2018/8/13.
* 脏读
*/
public class DirtyRead {
private String userName = "DaBaiTwo";
private String password = "123456";
private synchronized void setValue (String userName,String password){
this.userName = userName;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.password = password;
System.out.println("set的值:userName = "+this.userName+"!!password="+this.password);
}
private void getValue (){
System.out.println("查询的值:userName = "+this.userName+"!!password="+this.password);
}
public static void main(String[] args) {
final DirtyRead dr = new DirtyRead();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
dr.setValue("zhangSan","123");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
dr.getValue();
}
});
t1.start();
t2.start();
}
}
运行结果:
查询的值:userName = zhangSan!!password=123456
set的值:userName = zhangSan!!password=123
如果数据正常,一定是“DaBaiTwo”和“123456”成对出现,“zhangSan”和“123”成对出现。而结果可看出,出现了数据不一致的情况,这就是脏读。现实中的场景就是,当我们处理数据时,但是还没完全处理完毕,这时其他线程获取到这些数据(没完全处理完毕)就会出现数据不一致的情况,最终到时数据错误。
解决办法是将setValue加上synchronized关键字。因为这个对象被上了锁,getValue必须等待锁被释放。
oracle中是如何避免脏读的
假如有千万级别的数据,用户要查询某条记录(假设开始时的值是100),查询了10分钟,在这10分钟之内,别的用户将这条数据修改成了200,那么用户插的结果是多少?结果是100。因为Oracle采用undo机制,undo就是用来保存事务操作过的记录,如果发生错误,可将之前的数据重新填补
当用户A查询一大表table数据时,假设9:50开始查询,10:00本次查询结束,且本table在9:50这一刻的SCN编号为1000(自增)。用户B此时对大表table进行了一次update并commit。此时undo会记录B的反向操作记录为undo1,并记录SCN编号为1001,此时C再次对大表进行了一次update并commit,此时记录为undo2,并记录SCN编号为1002。当用户A查询到被修改的数据块时,发现此时的SNC编号(1002)大于查询发起时的编号(1000),然后就找比自己小的数据块进行对比,直到找到SCN编号为999的undo,在进行数据对比处理
上一篇: 互联网技术10——queue队列
下一篇: 互联网技术点评:云计算点评(一)
推荐阅读