脏读
- 脏读:在业务中读取的数据出现不一致的错误。
package demo;
/* 脏读:数据不一致的错误。
*
* 在对一个对象的方法加锁的时候,需要考虑业务的整体性,
* 在demo中为setUser/getUser方法同时加锁synchronized同步关键字,
* 保证业务的原子性,不然会出现业务错误。
* */
public class DirtyRead {
private String userName = "lc";
private String password = "123";
//设置User的名、密码
public synchronized void setUser(String userName, String password){
this.userName = userName;
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
this.password = password;
System.out.println("There set UserName : "+userName +"---password:----"+password);
}
//得到User信息
public synchronized void getUser(){
System.out.println("There get UserName : "+userName +"---password:----"+password);
}
//test
public static void main(String[] args) throws InterruptedException {
final DirtyRead dr1 = new DirtyRead();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
dr1.setUser("Jack", "123456");
}
});
/*
* t1线程只休眠等待1s,但是在setUser方法中,有Thread.sleep(3000);等待3秒。
* 也就是说,在set方法还没有执行完,主线程就开始调用getUser方法。
* 这样就造成了数据的不一致性,脏读
* */
t1.start();
t1.sleep(1000);
dr1.getUser();
}
}
getUser方法没有加synchronized时:结果
There get UserName : Jack---password:----123
There set UserName : Jack---password:----123456
getUser方法加上synchronized时:结果
There set UserName : Jack---password:----123456
There get UserName : Jack---password:----123456
关系型数据库中的一致性表现
- 我们常说的ACID:原子性、一致性、隔离性、永久性
场景描述:
一个用户A在9:00访问数据库表table。查询一个数据num=100,假设table数据量1000W
,需要10分钟才能查询到num,
然后一个用户B , 在9:05访问数据库,对数据num进行Update,num=200。
问:用户A查询到的数据num的值,是100还是200?
- 用户A在9:00发起的查询,他查询到的数据永远只是9:00这一刻数据库的数据,所以是num=100,
- 为什么?
比如说Oracle数据库中有个Undo的概念,类似于日志,记录修改数据的旧值。
A——9:00发起查询,在9:10查到num=?
B在9:05提交update了num=200。
A在查到num的值的时候,发现num有更改过,数据库就去Undo中找旧值返给A。
就旧值返给A,即使没有,报一个异常snapshot too old的异常。
数据库让它报异常都不会将num=200返回给A,这就是关系型数据库的一致性表示。
时间: 2024-10-12 10:02:14