mysql事务与锁的关系 09

一、事务的基础理论

事务是MySQL区别于NoSQL的重要特征,是保证关系型数据库数据一致性的关键技术。事务可看作是对数据库操作的基本执行单元,可能包含一个或者多个SQL语句。这些语句在执行时,要么都执行,要么都不执行。
MySQL事务包含四个特性:
原子性(Atomicity):语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的。实现主要基于undo log日志。
持久性(Durability):保证事务提交后不会因为宕机等原因导致数据丢失。实现主要基于redolog日志。
隔离性(Isolation):保证事务执行尽可能不受其他事务影响。InnoDB默认的隔离级别是RR,RR的实现主要基于锁机制、数据的隐藏列、undo log和类next-key lock机制。
一致性(Consistency):事务追求的最终目标,一致性的实现既需要数据库层面的保障,也需要应用层面的保障。

1.事务基础语法

  1. 在 MySQL 命令行的默认设置下,事务是自动提交的,即执行了SQL 语句之后会马上执行 commit 操作,我们可以设置 set autocommit=0 来禁用当前回话的自动提交。
  2. 还可以用 begin 、start transaction 来显式的开始一个事务。
  3. commit 在默认设置下是等价于 commit work 的,表示提交事务。
  4. rollback 在默认设置下等价于 rollback work,表示事务回滚。
  5. savepoint xxx 表示定义一个保存点,在一个事务中可以有多个保存点。
  6. release savepoint xxx 表示删除一个保存点,当没有该保存点的时候执行该语句,会抛出一个异常。
  7. rollback to [savepoint] xxx 表示回滚到某个保存点。

简单操作

--查询事务自动提交状态
show variables like '%commit%';

查看事务自动提交是否开启
以下是事务自动提交修改方式:

--全局修改(全部和新开的session窗口,重启失效。永久修改,修改配置文件或8.0 set persist)
set global autocommit=0;
show global variables like 'autocommit';
--局部修改 (session窗口)
set session autocommit=0;
show global variables like 'autocommit';

事务简单操作:开启两个窗口,一个用于事务新增数据,一个用于事务提交前查询第一次,session1(窗口1)事务没有提交,session2直接查询数据session1:

--session1:
start transaction--开启事务
insert into `user` (`name`,age,sex,`status`)values('harry',222,'男',1);
--session2:
select * from `user` where name='harry';

测试结果: session2查询为空。

第二次,session1提交事务,session2等到session1提交完成后查询数据

session1:
start transaction--开启事务
insert into `user` (`name`,age,sex,`status`)values('will',222,'男',1);
commit;--提交事务
rollback;--回滚事务

session2:
select * from `user` where name='harry';

测试结果: session2有查询到数据

通过上面,我们可以感受到事务的隔离性,也就是两个事务之间并不知道对方的存在,在 MySQL 的默认隔离级别下,当一个事务还没有提交的时候,其他事务是无法感知到数据的变化的。

二、事务的生命周期

MySQL的checkpoint

checkpoint,即检查点。在undolog中写入检查点,表示在checkpoint前的事务都已经完成commit或者rollback了,也就是检查点前面的事务已经不存在数据一致性的问题了(此处暂时不会深入解释)
Innodb的事务日志是指Redo log,简称Log,保存在日志文件ib_logfile里面(去mysql数据目录下看下)。
Innodb还有另外一个日志Undo log,但Undo log是存 放在共享表空间里面的(ibdata*文件,存储的是check point日志序列号)。
事务的生命周期

三、事务重做日志与回滚日志

-- 查看事务日志 :
show engine innodb status\G;
-- 查看日志文件设置状态
show variables like 'innodb_%';

innodb_log_files_in_group:DB中设置几组事务日志,默认是2; innodb_log_group_home_dir:事务日志存放目录,不设置,ib_logfile0…存在在数据文件目录下 Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间
注意:在MySQL中对于数据来说, 最为重要的是日志文件
redo log => ib_logfile0
undo log => ibdata

1.重做日志

1.1 持久化

事务被提交,数据一定会被写入到数据库中并持久存储起来,通常来说当事务已经被提交之后,就无法再次回滚了。

1.2 重做日志实现持久化

与原子性一样,事务的持久性也是通过日志来实现的,MySQL 使用重做日志(redo log)实现事务的持久性,重做日志由两部分组成,一是内存中的重做日志缓冲区,因为重做日志缓冲区在内存中,所以它是易失的,另一个就是在磁盘上的重做日志文件,它是持久的。
事务中
当我们在一个事务中尝试对数据进行写时,它会先将数据从磁盘读入内存,并更新内存中缓存的数据,然后生成一条重做日志并写入重做日志缓存,当事务真正 提交时,MySQL 会将重做日志缓存中的内容刷新到重做日志文件,再将内存中的数据更新到磁盘上,图中的第 4、5 步就是在事务提交时执行的。

重做日志执行时间
在mysql中事务执行commit提交了之后,但是服务器挂了,数据还没有写入磁盘,在mysql重启服务之后会重新执行这个重做日志写入数据。

3.2 回滚日志

3.2.1 原子性

通俗的解释就是:一条绳子上的蚂蚱。专业点:事务就是一系列的操作,要么全部都执行,要都不执行。

3.2.2 回滚日志实现原子性

想要保证事务的原子性,就需要在异常发生时,对已经执行的操作进行回滚,而在MySQL中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的 修改都会先记录到这个回滚日志中,然后在对数据库中的对应行进行写入。 注意:系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,这也就需要回滚 日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因。 在日志文件中:在事务中使用的每一条 INSERT 都对应了一条 DELETE,每一条 UPDATE 也都对应一条相反的 UPDATE 语句。
在这里插入图片描述

回滚日志执行时间

  1. 手动执行回滚命令时会执行
  2. 如果程序在事务执行之后,提交命令执行之前出现了异常,在下次mysql服务重启的时候会执行

测试:
在事务提交前停止mysql服务:
在这里插入图片描述
停止mysql服务:
在这里插入图片描述
再一次开启mysql服务后查询我们新增的数据:

在这里插入图片描述
未查询到事务新增的数据。

3.3 重做日志与回滚日志

到现在为止我们了解了 MySQL 中的两种日志,回滚日志(undo log)和重做日志(redo log);在数据库系统中,事务的原子性和持久性是由事务日志 (transaction log)保证的,在实现时也就是上面提到的两种日志,前者用于对事务的影响进行撤销,后者在错误处理时对已经提交的事务进行重做,它们能保 证两点:

  1. 发生错误或者需要回滚的事务能够成功回滚(原子性);
  2. 在事务提交后,数据没来得及写会磁盘就宕机时,在下次重新启动后能够成功恢复数据(持久性);
    在数据库中,这两种日志经常都是一起工作的,我们可以将它们整体看做一条事务日志,其中包含了事务的 ID、修改的行元素以及修改前后的值。
    事务日志

下一篇:mysql事务隔离级别与IO的关系 10
上一篇:mysql锁机制 08

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值