关于Mysql隔离级别、锁与MVCC介绍
作者:laozhang 发布时间:2024-01-16 04:28:26
本文意在弄清楚这些概念间的关系及其作用。弄清Mysql在开启事务的情况下,每条sql执行时的加锁操作和MVCC版本控制。为使讨论简单,本文忽略了GAP锁(间隙锁、范围锁)。
我们经常所高并发,高可用。就是从质和量来评估,任何事物都可以从这两个角度来分析。在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都是不可见的。
总结
为了解决隔离性问题,都没有使用完全copy数据这种笨方法。传统数据库使用共享锁和排它锁使读写操作串行;Mysql使用MVCC和排它锁,读写可并行。Mysql在RR隔离级别以下,和传统方式表现一致,在RR隔离级别,和传统方式有差异,体现在本事务更新某条数据后,能读取到其他事务对该条数据已提交的修改。
来源:https://www.cnblogs.com/jieqing/p/8328074.html
猜你喜欢
- 刚开始使用django,在创建第一个app时被提示不知道命令runserver,百度得出是环境变量的问题。1、配置python变量环境,C:
- 一、变量和表达式>>> 1 + 1 &n
- SQLSRV驱动程序允许您创建一个结果集,其中包含可以根据游标类型以任何顺序访问的行。本主题将讨论客户端(缓冲)和服务器端(非缓冲)游标及其
- JavaScript组件打包模式js组件通常带着css image ,但这样使用起来可能会有些小麻烦,为了让组件足够的solo,有了把css
- 一.python实现ping返回延迟繁琐版#!/usr/bin/python3.7# !coding:utf-8__author__ = &
- 1. 创建主窗口上文中我们建立的图形界面程序 GUIdemo2.py,通过导入图形界面 uiDemo1.py,已经实现了主窗口的创建。1.1
- 在我们学习的过程中会遇到这么样的问题,就是在我们学习的过程中会发现需要分页处理,这里呢,给大家介绍书上说的分页。@app.route(
- 1.if ...else ...判断进行断言from time import *from selenium import webdriver
- 问题:如何经过convTransposed1d输出指定大小的特征?import torchfrom torch import nnimpor
- 一、打开命令提示符方法一:window+R键 ——输入cmd方法二:在此搜索cmd进入命令提示符二、
- 本文实例讲述了php+mysqli使用面向对象方式更新数据库的方法,分享给大家供大家参考。具体实现方法如下:<?php//第一步:创建
- 在这个自动化时代,我们有很多重复无聊的工作要做。 想想这些你不再需要一次又一次地做的无聊的事情,让它自动化,让你的生活更轻松。 那么在本文中
- Labelme简要介绍通过labelme对图进行标注后,得到的是json文件,而Yolov5对数据进行模型构建的时候,读取需要的是txt格式
- 简介深度学习需要熟悉使用一个框架,本人选择了TensorFlow,一边学习一边做项目,下面简要介绍TensorFlow中的基本常量、变量和运
- 在python中读取csv文件时,一般操作如下:import pandas as pdpd.read_csv(filename)该读文件方式
- 前言Yolov5比较Yolov4,Yolov3等其他识别框架,速度快,代码结构简单,识别效率高,对硬件要求比较低。这篇博客针对Python+
- 本文实例讲述了python使用opencv实现马赛克效果。分享给大家供大家参考,具体如下:最近要实现opencv视频打马赛克,在网上找了一下
- 源码:#路飞骷髅import turtle as t#黄底帽子t.pu()t.goto(0,200)t.circle(-130,-80)t.
- 本文为大家分享了python操作excel的包,供大家参考,具体内容如下现在支持python操作excel的包有下列这些官网上最推荐的是op
- 前言之前一直认为UTF-8是万能的字符集问题解决方案,直到最近遇到这个问题。最近在做新浪微博的爬虫, 在存库的时候发现只要保持emoji表情