IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 【SQL事务】事务是如何实现的? -> 正文阅读

[大数据]【SQL事务】事务是如何实现的?

1. 什么是事务?

事务是一组 SQL语句的集合,要么全部执行,要么全部不执行。

事务有四大特性ACID: 原子性,一致性,隔离性,持久性

原子性:一个事务的操作要么全部执行,要么全部不执行。在事务的执行过程中,发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过 一样。主要是靠undolog进行保证的

隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力。事务隔离级别分为不同的级别:读未提交(Read uncommited),读已提交(Read commited),可重复读(Repeatable read)和串行化(Serializable)主要是靠MVCC进行保证的

持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。主要是靠redolog进行实现的

以上三个特性可以保证 一致性:在事务开始之前和事务结束之后,数据库的完整性没有破坏。

0. SQL的各个日志是干什么用的?

SQL中主要有:

errlog: 错误日志

binlog: 主从复制,主从同步

slowlog: 慢日志

relaylog: 中继日志

以上日志是位于server层面的,和存储引擎无关。

innodb有两个独有的日志,一个是

undolog:回滚日志,记录数据被修改前的样子

redulog:前滚日志,记录的是数据修改之后的值,不管事务是否提交都会记录下来

1. undolog是干什么的?

作用: 防止丢失数据,用于事务失败后的回滚。

记录时机: 在mysql将更新的数据加载到缓冲区Buffer pool时,同时往undolog中插入一条日志,也就是将id=1的这条记录的原来的值记录下来。

更新时机:

  1. 准备一条SQL语句
  2. MySQL(Innodb)会先去缓冲池(Buffer pool)中查找这条数据,没找到就回去磁盘中查找,如果查找到就会将这条数据加载到缓存池(Buffer pool)
  3. 在加载到Buffer Pool 的同时,会将这条数据的原始记录保存到undo日志文件中

问题:当Buffer Pool中的数据和数据库中的数据不一致时,我们就会认为缓存中的数据时脏数据。

2. redolog是干什么的?

作用: redolog记录的是数据修改之后的值,不管事务是否提交都会记录下来

  • redolog是Innodb特有的,他是存储引擎级别的,不是mySql server级别的
  • 服务器宕机,mysql重启时,利用redolog日志内容恢复到缓冲区数据
  • 一般情况下,redolog Buffer数据写入磁盘的策略是立即刷入磁盘

2.1 为什么需要redolog

  1. Mysql为了提高效率,所以先从磁盘读取数据放在内存中去完成,然后直接对内存进行数据的操作,这些操作会在某个时机将其持久化到磁盘中。
  2. 除了从磁盘中加载文件和将操作前的记录保存在undolog中,其他操作都是在内存中完成的
  3. 内存数据断电丢失:如果此时MySQL所在的服务器宕机了,那么Buffer Pool中的数据会全部丢失。这个时候就需要redolog来恢复数据

2.2 redolog的刷写时机

刷磁盘可以通过 innodb_flush_log_at_trx_commit 参数来设置

值为 0 表示不刷入磁盘
值为 1 表示立即刷入磁盘(默认情况)
值为 2 表示先刷到 os cache

一般情况下,redo log Buffer 数据写入磁盘的策略是立即刷入磁盘

3. binlog是干什么的?

用于记录数据库执行的写入性操作(DDL,DML,不包括查询)信息,以二进制的形式保存在磁盘中。

binlog是以追加的形式写入的。

3.1 使用场景

在实际应用中,binlog的主要使用场景由两个,分别是主从复制数据恢复

  1. 主从复制:在Master端开启binlog,然后将binklog发送到各个Slave端,Slave端重发binlog从而达到主从数据一致。
  2. 数据恢复:通过mysqlbinlog工具来恢复数据

mysql通过sync_binlog参数控制biglog的刷盘时机,取值范围是0-N:

0:先写入 os cache,由系统自行判断何时写入磁盘,宕机数据会丢失;(MySQL 5.7.7之前版本的默认值)
1:每次commit的时候都要将binlog写入磁盘;(MySQL 5.7.7之后版本的默认值)
N:每N个事务,才会将binlog写入磁盘。

