MySQL:事务


1.什么是事务

事务就是由一条或者多条SQL共同组成的一个集合体,这个集合体需要共同完成某个任务,这就是事务!!!

**假设一种场景:**你毕业了, 学校的教务系统后台 MySQL 中,不在需要你的数据,要删除你的所有信息(一般不会:) ), 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表 现,甚至你在论坛发过的文章等。这样,就需要多条MySQL 语句构成,那么所有这些操作合起来,就构 成了一个事务。

在这里插入图片描述

事务被 MySQL编写者设计出来,本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的.而不是伴随着数据库系统天生就有的.

2.事务的操作

2.1 查看数据库引擎

在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM 不支持。

mysql> show engines \G -- 行显示,查看数据库引擎
*************************** 1. row ***************************
Engine: InnoDB -- 引擎名称
Support: DEFAULT -- 默认引擎
Comment: Supports transactions, row-level locking, and foreign keys -- 描述
Transactions: YES -- 支持事务
XA: YES
Savepoints: YES -- 支持事务保存点
*************************** 2. row ***************************
..............
..............
..............
..............

2.2 事务的提交方式

在这里插入图片描述

2.3 事务的开始、保存、回滚与提交(结束)

①正常演示 - 证明事务的开始与回滚:
在这里插入图片描述
commit后这个数据就永久存在了!!!commit后无法回滚了!!!!!!!!!!!!!!!

②非正常演示1 - 证明未commit,客户端崩溃,MySQL自动会回滚(隔离级别设置为读未提交)
在这里插入图片描述
在这里插入图片描述

③非正常演示2 - 证明单条 SQL 与事务的关系
在这里插入图片描述

在这里插入图片描述

3.事务隔离级别

在多个事务各自执行多个SQL的时候,就还是有可能会出现互相影响的情况。比如:多个事务同时访问同一张表,甚至同一行数据。

就如同你妈妈给你说:你要么别学,要学就学到最好。至于你怎么学,中间有什么困难,你妈妈不关心。那么你的学习,对你妈妈来讲,就是原子的。那么你学习过程中,很容易受别人干扰,此时,就需要将你的学习隔离开,保证你的学习环境是健康的。

数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性
数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

在这里插入图片描述
隔离级别如何实现:隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的。常见有,表锁,行锁,读锁,写锁,间隙锁(GAP),Next-Key锁(GAP+行锁)等。不过,我们目前现有这个认识就行,先关注上层使用。

3.1 查看与设置隔离性(读未提交、读提交、可重复读、串行化)

设置当前会话 or 全局隔离级别语法

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
例:set session transaction isolation level serializable; -- 串行化

在这里插入图片描述
特别不建议大家随便改隔离级别!!!
提示:如果没有现象,关闭mysql客户端,重新连接。

①读未提交【Read Uncommitted】:几乎没有加锁,虽然效率高,但是问题太多,严重不建议采用。我这边增删查改,只要稍微一动(哪怕只改了一条语句),别人就都可以看见!一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读。
②读提交【Read Committed】:我这边增删查改,只要没有commit,别人就都看不见!但是它也有一个问题,就是查看放在一个事务期间,用同样的语句可能会查看到不同的结果(增删查改那边commit提交之前和之后)!这种现象叫做不可重复读
在这里插入图片描述
③可重复读【Repeatable Read】:那么这个就不需要我多说了吧,由上面的铺垫,大家应该知道这个可重复读是个什么操作了!MySQL的默认隔离级别就是这个!!
在这里插入图片描述
提示:一般的数据库在可重复读情况的时候,无法屏蔽其他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读。
④串行化【serializable】:串行化就是一个一个执行事务(注意是事务不是SQL语句),当一个事务,没有执行完的时候,其他事务就会被阻塞。所以串行化效率很低!
在这里插入图片描述

在这里插入图片描述

3.2 事务一致性

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。

其实一致性和用户的业务逻辑强相关,一般MySQL提供技术支持,但是一致性还是要用户业务逻辑做支撑,也就是,一致性,是由用户决定的。

而技术上,通过AID(原子性、持久性、隔离性)保证C(一致性)

4.事务隔离性

数据库并发的场景有三种:
①读-读 :不存在任何问题,也不需要并发控制
②读-写 :有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
③写-写 :有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失

读-读和写-写不做讨论,

4.1 读-写

多版本并发控制( MVCC )是一种用来解决 读-写冲突 的无锁并发控制

为事务分配单向增长的事务ID,为每个修改保存一个版本,版本与事务ID关联,读操作只读该事务开始 前的数据库的快照。 所以 MVCC可以为数据库解决以下问题

①在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能
②同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

理解多版本并发控制(MVCC) 需要知道三个前提知识:
①3个记录隐藏字段
②undo 日志
③Read View 读视图

3个记录隐藏字段:
在这里插入图片描述
undo日志:
在这里插入图片描述
上面的一个一个版本,我们可以称之为一个一个的快照。但是如果提交(commit)了,那么日志就被清理掉了。

Q: select读取,是读取最新的版本呢?还是读取历史版本?
①当前读:读取最新的记录,就是当前读。增删改,都叫做当前读,select也有可能当前读,比如:select lock in share mode(共享锁), select for update
②快照读:读取历史版本(一般而言),就叫做快照读。

我们可以看到,在多个事务同时删改查的时候,都是当前读,是要加锁的。那同时有select过来,如果也要读
取最新版(当前读),那么也就需要加锁,这就是串行化。
但如果是快照读,读取历史版本的话,是不受加锁限制的。也就是可以并行执行!换言之,提高了效率,即
多版本并发控制(MVCC)的意义所在。

Read View 读视图:
Read View 在 MySQL 源码中,就是一个类,本质是用来进行可见性判断的。 即当我们某个事务执行快照读的时候,对该记录创建一个 Read View 读视图,把它比作条件,用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的 undo log 里面的某个版本的数据。

m_ids; //一张列表,用来维护Read View生成时刻,系统正活跃的事务ID

up_limit_id; //记录m_ids列表中事务ID最小的ID(没有写错)

low_limit_id; //ReadView生成时刻系统尚未分配的下一个事务ID,也就是目前已出现过的事务ID的最大值+1(也没有写错)

creator_trx_id //创建该ReadView的事务ID

在这里插入图片描述
提示:read view 是事务可见性的一个类,不是事务创建出来就会有read view,而是当这个事务已经存在,首次进行快照读的时候,mysql形成read view!
在这里插入图片描述

4.2 RR(可重复读)和RC(读提交)的本质区别

正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同
在这里插入图片描述

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chris·Bosh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值