MySQL的事务

什么是事务?

在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是每次快照读的时候,都会更新。

写-写

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

相关推荐
诸神缄默不语20 分钟前
Java SE 与 Java EE 简介
java·数据库·java-ee·java se
AI探索先锋23 分钟前
Ubuntu 20.04下MySQL 8.4.3 LTS离线安装全攻略
linux·服务器·mysql·ubuntu
Minxinbb1 小时前
一文读懂MySQL数据类型
数据库·mysql·dba
程序员学习随笔2 小时前
PostgreSQL技术内幕22:vacuum full 和 vacuum
数据库·postgresql
sevevty-seven2 小时前
MySQL innodb中一条sql的执行流程
数据库·sql·mysql
smilejingwei2 小时前
从 SQL 到 SPL:组内查找最近的匹配记录
数据库·sql·数据分析·数据分析工具·esprocspl
步、步、为营2 小时前
解锁 C# 与 LiteDB 嵌入式 NoSQL 数据库
数据库·c#
风123456789~2 小时前
【Oracle专栏】实用SQL、查询处理
数据库·oracle
weisian1512 小时前
Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)
mysql·架构
谢泽浩2 小时前
Unity Webgl + WebAPI 之 SqlSugar根据Mysql表反向生成实体类
mysql·unity·webgl