当前位置: 首页 > 科技观察

MySQL数据库的四种隔离级别

时间:2023-03-18 01:25:37 科技观察

最近看了《高性能MYSQL》这本书,通过分析加深了印象。数据库的事务操作实际上是一组原子操作。要么所有操作都成功,要么所有操作都失败。比如我需要对外销售1张电影票,将销售信息注册到另外一个表中。至少需要以下3个步骤:1.查询电影票数量是否足够卖1张电影票SELECTremain_countFROMcinemaWHEREfilm_id=123456789;2.更新电影票数量UPDATEremain_count=remain_count-1FROMcinemaWHEREfilm_id=123456789;3.插入销售信息INSERTINTOSell_mes(id,mes)values(id,mes);想象一下,如果我们的某个步骤出错或者被其他操作打乱了,很容易出问题。例如,有两个销售系统A和B销售同一张票。此时,只剩下一张票了。A收到卖票的订单。他查到电影票的张数大于1,所以他要卖的时候,也就是执行第一步和执行第二步的时候,B也收到了订单,看到剩下的票是大于1,B也卖出1张票。这时出现了只剩下一张票却卖掉两张的荒唐情况。所以一个好的系统需要通过ACID测试。至于ACID是什么,大家可以自行百度。这篇博文是关于隔离级别和隔离示例的。有四种类型的事务隔离级别。隔离级别高的数据库的可靠性性能高,但并发低,而隔离级别低的数据库可靠性低,但并发高,系统开销小1.READUNCIMMITTED(未提交读)事务中的修改甚至可以被其他事务看到如果他们没有承诺。比如上面两步的现象就叫做脏读。这种隔离级别会导致很多问题。如非必要,不要随便使用。例子:还是在售票系统中,小明和小华是售票员,他们是两个不同窗口的员工。现在售票系统只剩下3张票了。这时A来找小花买3张票,B来找小明买票。萧华发现还有剩余的票,就接了单。快要执行第三步的时候,小明收到了B的请求,要查看是否还有余票。小花见卖了3张票,便不肯卖票。但是,小花的系统出了问题,第三步执行失败。为了保证原子性,数据库回滚了数据,也就是说一张票都没有卖出去。总结:这是事务还没有提交的后果,其他事务可以看到里面修改的数据,也就是脏读。2.READCOMMITTED(提交读)大多数数据库系统默认的隔离级别是READCOMMITTED。这个隔离级别是事务的开始。只能看到已完成交易的结果。其他事务看不到正在执行的内容。的。在这个层面上,会出现读取旧数据的现象。例:小明还是小花的业务员,还有3张票。A来找小华要3张票单。小花接单,要卖3张票。以上销售步骤正在执行的时候,B也来了小明的Buytickets,因为小华的销售交易进行到一半,小明的交易没有看到小华的交易执行,读到的票数是3,当订单是准备接受,小华的销售交易完成,这时小明的系统变成了显示0票,小明正要按下鼠标接单的手迅速缩回。总结:这是小花交易执行的一半,但是小明看不到他执行的操作,所以他看到的是旧数据,也就是无效数据。3.REPEATABLEREAD(可重复读)REPEATABLEREAD解决了脏读问题。这个级别保证了每一行记录的结果是一致的,也就是上面提到的读取旧数据的问题,但是不能解决另外一个问题。幻像行,顾名思义,就是突然弹出的数据行。意思是某个事务正在读取某个范围的数据,但是另一个事务向这个范围的数据插入数据,导致多次读取时数据行数不一致。例:销售部规定,如果销售记录低于规定值,则扣除工资。这时,经理在后台控制台查看了小明的销售记录,发现销售记录没有达到规定的次数。他暗暗高兴,做好了准备。打印出销售单后,我自信满满地向小明求婚。没想到打印出来的时候发现销售单里面的销售数量增加了几个项目,刚好符合要求。愤怒的经理撕毁了名单纸。原来小明一印就卖出了几张票,才免去了降薪的血雨腥风。总结:读取同一条数据虽然可以保证一致性,但是不能保证没有插入新的数据。4.SERIALIZABLE(可序列化)SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行来避免之前的幻读情况(注意是串行的)。因为他加了大量的锁,大量的请求超时,所以性能会比较低,这个隔离级别可能只有在特别需要数据一致性,并发量不需要这么大的时候才考虑大的。分类:mysql