美文网首页
2022-09-17

2022-09-17

作者: codeMover | 来源:发表于2022-09-17 22:59 被阅读0次

2.3 读-写或写-读情况

<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读-写</span>或<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">写-读</span>,即一个事务进行读取操作,另一个进行改动操作 。这种情况下可能发生<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">脏读</span>、<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">不可重复读</span>、<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">幻读</span>的问题。

各个数据库厂商对<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">SQL</span>的支持都不能一样。比如MySQL在<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">REPEATABLE READ</span>隔离级别上就已经解决了<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">幻读</span>问题。

2.4 并发问题的解决方案

怎么解决<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">脏读</span>、<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">不可重复读</span>、<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">幻读</span>这些问题呢?其实有两种可选的解决方案:

  • 方案一:读操作利用多版本并发控制(<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">MVCC</span>),写操作进行<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">加锁</span>。

    所谓的<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">MVCC</span>,就是生成一个ReadView,通过ReadView找到符合条件的记录版本(历史版本由undo日志构建)。查询语句只能<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读</span>到生成ReadView之前<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">已提交事务所做的更改</span>,在生成ReadView之前未提交的事务或者之后才开启的事务所做的更改是看不到的。而<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">写操作</span>肯定针对的是<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">最新版本的记录</span>,读记录的历史版本和改动记录的最新版本本身并不冲突,也就是采用MVCC时,<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读-写</span>操作并不冲突。

    普通的SELECT语句在READ COMMITED和REPEATABLE READ隔离级别下会使用到MVCC读取记录。
    - 在READ COMMITED隔离级别下,一个事务在执行过程中每次SELECT操作都会生成一个ReadView,ReadView的存在本身就保证了事务不可以读取未提交的事务所做的更改,也就是避免了脏读现象;
    - 在REPEATABLE READ隔离级别下,一个事务在执行过程中只有第一次执行SELECT操作才会生成一个ReadView,之后的SELECT操作都复用这个ReadView,这样也就避免了不可重复读和幻读的问题。
    
  • 方案二:读、写操作都采用<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">加锁</span>的方式。

    如果我们的一些业务场景不允许读取记录的旧版本,而是每次都必须去<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读取记录的最新版本</span>。比如,在银行存款的事务中,你需要先把账户的余额读出来,然后将其加上本次存款的数额,最后再写到数据库中。在将账户余额读取出来后,就不想让别的事务再访问改余额,直到本次存款事务执行完成,其他事务才可以访问账户的余额。这样在读取记录的时候就需要对其进行<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">加锁</span>操作,这样也就意味这<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读</span>操作和<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">写</span>操作也像<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">写-写</span>操作那样<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">排队执行</span>。

    <span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">脏读</span>的产生原因是因为当前事务读取了另外一个未提交事务写的一条记录,如果另一个事务在写记录的时候就给这条记录加锁,那么当前事务就无法继续读取该记录了,所以也就不会有脏读问题的产生了。

    <span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">不可重复读</span>的产生是因为当前事务先读取一条记录,另外一个事务对该记录做了改动并提交之后,当前事务再次读取时会获得不同的值,如果在当前事务读取记录时就该该记录加锁,name另一个事务就无法修改该记录,自然也不会发生不可重复读了。

    <span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">幻写</span>问题的产生是因为当前事务读取了一个范围的记录,然后另外的事务向该范围插入了新记录,当前事务再次读取该范围的记录时发现了新插入的新纪录。采用加锁的方式解决了幻读问题就有一些麻烦,因为当前事务在第一次读取记录时幻读的记录并不存在,所以读取的时候加锁不知道锁那个记录。

  • 对比:

    • 采用<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">MVCC</span>方式的话,<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读-写</span>操作批次并不冲突,<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">性能更高</span>。
    • 采用<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">加锁</span>方式的话,<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读-写</span>操作彼此需要<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">排队执行</span>,影响性能。

    一般情况下我们愿意采用<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">MVCC</span>来解决<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">读-写</span>操作并发执行的问题,但是业务在某些特殊情况下,要求必须在<span style="color:#a27e22;background:#e9e9e9;font-size:16px;font-family:Helvetica;">加锁</span>的方式执行。

相关文章

  • tiledlayout 或 subplot

    2022-09-17 您可以使用 tiledlayout 或 subplot 在同一窗口的不同部分显示多个绘图。 ...

  • 写给自己的感恩信

    --蓉儿写于 2022-09-17 00:37:17 致亲爱的自己: 来到28天好妈妈训练营,...

  • 第665篇|岁月守候III-5(/2022/09/17-2022

    ❁/岁月守候III-5(/2022/09/17-2022/09/23) 2022-09-17,星期六,晴。今天上午...

  • 暖宝语录

    宝宝语录2022-09-17: 1、宝宝:妈妈你会给别人做零食吗? 妈妈:妈妈只给你做零食 宝宝:那让别人哭死吧 ...

  • 0320|因为在此刻被看见

    2022-09-17 北京 晴天 有点小雾霾 关于会议时间的问题 周六早晨的恐惧实验室,7点是有点早,8点是不是更...

  • 晨读文言文(一)-初至天目双清庄记

    2022-09-17 初至天目双清庄记 数日阴雨,苦甚,至双清庄,天稍霁。庄在山脚,诸僧留宿庄中,僧房甚精。溪流激...

  • 痛苦:有“痛”一定会“苦”吗?

    原创精进学思行精进学思行2022-09-17 14:01发表于上海 你有过痛苦的感受吗?你还记得最近一次什么时候吗...

  • 2022-09-17

    今天虽然是休班,但是感觉过得太快了,早上起的可能有些晚了,大概9点多起来了,然后一天也没觉得干什么睁眼睛就到时候下...

  • 2022-09-17

    1.#加油高中生#早早的起床,这可不敢偷懒,赶紧给孩子端了羊肉烙了火烧。不辞千米去送吃的。没想到在接赫尔的时候,发...

  • 2022-09-17

    穷归穷,不穷讲究的才是真讲究。 越是花里胡哨的场面往往越吃钱,效用几何,就不好说了。 停杯投箸不能食,拔剑四顾心茫...

网友评论

      本文标题:2022-09-17

      本文链接:https://www.haomeiwen.com/subject/fexyortx.html