文章目录
1. 事务
1.1 概念
事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,在MySQL中,默认一条语句就是一个事务单元,除非关闭事务自动提交。
存储引擎:mysql中的数据通过何种技术存储在文件(或内存)中,通过show engines查看mysql支持的引擎,innodb支持事务。
1.2 ACID属性
事务满足以下四个属性:
- 原子性(Atomicity):事务是一个不可分割的工作单位,要么做完要么不做
- 一致性(Consistency):事务必须使数据库从一个一致性状态变化到另一个一致性状态:
- 隔离性(isolation):一个事务的执行不能被其他事务干扰,并发的各个事务之间不能互相干扰
- 持久性(Durability):一个事务一旦被提交,它对数据库中数据的改变是永久性的。
1.3. 隔离级别
当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:
-
脏读:两个事务T1读取了已被T2更新但还没有提交的字段,之后若T2回滚,则T1读取的内容是临时且无效的
-
不可重复读:T1读取一个字段,T2更新该字段,T1再读同一字段,值就不同了
-
幻读:T1从表中读取了一个字段,T2插入新行,T1再读同一个表则多出几行了
为了解决上面三种问题,数据库MySQL为我们提供了四种隔离级别:
-
READ UNCOMMITETD(读未提交数据,最低隔离级别);
-
READ COMMITTED(读已提交数据,可避免脏读);
-
REPEATABLE READ(可重复读,默认,可避免脏读不可重复读);
-
SERIALIZABLE(串行化,均可避免);
select @@tx_isolation #查看当前的隔离级别:
set session/globals transaction isolation level XXXXXX; # 更改隔离级别:
savepoint 节点名 # 设置保存点
rollback 保存点名 # 回滚到保存点
1.3. 演示事务的使用步骤
- 隐式事务:事务没有明显的开启和结束标记,如insert,update,delete语句
- 显式事务:事务具有明显的开启和结束标记 前提:必须先设置自动提交功能为禁用
- 步骤1:开启事务 set autocommit=0;start transaction;(可选的)
- 步骤2:编写事务中的sql语句 (select insert update delete )
- 步骤3:提交事务 commit;提交事务 rollback;回滚事务
一般步骤
BEGIN;
UPDATE student SET Sdept = "2222222222" WHERE Sno = 1;
UPDATE student SET Sdept = "2222222222" WHERE Sno = 2;
COMMIT;
1.5 redo log保证事务的持久性
MySQL的innoDB存储引擎,使用Redo log保证了事务的持久性。当事务提交时,必须先将事务的所有日志写入日志文件进行持久化,就是我们常说的WAL(write ahead log)机制。这样才能保证断电或宕机等情况发生后,已提交的事务不会丢失,这个能力称为 crash-safe。
MySQL中有三种日志,分别是
- redo log 是 存储引擎层(innodb)生成的物理日志,主要为了保证数据的可靠性;
- bin log 是 MySQL 数据库层面上生成的日志,主要用于 point in time 恢复和主从复制。
- undo log 主要用于事务的回滚(undo log 记录的是每个修改操作的逆操作) 和 一致性非锁定读
redo log 和 undo log 都是存储引擎层面上生成的日志,并且都记录了数据的修改:只不过 redo log记录的是"物理级别"上的页修改操作,比如页号xxx、偏移量yyy写入了’zzz’数据;而undo log 记录的是逻辑操作日志,比如对某一行数据进行了INSERT语句操作,那么 undo log就记录一条与之相反的DELETE操作。
MySQL作为一个存储系统,为了保证数据的可靠性,最终得落盘。但是,又为了数据写入的速度,需要引入基于内存的"缓冲池"。其实不止MySQL,这种引入缓冲来解决速度问题的思想无处不在。既然数据是先缓存在缓冲池中,然后再以某种方式刷新到磁盘,那么就存在因宕机导致的缓冲池中的数据丢失,为了解决这种情况下的数据丢失问题,引入了redo log。在其他存储系统,比如Elasticsearch中,也有类似的机制,叫translog。
执行流程:
1、执行器先从引擎中找到数据,如果在内存中直接返回,如果不在内存中,查询后返回