数据库系统事务隔离级别

来源:互联网 发布:js url转base64编码 编辑:程序博客网 时间:2024/06/07 15:26

READ UNCOMMITTED : 未提交读

在 READ UNCOMMITTED 级别,事务中的修改,即使没有提交,对其他事务也都是可见的,事务可以读取(注意说的是读取)未提交的数据,这也被称为脏读,这个界别等级会导致很多问题,从性能上来说,READ UNCOMMITTED  不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少用。


比如:

事务A:小强在A表修改一条记录money字段的金钱总额度,原100增加1000元后为1100,记作TimeA, 同一个事务中在修改A表后还需要去查询修改别的表...,记作TimeB...

事务B:小明这时读取A表同一记录的money字段的金钱总额,发现为1100,记作TimeC


TimeA < TimeC < TimeB


并发原因,同时采用 read uncommitted 事务级别,当事务A执行到TimeA,事务B 执行 开始执行到TimeC 查询到1100, 但事务A在TimeB回滚,把1100重新会滚味1000

这个时候,事务B 读取到的1100就是脏数据。



READ COMMITTED : 提交读

大多数数据库系统的默认隔离级别都是 READ COMMITTED (单mysql不是),READ COMMITTED 满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始提交之前,所做的任何修改对其他事务都是不可见的,这个级别有时候也叫不可重复读,应为两次执行同样的查询,可能会得到不一样的结果。


事务A:小强在A表修改一条记录money字段的金钱总额度,原100增加1000元后为1100,记作TimeA, 同一个事务中在修改A表后还需要去查询修改别的表...,记作TimeB...

事务B:小明这时想读取A表同一记录的money字段的金钱总额


TimeA < TimeC < TimeB


采用 read committed 事务级别,当事务A执行到TimeA,事务B 想开始执行查询到1100, 但事务A未提交事务B时看不到money 为1100的,一种可能的原因事务A未提交所以事务B被阻塞,需要等到事务A提交后才能顺利执行,查询到1100,另外一种可能是,只能读取到money的原有值100,应为事务B看不到未提交的事务A对money的修改结果。

另外会有一个不可重复读的问题:

事务C: 有两条查询语句,语句1,查询A表的某一记录 select * from A where id = 1   时间为 TimeA, 语句2,同样查询A表的某一记录 select * from A where id = 1   时间为 TimeB,

事务D:修改A表某一记录的值,语句 update A set money = money + 1000 where id = 1 时间为TimeC


TimeA < TimeC < TimeB


对于事务C内的两条语句1和2,得到的查询结果是不一样的,应为该记录在事务A执行的期间被事务D修改了并提交了D事务,事务C的这样在同一事务中前后两次同样的查询,得到的结果不一样,称为不可重复读。


这都是因为read committed 没有限制对同记录的 修改、删除等


REPEATABLE READ:可重复读

REPEATABLE READ解决了脏读的问题,该别别保证了在同一个事务中多次读取同样纪录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读的问题。所谓幻读,指的是当某个事务在读取某哥范围内的纪录时,会产生幻行,InooDB 和 XtraDB 存储引擎通过多版本兵法控制解决了幻读的问题。

可重复读是MySql的默认事务隔离级别。


事务C: 有两条查询语句,语句1,查询A表的某一记录 select * from A where id = 1   时间为 TimeA, 语句2,同样查询A表的某一记录 select * from A where id = 1   时间为 TimeB,

事务D:修改A表某一记录的值,语句 update A set money = money + 1000 where id = 1 时间为TimeC


TimeA < TimeC < TimeB

对于事务C内的两条语句1和2,得到的查询结果是一样的,因为REPEATABLE READ,事务A执行完语句1后,会对所有满足条件的记录加锁,这期间被事务D想修改该条记录,发现记录上锁,只能被阻塞等待,等到事务C提交后才能顺利执行。


另外的问题:

事务E: 有两条查询语句,语句1,查询A表的某一记录 select * from A where id > 1 and id < 5   ,结果id 有 2和4,时间为 TimeA, 语句2,同样查询A表的某一记录 select * from A where iid > 1 and id < 5  时间为 TimeB,

事务F:给A表某一记录,语句 inser into A(id) value(3) 时间为TimeC


TimeA < TimeC < TimeB

对于事务E内的两条语句1和2,语句2的到id为2和4的记录值完全一样,但是相比语句1,多了一条记录id=3,这是因为在TimeC 事务F新增了一条记录,这就是幻读


SERIALIZABLE:可串行化

SERIALIZABLE 是最高的隔离级别,它通过强制事务串执行,避免了前面说的幻读的问题,简单来说,SERIALIZABLE 会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题,实际应用中也很少用到这个隔离级别,只有在非常需要确保数据一致性而且可以接受没有并发的情况下,才考虑采用该级别。

0 0
原创粉丝点击