[C/C++后端开发学习]18 Mysql事务原理

本文详细介绍了MySQL中事务的基本概念,包括ACID特性(原子性、一致性、隔离性、持久性)以及事务并发异常。重点讨论了事务的隔离级别,如READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE,并分析了它们之间的区别和应用场景。此外,还深入探讨了事务隔离性的实现,包括锁的类型(共享锁、排他锁、意向锁等)以及MVCC(多版本并发控制)机制,以及事务持久性的实现——redo log。
摘要由CSDN通过智能技术生成

1 事务基本概念

事务将数据库从一种一致性状态转换为另一种一致性状态。它是访问并更新数据库各种数据项的一个程序执行单元,可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成。

简而言之,在数据库提交事务时,可以确保要么所有修改都已经保存,要么所有修改都不保存。

在 MySQL InnoDB 下,每一条语句默认都是事务。可以通过set autocommit = 0;设置当前会话手动提交。

ACID特性

原子性(A)

事务操作要么都做(提交),要么都不做(回滚)。

事务的回滚的通过undolog来实现的。undolog记录的是事务每步具体操作,当回滚时,执行事务具体操作的逆运算。

一致性(C)

在事务执行前后,数据库的完整性约束没有被破坏。一致性由原子性、隔离性以及持久性共同来维护的。

例如:一个表的姓名是唯一键,如果一个事务对姓名进行修改,但是在事务提交或事务回滚后,表中的姓名变得不唯一了,这样就破坏了一致性

隔离性(I)

对于同时执行的多个不同事务,其操作对象互相隔离,也就是说一个事务提交前对其他事务都不可见。这主要是通过 MVCC(多版本并发控制)和 锁来实现的。

锁用来处理并发 DML 操作。而 MVCC 实现一致性非锁定读,通过记录和获取行版本,而不是使用锁来限制读操作,从而实现高效并发读性能。

持久性(D)

事务提交后,事务DML操作将会持久化,即使发生宕机等故障,数据库也能将数据恢复。这是通过写入redolog磁盘文件来实现的,大致内容包括操作了数据的哪一个页、页偏移值以及具体数据等。

事务并发异常

在我们未对事务做优化前,事务的并发操作可能存在如下问题。

1)脏读

事务(A)可以读到另外一个事务(B)中未提交的数据,则称事务A读到了脏数据。

2)不可重复读

一个事务还未提交前,两次读同一个数据得到的结果却不一样的情况。出现这种情况说明有另一个事务提交了修改。一般而言,不可重复读的问题是可以接受的,因为读到已经提交的数据,一般不会带来很大的问题。

3)幻读

往往发生在事务中需要先读数据进行条件判断然后再进行写操作的情况。读数据后,判断条件成立,然后在执行写操作前,数据已被其他事务修改,之前读操作得到的条件已经不满足,导致后续写操作失败或错误。也就是说读了个”寂寞“。
例如:对于一个以name为唯一索引的表,在一个事务中经查询得知不存在name=aaa的行记录,于是正准备执行插入name=aaa的行记录,此时另外一个事务执行了相同的插入操作,这将导致本事务的此次插入操作失败。

幻读也可以通过手动给读操作加锁来解决,但具体还需要看隔离级别。

隔离级别

引入隔离级别的目的就是为了解决上面提到的事务并发异常。

SQL标准制定了四种事务隔离级别的标准,各数据库厂商在正确性和性能之间做了妥协,并没有严格遵循这些标准。

1)READ UNCOMMITTED

所谓读未提交,即可以读到其他事务未提交的操作。该级别下读操作不加锁,写操作加排他锁,在事务提交或回滚后释放锁;

2)READ COMMITTED

读已提交,即只能读到已提交的数据,但可能出现”不可重复读“。从该级别开始支持 MVCC ,也就是提供一致性非锁定读。此时读取操作实际读取的是历史快照数据的最新版本,如果出现更新的版本,则读到的就是更新的版本了。

很多厂商(如Oracle、SQL Server)默认隔离级别就是READ COMMITTED

3)REPEATABLE READ

可重复读,可以避免”不可重复读“的问题,即事务提交前读同一个数据得到的结果总是相同的。此时执行读操作实际读到的是该事务开始时的快照版本(不是最新版本),因为事务开始时刻的那个快照版本肯定不会变,所以每次读的结果都是一样。该级别下也支持 MVCC,但如果不主动加锁仍可能出现幻读。

4)SERIALIZABLE

可串行化,即所有事务都是串行化的执行,因此是最严苛的隔离级别。可以解决上面的所有的并发异常。

不同隔离级别对比

在这里插入图片描述
MySQL InnoDB默认支持的隔离级别是REPEATABLE READ

事务控制语句

设置事务隔离级别的命令为:

-- 设置隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL REPEATABLE READ;

开始和提交事务等:

-- 显示开启事务
START TRANSACTION
-- 提交事务,并使得已对数据库做的所有修改持久化
COMMIT
-- 回滚事务,结束用户的事务,并撤销正在进行的所有未提交的修改
ROLLBACK

-- 创建一个保存点,一个事务可以有多个保存点
SAVEPOINT identifier
-- 删除一个保存点
RELEASE SAVEPOINT identifier
-- 事务回滚到保存点
ROLLBACK TO [SAVEPOINT] identifier

示例:

DROP TABLE IF EXISTS `lock_test`;
CREATE TABLE `lock_test` (
`id` INT PRIMARY KEY AUTO_INCREMENT, 
`cid` INT,
`num` INT, -- 用于测试修改
KEY(`cid`)
) ENGINE=InnoDB;	-- 建表
INSERT INTO `lock_test` (`cid`, `num`) VALUES (3, 1), (5, 2), (9, 3), (11, 4), (15, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值