[MySQL]并发执行事物的时候, 都发生了什么?

1. 目标

        本篇文章最终目标是要熟悉MySQL中事物的四大基本特性(特别是隔离性), 再由事物的隔离性引出在并发这个行为中, 执行事物所出现的几个最主要, 最常见的问题, 同时也引出了在MySQL等的数据库中自带的解决办法.

2. MySQL中事物的四大基本特性

2.1 原子性

        原子性其实是事物最核心的特性. 在事物存在之前, 就银行的转账系统来说, A和B的账户里都是有20, 当A向B转账10, 这时候在数据库中, A的账户余额要先减10, 然后B的账户余额再加10. 正常来说, 这种情况是没毛病的, 但是可能会发生这样一种情况: 当A减10与B加10之间的这一小段时间里面, 机器突然发生宕机, 那么当机器恢复后就会发现 — A中无缘无故少了10, 而B中却一点也没有增加, 针对这样的情况, 数据库中也就引入了事物这个概念.
        事物会把上面这两步操作视为是一个整体, 当其中一方发生异常的时候, 就会回滚(rollback)到执行整体操作. 形如这样把一些操作视为一个密不可分的整体, 我们就称其为事物的"原子性"(因为原子在之前是最小的单位, 象征着密不可分的含义), 这也是事物中最核心的特性.

2.2 一致性

        比如我们在进行数据库提交操作的时候, 经常就会使用到事物, 这样能够保证数据是一致的, 不会出现纰漏等情况.

2.3 持久性

        事物进行的操作都是会写(存储到)磁盘的, 事物一旦提交成功, 造成的修改, 那就是持久化保存的了, 即使对主机重新启动, 也是存在的, 所以说对数据库的改变是永久的, 很好地就体现了持久性.

2.4 隔离性

        数据库中, 在多个事物进行并发执行的时候, 就会产生这种隔离性. 所谓的并发, 就是在多个事物同时执行的时候, 它们彼此之间是会相互产生影响的, 可能会导致执行结果不准确, 甚至是崩溃… 这个时候, 事物的隔离性就会体现出来了, 它的目标就是要阻止多个事物并发执行, 将多个事物之间的影响降低.

3. 并发执行事物出现的问题及解决方案

3.1 什么是并发行为

        上面简单介绍过了, 并发就是在多个事物同时执行的时候, 彼此之间相互产生影响的过程. 虽然上面说, 并发的执行可能会导致数据的不准确现象, 但是并发过程中的效率是非常高的, 实际开发中, 并发是很经常用到的. 总的来说, 并发这种行为是提高执行的效率, 降低数据的准确性的行为.
        其中, 多线程的执行是一种并发的行为, 多客户端来执行事物也是一种并发行为. 本篇文章我们讨论的就是第二种情况.

3.2 并发执行事物出现的问题

3.2.1 问题一: 脏读问题

        一个事物A在执行的过程中, 对其中的一系列数据进行修改, 并且在完成这个事物A(或者提交)之前, 如果有另外一些事物B恰好正在读取这些还没被修改的数据, 由于这些事物B所读取到的数据都是一些临时数据, 与最终事物A完成(或者提交)之后的数据是不一定匹配的(有可能在这些事物B读取完成之后, 事物A可能重新对之前的内容进行了修改). 这样的话, 这些事物B所读到的数据就是脏数据, 类似这种行为就叫做"脏读".

    问题一解决方案:
        我们可以规定说, 在事物A对数据进行修改的时候, 其他一些事物B不能尝试去读取其中的数据, 必须等到事物A完成(或者提交)之后, 才能有权限去访问.
        类似这种操作, 我们就称为"给读操作加锁"操作. 控制其只有在事物A完成后再进行读取数据. 降低了并发程度, 效率降低, 但是隔离性提高了.

