脏读:事务A修改记录,事务A运行成功但未提交时,事务B获取数据时获取了已更新数据。当事务A回滚后,事务B获得的数据不准确,这种现象被成为脏读。
关键词:事务A修改运行,但未提交。事务B获取数据为事务A执行后的数据。事务A回滚后导致事务B获得的数据不正确;
出现脏读的前提条件:事务隔离级别为:read uncommitted;
实验:
有一个salary表,如下:
首先,关闭数据库的自动提交功能:set autocommit = 0;
然后开启事务并修改张无忌的e_salary = 20000,但不提交事务;
然后另一事务查看此表:
我们可以看到,绿色的另一事务读取的数据中,张无忌的e_salary为20000(若黑色的事务回滚后,绿色的事务再次获取就为之前正确数据了)。
由此可见:当事务隔离级别为 read uncommitted时,会出现脏读的现象。
将事务隔离级别设置为 read committed后就能避免脏读了。
可重复读:当事务A读取了一条数据后,事务B对该数据进行了修改并提交,事务A再次读取此数据时数据不变;
当隔离级别为 read committed时,虽然避免了脏读,但是会导致不可重复读。
实验:
将事务级别设置为 repeatable read:
关掉自动提交,开始黑色事务:并修改数据:
在黑色事务未提交时,绿色事务查看数据:
我们可以看到,绿色事务读取的还是原来的数据。
黑色事务提交后绿色事务继续查看:
所以:当事务隔离级别设置未可重复读:repeatable read后,可以避免不可重复读的问题出现。
幻读:当事务A读取表中的数据时,如10条工资为1000的数据,此时事务B插入或删除了一条工资为1000的数据,事务A再次读取表中数据时,工资为1000的数据
就多了一条或少了一条,导致出现幻读。
为了避免幻读,可以将隔离级别设置为:serializable(串行化)
当隔离级别为串行话时,数据库的性能将收到很大的影响,应为事务必须进行排队(具体可以看后面的锁概念),所以对于mysql来所,默认的隔离级别为:repeatable read.