务读到的数据就是脏数据,这就是脏读(Dirty Read)。
下面,我准备好了一个例子,来看一下。
首先,我准备好employees表的数据:
然后,分别开启两个MySQL客户端连接,按顺序依次执行事务A和事务B:
第一步:执行事务A,UPDATE employees SET last_name = 'keng' WHERE employee_id = 100;
第二步:执行事务B,SELECT * FROM employees WHERE employee_id = 100;
第三步:执行事务A, ROLLBACK;
第四步:执行事务B,SELECT * FROM employees WHERE employee_id = 100;
第五步:执行事务B,COMMIT;
当事务A执行完第1步时,它更新了id=1的记录,但并未提交,而事务B在第2步读取到的数据就是未提交的数据。
随后,事务A在第3步进行了回滚,事务B再次读取employee_id=100的记录,发现和上一次读取到的数据不一致,这就是脏读。
可见,在Read Uncommitted隔离级别下,一个事务可能读取到另一个事务更新但未提交的数据,这个数据有可能是脏数据。
在Read Committed隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。
不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
我们接着使用上表的数据:
然后,分别开启两个MySQL客户端连接,按顺序依次执行事务A和事务B:
第一步:执行事务A,SELECT * FROM employees WHERE employee_id = 100;
第二步:执行事务B,UPDATE employees SET last_name = 'keng' WHERE employee_id = 100;
第三步:执行事务B,COMMIT;
第四步:执行事务A,SELECT * FROM employees WHERE employee_id = 100;
第五步:执行事务A,COMMIT;
当事务B第一次执行第1步的查询时,得到的结果是Alice,随后,由于事务A在第2步更新了这条记录并提交,所以,事务B在第4步再次执行同样的查询时,得到的结果就变成了Bob,因此,在Read Committed隔离级别下,事务不可重复读同一条记录,因为很可能读到的结果不一致。