不求甚解

此博客为个人学习之用,如与其他作品雷同,纯属巧合。

导航

MySQL8.0事务知识点

Posted on 2021-04-17 09:13  三年三班王小朋  阅读(257)  评论(0编辑  收藏  举报

mysql8.0事务学习

1、基本概念

事务(Transaction)是访问和更新数据库的程序执行单元;是一个最小的不可分割的工作单元,能保证一个业务的完整性;事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。事务只和DML语句有关,或者说只有DML语句才有事务,如果业务逻辑不同,DML语句的个数也不同。在MySQL中,默认情况下事务是自动提交的。

DML(data manipulation language)数据操纵语言:就是我们最经常用到的 SELECT、UPDATE、INSERT、DELETE。 主要用来对数据库的数据进行一些操作。
DDL(data definition language)数据库定义语言:其实就是我们在创建表的时候用到的一些sql,比如说:CREATE、ALTER、DROP等。DDL主要是用在定义或改变表的结构,数据类型,表之间的链接和约束等初始化工作。
DCL(Data Control Language)数据库控制语言:是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。

2、 提交和回滚

提交和回滚针对的是dml语句,ddl语句会直接提交事务。典型的MySQL事务是如下操作的

start transaction;
……  #一条或多条sql语句
commit;

其中start transaction标识事务开始,commit提交事务,将执行结果写入到数据库。如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。当然,也可以在事务中直接使用rollback语句进行回滚。

自动提交:MySQL中默认采用的是自动提交(autocommit)模式,如果没有start transaction显式地开始一个事务,那么每个sql语句都会被当做一个事务执行提交操作。如下所示:

=

autocommit参数是针对连接的,在一个连接中修改了参数,不会对其他连接产生影响。
关闭autocommit:如果关闭了autocommit,则所有的sql语句都在一个事务中,直到执行了commit或rollback

3、ACID是衡量事务的四个特性

原子性(Atomicity):语句要么全执行,要么全不执行,是事务最核心的特性,事务本身就是以原子性来定义的;实现主要基于undo log,记录事务之前原始的数据,
一致性(Consistency):保证事务提交后不会因为宕机等原因导致数据丢失,即数据库的完整性约束没有被破坏 ;实现主要基于redo log,记录事务修改后数据。
隔离性(Isolation):保证事务和事务之间是相互分离,互不影响;InnoDB默认的隔离级别是RR(可重复读),RR的实现主要基于锁机制(包含next-key lock)、MVCC(包括数据的隐藏列、基于undo log的版本链、ReadView)
持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚,MySQL 事务的持久性主要基于redo log。

4、事务的并发问题

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。
不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
幻读:就好像发生了幻觉一样,比如:明明当前事务查询没有这条结果,理应可以在当前事务进行新增操作,但是却提示记录已存在不能插入相同主键记录,这就是幻读,或者修改明明是全表update,但是执行成功后再进行查询却发现还有一条记录没有更新成功,这也是幻读。
其中:
不可重复读的和幻读区别:不可重复读侧重于修改或删除,幻读侧重于新增。不可重复读是select同一个数据发现的到的结果跟刚才不一样。幻读是比不可重复读高一个级别的错误,读取同一条数据发现跟刚才是一样的,只有读取一堆数据发现忽然多了一个,或者少了一个,就像自己产生了幻觉!综上,不可重复读针对的是同一条数据,幻读针对的是一片数据。
解决不可重复读的问题只需锁住满足条件的,解决幻读需要锁

5、锁

悲观锁:假定所有不同事务的处理一定会出现干扰,数据库中最严格的并发控制策略,如果一个事务正在对数据处理,那么在整个事务过程中,其他事务都无法对这个数据进行更新操作,直到该事务释放了这个锁。
乐观锁:假定所有不同事务的处理不一定会出现干扰,所以在大部分操作里不许加锁,但是既然是并发就有出现干扰的可能。在乐观锁中当提交更新请求之前,要先去检查读取这个数据之后该数据是否发生了变化,如果有变化,那么你此次的提交就要放弃,如果没有变化就可以提交。

6、事务隔离级别

事务隔离级别名称脏读不可重复读幻读
read-uncommitted 读未提交
read-committed 读已提交
repeatable-read 可重复读
serializable 串行化
 mysql默认隔离级别是“可重复读”,oracle默认隔离级别是“读已提交”。隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
可重复读 隔离级别表示, 你随便读,读多少次都没事,是好的一面。
MySQL InnoDB的mvcc机制解决不可重复读,并不保证完全避免幻读,需要应用使用加锁读来保证,mvcc属于乐观锁。
参考https://blog.csdn.net/qq_35590091/article/details/107734005

我的理解:1、事务的并发问题都是数据库读一致性的问题。2、回滚导致脏读,读已提交解决。3、不可重复读针对同一数据修改,锁行解决。4、幻读是查询和dml操作有间隙导致,锁表解决

7、事务提交过程

MySQL是通过WAL(Write-Ahead Logging)方式,来保证数据库事务的一致性和持久性

WAL是一种实现事务日志的标准方法,具体而言就是:
1、修改记录前,一定要先写日志;
2、事务提交过程中,一定要保证日志先落盘,才能算事务提交完成。
通过WAL方式,在保证事务特性的情况下,可以提高数据库的性能。

MySQL 本身不提供事务支持,而是开放了存储引擎接口,由具体的存储引擎来实现,具体来说支持 MySQL 事务的存储引擎就是 InnoDB。存储引擎实现事务的通用方式是基于 redo log 和 undo log。简单来说,redo log 记录事务修改后的数据, undo log 记录事务前的原始数据。在 MySQL 执行事务过程中如果因故障中断,可以通过 redo log 来重做事务或通过 undo log 来回滚,确保了数据的一致性。这些都是由事务性存储引擎来完成的,但 binlog 不在事务存储引擎范围内,而是由 MySQL Server 来记录的。

事务执行过程简化如下:

  1. 先记录 undo/redo log,确保日志刷到磁盘上持久存储。
  2. 更新数据记录,缓存操作并异步刷盘。
  3. 将事务日志持久化到 binlog
  4. 提交事务,在 redo log 中写入commit记录。

这样的话,只要 binlog 没写成功,整个事务是需要回滚的,而 binlog 写成功后即使 MySQL Crash 了都可以恢复事务并完成提交。要做到这点,就需要把 binlog 和事务关联起来,而只有保证了 binlog 和事务数据的一致性,才能保证主从数据的一致性。所以 binlog 的写入过程不得不嵌入到纯粹的事务存储引擎执行过程中,并以内部分布式事务(xa 事务)的方式完成两阶段提交