3.2 binlog刷写磁盘策略

对于InnoDB存储引擎而言,只有在事务提交时才会记录binlog

4. 准备更新到事务提交全过程

  1. 首先执行器根据 更新sql,来查询满足条件的数据,先是从缓存池中查询数据,如果没有就会在数据库中查询,如果查询到了将其放到缓存池中
  2. 在数据被缓存到缓存池的同时,将原始数据写入undolog文件中
  3. 在Buffer Pool中更新数据,将更新后的数据添加到redo log buffer中
  4. 完成以后就可以提交事务,在提交事务前会做以下三件事

将redo log buffer 的数据持久化到 redolog文件中
将本次操作记录持久化到binlog日志文件中
将binlog记录结束的位置标记记录到redolog中,最后在redolog添加commit标记(表示事务完成)

在这里插入图片描述

4.1 两阶段提交

在这里插入图片描述

  1. 写入 redo log,处于 prepare 状态。
  2. 写 binlog。
  3. 修改 redo log 状态变为 commit。
    由于 redo log 的提交分为 prepare 和 commit 两个阶段,所以称之为两阶段提交。

4.2 为什么需要两阶段提交?

如果没有两阶段提交的话,那就是一阶段提交,就两种形式

  1. 先提交binlog,再提交redolog
  2. 先提交redolog,再提交binlog

当我们要想表中插入一条记录R,先写binlog,再写redolog。但是写完binlog后,突然发生了断电。具体操作已经同步binlog保存了起来,但是没有保存操作过后的数据。然后来电后,机子开始进行恢复的操作,binlog中已经有R的记录了,当从机从主机同步数据的是时候,或者我们使用binlog恢复数据的时候,就会同步到R这条记录;但是redolog中没有关于R的记录,所以崩溃恢复之后,插入R记录的这个事务是无效的,即数据库中没有该行记录,这就造成了数据不一致。

当我们要想表中插入一条记录R,先写redolog,再写binlog。但是写完redolog后,突然发生了断电。机子开机再恢复的过程中就会出现问题:redolog中是有数据R的,所以在恢复数据库的时候将该条数据恢复到数据库中。但是binlog中是没有关于R的数据的,所以当从机从主机同步数据的时候或者我们使用binlog恢复数据的时候,就不会同步到R这条记录,这也就造成了数据不一致。

5. 数据库支持的几种并发情况

读读,读写,写写

读读: 不存在任何问题,也不需要并发控制
读写: 有数据安全问题,会出现脏读,不可重复读,幻读,依靠MVCC解决
写写: 有数据安全问题,会存在丢失更新的问题,锁来解决

6. 什么是MVCC?

MVCC:Multi-Version Concurrency Control,多版本并发控制,用来解决并发读写问题,不需要通过加锁来解决。
MVCC本质上是维持了一个数据的多个版本,使得读写操作之间没有冲突。
MVCC只在RC 和 RR 两个隔离级别下工作

6.1 当前读和快照读

当前读: 读取的是数据的最新版本,而且要保证其他并发事务不能修改当前记录,for update,update,delete,insert
快照读:不加锁的非阻塞读,读取的是历史版本的数据,不是最新的记录。不加锁的select

6.2 RC 和 RR

RC读已提交:当其他事务修改数据之后,可以看的修改之后的值,每一次进行一次快照读,都会生成新的readview
RR可重复读:当其他事务修改数据之后,看不到修改之后的值,每个事务只有在第一次进行快照读的时候会生成readview,之后的快照读都会沿用之间的readview

不同的隔离级别生成的readview的时机是不同的

6.3 RR隔离级别能否解决幻读问题?

不能

幻读: 一个事务读取到了另一个数据插入进来的数据。
出现的本质原因是:
如果事务中都是用快照读,那么是不会产出幻读的,但是当快照读和当前读一起使用的时候就产生了幻读问题。

参考

直播笔记
MySQL-三大日志详解
MySQL 事务-菜鸟教程
MySQL 为什么需要两阶段提交?

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-05-21 19:02:54  更:2022-05-21 19:05:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:01:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码