事务和MVCC

事务是数据库保持一致性的关键机制,具备ACID特性。MySQL的InnoDB存储引擎支持四种隔离级别,包括READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ(解决脏读和不可重复读问题,InnoDB通过MVCC在此级别下避免幻读)和SERIALIZABLE。MVCC通过保存数据的多个版本来提高并发性能,适用于REPEATABLE READ和READ COMMITTED隔离级别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、SQL事务

事务是确保数据库一致的机制,尤其是发生错误或者服务器崩溃的情况下确保数据库一致的机制。

事务的特性:ACID, 即原子性、一致性、隔离性、持久性

原子性:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其

中的一部分操作,这就是事务的原子性。

一致性:数据库总是从一个一致性的状态转换到另外一个一致性的状态。

隔离性:通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。 

持久性:一旦事务提交,则其所做的修改就会永久保存到数据库中。

 

隔离级别:在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。(每种存储引擎实现的隔离级别不尽相同)。

四种隔离级别:

READ UNCOMMITTED(未提交读):在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读。

READ COMMITTED(T提交读):大多数数据库系统的默认隔离级别是READ COMMITTED(但mysql不是)。一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读,因为两次执行同样的查询,可能会得到不一样的结果。

REPEATABLE READ(可重复读):REPEATABLE READ 解决了脏读的问题,该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的纪录,当之前的事务再次读取该范围的记录时,会产生幻行。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。可重复读是MYSQL的默认隔离级别。

SERIALIZABLE(可串行化):SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。

 

隔离级别

脏读可能性

不可重复读可能性

幻读可能性

加锁读

RU

Y

Y

Y

N

RC

N

Y

Y

N

RR

N

N

Y

N

S

N

N

N

Y

 

二、MySQL中的事务

MySQL提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster。另外还有一些第三方存储引擎也支持事务,比较知名的包括XtraDB 和 PBXT。

MySQL能够识别所有的4个ANSI隔离级别,InnoDB引擎也支持所有的隔离级别。MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。

       事务处理语句

      (1)查询mysql事务隔离级别

           1、查看当前会话隔离级别              select  @@tx_isolation;

           2、查看系统当前隔离级别              select  @@global.tx_isolation;

           3、设置当前会话隔离级别              set session transaction isolation level repeatable read;

           4、设置系统当前隔离级别              set global transaction isolation  level repeatable read;

           5、命令行,开始事务时                 set autocommit=0; 或者start transaction; 或者 begin;

      (2)MySQL事务处理只要有两种方法

      1、用BEGIN(或START TRANSACTION),ROLLBACK,COMMIT来实现

  •              BEGIN开始一个事务

  •              ROLLBACK事务回滚

  •              COMMIT事务确认

      2、直接用SET来改变MySQL的自动提交模式:

  •       SET AUTOCOMMIT=0   禁止自动提交

  •       SET AUTOCOMMIT=1   开启自动提交

  •       ROLLBACK事务回滚

  •       COMMIT事务确认

      3、两种方式的区别: 如果只是对某些语句需要进行事务控制,则使用 START TRANSACTION 语句开始一个事务比较方便,这样事务结束之后可以自动回到自动提交的方式,如果希望所有事务都不是自动提交的,那么通过修改 AUTOCOMMIT 来控制事务比较方便,这样不用在每个事务开始的时候再执行 START TRANSACTION 语句。

三、多版本并发控制(MVCC)

(1)MVCC定义:

    MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制(MVCC)。可以认为MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只是锁定必要的行。MVCC的实现,是通过保存数据在某个时间点的快照来实现的。

   InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。下面看一下REPEATABLE READ 隔离级别下,MVCC具体如何操作的。

    SELECT:

         Innodb会根据以下两个条件检查每行记录:

         a、Innodb只查找版本小于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。

        b、 行的删除版本号要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除。

       只有符合上述两个条件的记录,才能返回作为查询结果。

   INSERT:

        Innodb为新插入的每一行保存当前系统版本号作为行版本号。

   UPDATE:

        Innodb为插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。

  * 保存这两个额外的系统版本号,使大多数读操作都可以不用加锁,这样设计使得读数据操作很简单,性能很好,并且也能保证只会读到符合标准的行。不足之处是每行记录都需要额外的存储空间,需要做更多的检查工作,以及一些额外维护工作。

MVCC只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作。

   (2)  MVCC在不同隔离级别是怎么工作的

        1)可重复读隔离级别

         begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句事务才真正启动。如果想要马上启动一个事务,可以使用start transaction with consistent snapshot这个命令。begin/start transaction 启动方式,一致性视图是在执行第一个读语句时创建的;第二种启动方式,一致性视图是在执行start transaction with consistent snapshot时创建的。之后事务里的其他查询都共用这个一致性视图。

       对于一个事务视图来说,除了自己的更新总是可见的,是否可见有三种情况:

  • 版本未提交,不可见;

  • 版本已提交,但是是在视图创建后提交的,不可见;

  • 版本已提交,而且是在视图创建前提交的,可见。

       一致性读:事务A不论在什么时候查询,看到的这行数据的结果都是一致的,通过一致性视图读取。

       当前读:总是读取已经提交完成的最新版本。

      一致性读和当前读的应用:

          一致性读:可重复读的核心就是一致性读,因此在事务读取数据时,用的是一致性读。

          当前读: 1、事务更新数据的时候,只能用当前读,如果当前的记录的行锁被其他事务占用的话,就需要进入锁等待。2、select 语句如果加锁,也是当             前读。

         2)读提交隔离级别

           在读提交隔离级别下,start transaction with consistent snapshot的用法没有任何意义,等效于普通的start transaction。每一个语句执行前都会重新算出一个新的视图。

 

    

     

         

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值