MySQL的事务

发布于:2025-02-10 ⋅ 阅读:(37) ⋅ 点赞:(0)

在这里插入图片描述

什么是事务?

在MySQL中,事务(Transaction)是一组要么全部执行成功、要么全部不执行的SQL语句序列。事务主要用于确保数据的一致性和完整性,特别是在多个用户并发访问和修改数据库时。事务具有四个关键特性,通常称为ACID特性:

  1. 原子性(Atomicity):

    • 原子性意味着事务是一个不可分割的工作单元。事务中的所有操作要么全部完成,要么全部不执行。如果事务中的某个操作失败,那么事务中已经完成的操作必须被回滚(撤销),使数据库返回到事务开始之前的状态。
  2. 一致性(Consistency):

    • 一致性确保事务将数据库从一个一致状态转换到另一个一致状态。事务执行前后,数据库中的数据必须满足所有定义的完整性约束、触发器、级联回滚等规则。
  3. 隔离性(Isolation):

    • 隔离性保证事务并发执行时,一个事务的内部操作对其他并发事务是隔离的。这意味着一个事务的中间状态对其他事务是不可见的,除非该事务已经提交。MySQL支持几种隔离级别,包括读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。
  4. 持久性(Durability):

    • 持久性确保一旦事务提交,它对数据库的影响是永久的,即使系统发生崩溃。这意味着事务一旦提交,其修改的数据必须被永久保存到数据库中,不会被丢失。

为什么要有事务?

多用户是可以并发访问数据库的,这时数据库中的数据就相当于是临界资源,这时使用者必须写一些无关的代码来保证线程安全,使用起来很麻烦。所以,事务就是该部分的封装。访问数据库时,事务能够简化编程模型。本质上事务是为应用层服务的。

MySQl中一定有大量的事务,这些事务需要被管理。
如何管理?
先描述,再组织。
事务的本质就是一个类。

事务的版本支持

在使用事务时,应确保数据库引擎支持事务。例如,InnoDB是MySQL的默认存储引擎,支持事务;而MyISAM则不支持事务。

show engines;

在这里插入图片描述

事务的提交方式

  1. 手动提交
  2. 自动动提交
  • 查看事务提交方式
    在这里插入图片描述

在这里插入图片描述

  • 修改提交方式
    在这里插入图片描述
    在这里插入图片描述

事务的常见操作

在这里插入图片描述
注意下面的操作的隔离级别都是读未提交(read uncommitted)

  • 创建测试表
create table if not exists account(
id int primary key,
name varchar(50) not null default '',
blance decimal(10,2) not null default 0.0
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;
mysql> show variables like 'autocommit'; -- 查看事务是否自

操作流程

在这里插入图片描述
commit可以理解为,结束该事务,也就是完成了整个过程,MySQL的数据此时应该是持久化,不再受该事务的影响。
在这里插入图片描述
没有commit事务出现异常,直接将表回滚到处理该事务前表的状态。

回滚rollback

在这里插入图片描述

begin与autocommit

上面的操作都是在自动提交下完成的。
为什么还需要commit来完成手动提交呢?
在这里插入图片描述
autocommit影响不了手动开始的事务。begin开始事务后,必须手动进行提交。
autocommit影响的是CURD的操作。mysql将单个SQL语句封装为了事务(包含了autocommit)。

  • 手动提交
    在这里插入图片描述
  • 自动提交
    在这里插入图片描述

结论

  • 只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关。
  • 事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为MySQL 有 MVCC )从上面的例子,我们能看到事务本身的原子性(回滚),持久性(commit)
    那么隔离性?一致性?

事务操作注意事项

  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了(commit),则不可以回退(rollback)
  • 可以选择回退到哪个保存点
  • InnoDB 支持事务, MyISAM 不支持事务
  • 开始事务可以使 start transaction 或者 begin

事务的隔离级别

理解隔离级别和隔离性

  • 事务的执行阶段可以分为三个阶段,执行前,执行中,执行后。
  • 并发的访问一个数据库的事务,在执行中会相互影响。
  • 隔离性:在事务运行中,不会相互影响
  • 隔离级别:在事务运行中,不会相互影响的程度

修改隔离级别

在这里插入图片描述
在这里插入图片描述

四种隔离级别

  • 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
    就是事务中未提交的操作后的表的内容也可被看到。
    读未提交就是没有任何进行任何隔离处理。

  • 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
    意思大致就是只能看到已经提交的事务的表。
    在这里插入图片描述
    在这里插入图片描述
    读提交也叫做不可重复读
    在这里插入图片描述
    在事务中多次读到的数据不一致,就是不可重复读。推此即彼,可重复读读到的数据是一致的。

  • 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
    在这里插入图片描述
    在这里插入图片描述
    在事务中读到的表的数据始终是一样的。

  • 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,
    从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这里插入失败是因为等待时间有点长
重新操作一遍。
在这里插入图片描述
在这里插入图片描述

总结:在上面的实验中两个事务在读取数据库时,不会阻塞,只有进行其他操作时,会阻塞,需要等待另一个进程提交才会继续执行。在这里插入图片描述
在这里插入图片描述
一致性由原子性,隔离性和持久性保证。

数据库并发的三种场景

在这里插入图片描述
这三种情况,读读没有线程安全问题,不需要处理,剩下的两种情况都有线程安全问题,但读写是占大多数的。

隔离性的原理

这里针对的主要是读写并发的情况。
MySQL数据库实现隔离性主要采用的技术是MVCC(多版本控制),这种控制是不需要锁的,也就是无锁并发控制

一些认知:
1.MySQL如何区分事务的先后–>每个事务都有一个事务ID,事务ID越小,则事务来的更早
2.MySQL要对事务进行管理—>一套对象/结构体(对事务进行建模)

3个隐藏字段

在这里插入图片描述
DB_TRX_ID:记录最近被修改的事务ID
DB_ROLL_PTR:指向上一个版本
DB_ROW_ID:在没有给表设置索引是会被使用
flag:标识该条记录是否被删除
在这里插入图片描述
上面表的更具体描述是:
在这里插入图片描述

undo log

undo log理解为MySQL中的一段内存缓冲区

理解表中数据的更新(版本更新)

1.将张三改为李四
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
2.继续,将李四的年龄改为28
在这里插入图片描述
这样表中每条记录就形成了一条版本链

3.如果删除该条记录呢?
并不是真正的删除该条记录,只需要将flag进行修改就可以了,然后将老的版本放入undo log就可以了,跟上面的步骤差不多。

当前读和快照读

当前读:就是读最新被修改的记录
快照读:就是读版本链中的某一个版本,读哪一个版本取决于隔离级别。

如何使不同的事务看到不同的内容?如何实现隔离级别的呢?

通过Read View来实现的。
Read View是判断事务可见性的一个类,不是事务被创建出来后,就接着创建Read View,只有在进行快照读的时候,才会创建Read View

Read View

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
源代码:
在这里插入图片描述

可重复读(RR)和不可重复读(RC)的本质区别

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
可以读到被提交的内容
在这里插入图片描述
在这里插入图片描述
在提交之前读
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • Read View形成的时机(首次快照读的时候)不同可能影响快照读的结果。
  • RR 的Read View是一旦创建就不会改变。
  • RC的Read View是每次快照读的时候,都会更新。

写-写

直接理解为当前读就可以。


网站公告

今日签到

点亮在社区的每一天
去签到