MySQL事务

事务

事务是多条DML语句组成为了达到某一特地的任务。

一个完整的事务,需要满足四个属性:

  1. 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  2. 一致性:在事务开始之前和事务结束之后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度,串联性以及后续数据库可以自发地完成预定的工作。
  3. 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(read uncommitted),读提交(read committed),可重复读(repeatable read)和串行化(Serializable)
  4. 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
    简称ACID

原子性(Atomicity,或称不可分割性)

一致性(Consistency)

隔离性(Isolation,又称独立性)

持久性(Durability)

事务提交方式

  • 手动
  • 自动
sql 复制代码
show variables like 'autocommit';    #查看自动提交
set autocommit=0;   #关闭
set autocommit=1;   #打开

启动事务

sql 复制代码
start transaction;    #启动
savepoint s1;    #设置保存点s1
rollback to s1;     #回滚到s1
commit;     #提交结束掉事务
begin;     #启动事务

如果没有设置保持点rollback会回到最初的状态。

commit之后就无法rollback

  • 异常退出事务会自动回滚
  • 自动提交不会影响手动的提交
  • autocommit会影响单sql语句
  • 对于InnoDB单sql也是事务,自动提交

隔离性

数据库中为了保证事务执行过程中尽量不受干扰,就有了隔离性

隔离级别

  • 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
  • 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
  • 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。默认级别
  • 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)

查看与设置隔离性

sql 复制代码
select @@global.tx_isolation;    #查看全局隔离级别
select @@session.tx_isolation;   #查看会话(当前)隔离级别
select @@tx_isolation;		#查看会话(当前)隔离级别
set session transaction isolation level read committed;  #设置会话隔离级别
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ 
COMMITTED | REPEATABLE READ | SERIALIZABLE}

如果global和session不一样默认使用session

读未提交:一个正在执行的事务只要插入了没有commit另一个事务就能看到数据,这种现象叫做脏读

读提交:不可重复读,一个读的事务可能会出现重复的数据

可重复读:只有退出mysql重新登录进入事务才能看到修改的内容

串行化:数据库并发性能低,加锁

隔离性更深的理解

读写并发

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

三个前置知识:

  • 3个隐藏字段
  • undo 日志
  • read view
    三个隐藏列字段
  • DB_TRX_ID:6byte,最近修改(修改/插入)事务ID,记录创建这条记录/最后一次修改该记录的事务ID
  • DB_ROLL_PTR:7byte,回滚指针,指向这条记录的上一个版本(简单理解成,指向历史版本就行,这些数据一般在 undo log 中)
  • DB_ROW_ID:6byte,隐含的自增ID(隐藏主键),如果数据表没有主键,InonoDB会自动以DB_ROW_ID产生一个聚簇索引
  • 补充:实际上还有一个删除flag隐藏字段,既记录被更新或删除并不代表真的删除,而是删除flag遍历

undo log

简单理解成,就是MySQL中的一段内存缓存区,用来保存日志数据的就行。

read view

read view是事务可见性的一个类,不是事务创建出来,就会有read view.而是当这个事务(以及存在),首次进行快照读的时候,mysql形成read view

  1. 每个事务都要有自己的事务ID,可以根据事务ID的大小,来决定事务到来的先后顺序
  2. mysql可能会面临处理多个事务的情况,事务也有自己的生命周期,mysqld要对多个事务进行管理,先描述,后组织。事务也有自己的结构体。
相关推荐
名字还没想好☜1 小时前
Go 的 database/sql 连接池实战:SetMaxOpenConns 怎么配、连接泄漏怎么查
数据库·sql·golang·go·数据库连接池
大眼、不聚光1 小时前
2.oracle--表空间管理
数据库·oracle
字节跳动数据库1 小时前
火山 PostgreSQL Serverless × 飞书妙搭:把 AI 装进数据库,一句话唤醒数据智能
数据库·人工智能·后端
玛丽莲茼蒿2 小时前
Redis(六)—— Redis高级
数据库·redis·缓存
Wang's Blog2 小时前
PostgreSQL笔记22: WAL日志与崩溃恢复原理
数据库·笔记·postgresql
陈聪.3 小时前
企业级 NoSQL 数据库 Redis 核心知识整理
数据库·redis·nosql
翼龙云_cloud3 小时前
腾讯云国际代理商:CDB数据库自动备份和异地灾备配置 从快照到跨区域恢复
运维·数据库·云计算·腾讯云
小屁孩你滑稽掉了3 小时前
prisma操作数据库的方法使用教程(简洁版)
数据库·node.js·prisma·fastify
l1t3 小时前
利用DuckDB luajit插件和openblas库对表中数据做矩阵运算
数据库·线性代数·矩阵·duckdb