3.2.2 问题二: 重复读问题

        当解决了问题一中的脏读问题之后, 虽然规定了在事物对数据修改的过程中其他事物不可以进行读操作, 但是如果出现有一种情况: 当事物A完成(或者提交)了之后, 其他事物B在执行的过程中, 事物A又对其数据进行一次修改, 这时候如果这些事物B再执行的话, 前后两次读取到的数据是会不一样的, 进而导致数据不准确. 类似这种行为就叫做"重复读".

    问题二解决方案:
        由于是在其他事物B执行的时候, 事物A进行修改操作, 导致其他事物B两次读取到数据是不对等的, 这时候我们就可以考虑限制事物A在其他事物B执行的过程中, 不能对其中的这些数据进行修改, 进一步地保证了不会出现重复的现象.
        类似这种操作, 我们就称为"不可重复读操作"操作. 控制了事物A在其他事物B执行的过程中, 不能对其中的数据进行修改操作. 又一次降低了并发程度, 效率再次降低, 但是隔离性得到进一步提高.
        对比"脏读问题"和"重复读问题": "脏读问题"是事物A对数据进行修改的时候, 其他事物B执行所产生问题的过程. 而"重复读问题"是其他事物B在执行的过程中, 事物A对数据进行修改所产生问题的过程.

3.2.3 问题三: 幻读问题

        解决了问题一和问题二带来的问题后, 我们保证了在事物A进行修改数据的时候, 其他事物B不能执行, 同时也保证了在这些事物B执行的过程中, 事物A不能修改其对应的数据. 但是如果有一种情况: 在这些事物B执行的过程中, 事物A对数据进行修改, 但是是没有直接修改这些事物B读取的数据的, 虽然这些事物B读取的最终结果可能没有产生影响, 但是还是会影响到这些事物B读取的结果集, 使得这些事物B两次读取到的结果集是不一样的, 进而导致数据不准确.

    问题三解决方案:
        其实从本质上来说, "幻读问题"是"重复读问题"的一种特殊情况, 我们的解决办法还是和"重复读问题"的解决办法是类似的, 那就是限制事物A在其他事物B执行的过程中, 不进行任何修改操作, 这样就可以完美地保证了不会出现重复的现象.
        类似这种操作, 我们称为"不可幻读"操作. 控制了事物A在其他事物B执行的过程中, 不能对其中的数据进行任何修改操作. 达到隔离性最高, 数据准确性最好的效果, 但是相对应的, 并发程度也会变成最低, 执行效率变得最低.

3.3 总结

        总的来说, 并发与隔离这两种东西相当于是死对头了, 它们往往都是相悖的.
        上面的三个并发执行事物出现的问题是逐渐递进的, 可分为四个"档位", 分别是: (1) 什么都不加以限制 — 这种情况并发程度最高, 隔离性最低; (2) 给读操作加锁操作 — 这种情况并发能力下降一些, 隔离性进一步增加; (3) 不可重复读操作操作 — 这种情况并发能力又进一步下降, 隔离性进一步增加; (4) 不可幻读操作 — 这种情况并发程度最低, 隔离性最高.
        我们在实际开发的过程中, 需要根据实际的场景来去合理地选择上面的档位, 就比如说, 当一些涉及到转账(钱相关)的操作, 就必须使用隔离性最高的操作, 保证数据最为准确; 当一些只是计算观看人数(或者播放量)的操作, 就可以使用并发程度最高的操作, 提高执行效率, 大大降低执行成本.

4. MySQL数据库对应的解决方法

        我们前面知道了并行执行事物出现的各种问题以及对应的解决办法, 那么在MySQL中究竟是如何实现这些解决办法的?
        同样的, MySQL提供了四个"档位"来对应上面说到的四个"档位":
        (1) read uncommitted — 并发能力最强, 隔离性最弱.
        (2) read committed — 解决了"脏读问题", 并发能力下降一些, 隔离性进一步增加.
        (3) repeatable read — 解决了"重复读问题", 并发能力又进一步下降, 隔离性进一步增加.
        (4) serializable — 解决了"幻读问题", 并发能力最弱, 隔离性最强.
        针对不同场景, 我们对MySQL提供的这四个"档位"进行选择, 并在配置文件my.ini中修改数据库的隔离级别. my.ini这个文件也就是之前我们修改默认编码所用到的文件, 还不知道怎么找到这个文件的小伙伴可以看看这篇文章: 对初学MySQL小伙伴的建议(强烈推荐~ 不看后悔~~).
        在my.ini文件里面加上下面这行命令即可指定隔离级别:

#可选参数有:read-uncommitted, read-committed, repeatable-read, serializable.
[mysqld]
transaction-isolation = repeatable-read

        在MySQL中, 默认的隔离级别是repeatable-read, 这也是全局默认的.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡欣致

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值