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

写-写

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

相关推荐
广州智造29 分钟前
OptiStruct实例:3D实体转子分析
数据库·人工智能·算法·机器学习·数学建模·3d·性能优化
技术宝哥4 小时前
Redis(2):Redis + Lua为什么可以实现原子性
数据库·redis·lua
学地理的小胖砸5 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
dddaidai1235 小时前
Redis解析
数据库·redis·缓存
数据库幼崽5 小时前
MySQL 8.0 OCP 1Z0-908 121-130题
数据库·mysql·ocp
Amctwd6 小时前
【SQL】如何在 SQL 中统计结构化字符串的特征频率
数据库·sql
betazhou6 小时前
基于Linux环境实现Oracle goldengate远程抽取MySQL同步数据到MySQL
linux·数据库·mysql·oracle·ogg
lyrhhhhhhhh7 小时前
Spring 框架 JDBC 模板技术详解
java·数据库·spring
喝醉的小喵8 小时前
【mysql】并发 Insert 的死锁问题 第二弹
数据库·后端·mysql·死锁
付出不多8 小时前
Linux——mysql主从复制与读写分离
数据库·mysql