Mysql隔离级别、锁与MVCC有什么用

24次阅读
没有评论

共计 2019 个字符,预计需要花费 6 分钟才能阅读完成。

这篇文章主要介绍了 Mysql 隔离级别、锁与 MVCC 有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让丸趣 TV 小编带着大家一起了解一下。

我们经常所高并发,高可用。就是从质和量来评估,任何事物都可以从这两个角度来分析。在 Mysql 数据库中,事务就是用来保证质的,MVCC 就是用来保证量的。

事务

我们使用事务来保证每一条 SQL 语句的结果执行符合我们的预期。我们说事务必须具备 ACID 特性。ACID 中的三者:原子性、一致性和持久性其实描述的都差不多,保证 SQL 执行结果的可靠性。而隔离性就比较复杂了,隔离性描述的是在并发场景下数据库的表现,但并发量并不是固定的,而不同的业务可能有不同的需求,为了使数据库能适应不同的并发场景,所以伟大的人们又定义了四种隔离级别:Read Uncommited,Read Committed (RC),Repeatable Read (RR),Serializable。随着数据库隔离级别的提高,数据的并发能力也有所下降。

隔离级别

标准隔离级别下数据库会怎么表现可参考 https://www.jb51.net/article/116477.htm,我们这里只讨论共享锁和排它锁这两概念,读加共享锁,写加排它锁:

在 RC 隔离级别下,修改数据会加排它锁,事务结束释放,其他事务不许读,解决脏读问题。(共享锁当场释放)
在 RR 隔离级别下,读数据加共享锁,事务结束释放,其他事务不许修改,解决不可重复读。(共享锁事务结束释放)

实际上都把操作串行化了。而 Mysql 对其进行了优化,一个事务读时其他事务不能写,一个事务写时其他事务不能读?我不这么干照样能解决脏读和不可重复读问题。MVCC 出现了。(这也使得问题变得越来越复杂,而不一样的地方也开始出现在 RR 隔离级别下,碰巧 Mysql 的默认隔离级别就是 RR)

MVCC

MVCC 即多版本并发控制,使用了双版本号来解决数据的隔离问题。(“create”一个版本号,“delete”一个版本号,修改操作拆分为“delete”和“create”)每个事务在开始对每张表增删改查操作时都会生成一个版本号,每个事务只能查到“create”小于本版本号和“delete”大于本版本号的数据。这样,增删查操作就完全可以并发进行了,只有修改操作是一定要排队的。这样,就算没有共享锁也解决了不可重复读问题,因为其他事务修改后,数据的版本号比我大,我不会读到。

MVCC 在 RR 隔离级别下的并发

引入 MVCC 之后,看似很美好。然而大家有没有想过两个事务先后对一条数据做更新操作,然后两个事务再读取那条数据,分别读到什么?哈哈,这根本是不可能出现的,因为修改操作是串行的,另一个事务必须先 commit 本事务才能修改。好,换个问题,两个事务先后对一条数据做 + 1 操作,另一个事务提交后,本事务再 +1,再读取那条数据,本事务是读取到 + 1 还是 + 2 的结果?如果读取到 +2,那不是破坏了隔离性,读到了其他事务提交的数据么?

然而事实确实是这样,其他事务已经提交,本事务也已修改过那条数据了,之后当然要读到 + 2 才行。虽然本来是 0,本事务明明只加了 1,可读取后却变成 2 了,有点不适应。确实,在标准的 RR 隔离级别下,因为操作都是串行的,本事务读取一行数据后,其他事务就不能修改这条数据了,这条数据永远只有本事务在操作,所以严格满足隔离性。但是 Mysql 的 RR 增强了读与写的并发,只有当两个事务同时修改一条数据需要串行,其他所有操作都可以并行。所以造成了这种结果,好像出现了不可重复读。但是这种不可重复读实际上是符合我们的直观感受的,在本事务对数据修改后,当然要读取到最新的数据。

要对其过程进行分析的话:

数据 create 版本号为 0

事务 1 版本号为 1,读取数据 value=0

事务 2 版本号为 2,修改数据 value+1=1,原数据 delete 版本号为 2,新数据 create 版本号更新为 2,commit

事务 1 修改数据 value+1=2,(由于修改是当前读,永远读取版本号最大的数据,所以读取到 value 为 1)修改后 delete 版本号为 1,

新数据 create 版本号为 1

本事务读取数据 value=2

深入分析:

其实上面的描述也是有漏洞的,如果有第三个事务版本号为 3 呢?因为版本号为 3,是不是可以直接读取事务 1、2 未提交的数据?实际上在 MVCC 中,每个事务还有一个最低可见版本 low_limit_id(事务号 = low_limit_id 的记录,对于当前事务都是不可见的),把当前正在执行还没 commit 的事务给过滤掉了。例如事务 3,虽然版本号为 3,但是 low_limit_id=1,所以事务 1 和事务 2 的修改对 3 都是不可见的。

感谢你能够认真阅读完这篇文章,希望丸趣 TV 小编分享的“Mysql 隔离级别、锁与 MVCC 有什么用”这篇文章对大家有帮助,同时也希望大家多多支持丸趣 TV,关注丸趣 TV 行业资讯频道,更多相关知识等着你来学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-04发表,共计2019字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)