MySQL技术内幕-InnoDB存储引擎读书笔记(MySQL日志文件)

既然是COM_QUERY类型的,也包含update,insert语句。

2、binlog、redo、undo

接下来重点讨论binlog、redo、undo日志

基于InnoDB存储引擎来讨论binlog,redo,undo。

2.1 binlog

mysql二进制日志,在mysql服务层面记录mysql数据的变化轨迹,其存储格式为基于SQL语句(statement)、基于数据行变化(row)、混合方式(mixed),其作用主要用来做主从同步。横向类比(Redis主从复制)。

写入时机:下文与redo时一起讨论。

2.1.1 binglog相关参数与解读

binlog相关的配置参数如下:

log-bin=mysql-bin  (指定binlog的日志名,默认路径为${mysql_home}/data)

binlog_format 指定binglog的存放格式,statement,row,mixed

max_binlog_size

binlog_cache_size

sync_binlog

涉及文件操作,一般的做法是先缓存(内存中),然后隔一段时间将缓存写入到文件中。binlog的写入同样如此,mysql会为binlog提供一个写缓存区,每个会话将binglog,首先会写入到写缓存区,然后按某种机制刷写到磁盘。通过max_binlog_size设置单个binlog文件的大小,默认为1G,一个文件达到上限后,再新建一个文件,.index记录了所有的binlog文件。binlog_cache_size,是会话级别的参数,设置binlog的内存缓存区大小,默认为32K。如果一个会话内的产生的binlog日志超过32K后,mysql会将binglog写入临时的日志文件。mysql提供两个运行时变量binlog_cache_use、binlog_cache_disk_use来记录利用内存缓存和文件缓存的次数。sync_binlog用来设置输入缓存的频率,表示多少次写缓存区后刷新到磁盘。我们知道,在事务允许过程中,首先会将产生的binlog写入到会话内的缓存区(内存缓存区),然后在事务提交后,将内存缓存区的数据写入到mysql binlog的写缓存区,然后刷写到磁盘,sync_binlog=1表示事务提交时(发出commit之前会先写binlog,但不一定会落盘,InnoDB1.2之后,提交阶段写redo,binlog日志为两阶段提交,见下文详解),将缓存区中的数据立即刷写到磁盘(落盘)。生产环境下sync_binlog设置为1,保证其数据一致性。但还存在这样一种情况,如果发出事务comit操作,binlog已经被写入,但事务提交过程中,mysql服务器down了,此时会引起主从数据不一致性,该怎么办呢?innodb存储引擎提供了innodb_support_xa=1来解决binlog与innodb存储引擎日志文件不一致的问题(二阶段提交),下午redo,undo部分再详细解读。

binlog-do-db          指定需要同步的数据库(schema)

binlog-ignore-db    指定需要同步(记录binlog)日志的数据库(schema)

log-slave-update    设置从服务器是否也写binglog日志,默认是关闭的,log-slave-update=1表示开启。

2.1.2 binglog工具

mysql提供了官方的binlog查看工具,mysqlbinlog

2.2 redo与undo日志

redo与undo是mysql存储引擎级别的日志,俗称事务日志,与事务的实现息息相关。那我们从事务的ACID属性开始说起:

原子性(Atomicity)

事务内的操作要么全部执行,要么全部不执行。

一致性(Consistency)

在事务开始之前和事务开始之后,数据库的完整性约束没有被破坏。

隔离性

两个事务的执行互不干扰,sql定义了4种隔离级别(读未提交、读已提交、可重复读、串行话读)

持久性(Durability)

事务成功执行后,该事务所对数据库所做的变更持久的保存在数据库之中。

redo 重做日志,主要用来保证事务的持久性。

undo 回滚日志,在InnoDB中,将undo看成是数据,并不是日志,存放在数据文件中(innodb表空间文件中ibdata1)。

2.2.1 redo,undo日志基础

https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_log_buffer_size  官方文档关于InnoDB参数

1)undo 取消操作,用于事务回滚,将数据恢复到修改之前的状态,InnoDB的多版本并发控制(MVCC)就是基于undo来实现的。undo严格意义上来说,InnoDB将undo信息当成数据,存放在数据文件。数据文件相关的参数如下:

innodb_data_home_dir :数据文件的路径,在my.cnf中对应 data_dir

innodb_data_file_path:数据文件名(默认表空间文件),默认为ibdata1:12M:autoextend

innodb_file_per_table : 支持每个表单独一个表空间文件(数据文件)

innodb_tmpdir           :临时表空间路径

innodb_temp_data_file_path:临时表空间文件,默认为ibtmp1:12M:autoextend

innodb_undo_directory : undo独立目录(undo独立表空间)

innodb_undo_log_truncate:默认为off,undo日志是否支持压缩,删除已经落盘的信息。

innodb_undo_logs:128,默认为128个undo段,其中0号回滚段存在于默认表空间中,1-32号表空间位于临时表

空间。

innodb_undo_tablespaces:默认为0,表示不开启独立的undo表空间。

2)redo日志

重做日志,用来实现服务器异常时的数据恢复,实现事务的持久性。

redo日志的核心思想是使用顺序IO(事务提交时主要写redo日志,操作一个顺序的联系的IO文件)来代替每个事务提交时大量的随机IO去更新数据文件。也就是对数据的修改不会立马刷写到数据文件,而是写入redo文件,然后使用一定的机制,将内存中的脏页异步写入到数据文件,提高事务的执行效率与并发能力。

redo相关的配置参数:

innodb_log_buffer_size : 一般根据页的大小(8K,16K)设置为8M,16M,写redo日志的缓冲区大小

innodb_log_file_size:单个redo日志文件的大小,默认为48M

innodb_log_files_in_group:默认为2,表示一个redo日志组中包含多少个文件,默认为2个。进行循环覆盖写

innodb_log_write_ahead_size,每次追加写到redo日志文件的大小,默认为页的大小。8K或16K

innodb_log_group_home_dir:redo日志文件目录,默认为数据文件路径${mysql_home}\data

2.2.2 binlog、undo、redo日志写入时机

redo,重做日志,其引入的目的就是能够回复InnoDB的事务,达到恢复数据的目的。(持久性)

undo回滚日志,其引入的目的就是事务内的回滚(rollback)。(原子性)

redo日志引入的技术性原理分析:

首先,数据库存储其底层是文件系统,也就是数据库的数据最终存放在文件中,称之为数据文件。其持久性最通俗的要求就是事务执行后变更要能反馈到数据文件中即可。

操作数据库数据的逻辑一般是这样的:

首先,从数据库文件中找到记录,文件一般是按照一种特定的格式存放,比如页,然后加载整页数据到内存,在内存中进行数据的操作(脏页)然后将脏页同步回文件,一般不会立即将脏页刷回到磁盘,这样会产生大量的随机IO操作,性能低下,如果不立即刷回磁盘,那么当服务器挂掉后,存放在内存中的数据会丢失,造成数据的不一致性,也就无从持久化。为了解决这一矛盾,引入了redo日志。

redo日志的引入核心一个思想是采用对redo日志文件的顺序IO来替换频繁的随机IO(更新数据文件),redo文件使用循环覆写方式。redo一般会有两个文件ib_log0与ib_log1。引入redo日志后,数据库修改数据的通常逻辑为,从数据文件中找到数据页并加载到内存,在内存中修改数据,在事务提交之前先写redo日志,确保redo日志落盘,然后提交事务。数据库中的脏页使用一定的机制,统一刷写到数据文件。这样就将每次事务提交的时候,将随机访问数据文件变成顺序写redo日志。这样就提高了效率。

接下来我们以示例来分析,redo,undo是如何写入的。

1)update语句

我们知道,InnoDB使用多版本控制并发控制协议(MVCC)来实现无锁的并发读控制,MVCC,就是借助于undo日志。根据MVCC的实现方式,update语句执行逻辑为,先复制一份老的数据,请删除版本号设置为当前的事务ID,然后插入一条新的数据,更新版本号为当前事务。这里复制老的数据这一个步骤完全与undo的引入非常吻合,可以利用undo来恢复数据。那么MVCC结合undo关于update的实现:

a、首先将数据(数据行)拷贝一份,将其删除版本号设置为当前事务ID,申请回滚段(undo),记录undo日志,undo日志的存储方式是一条链表(双链表)并且按照事务ID后排序。因为InnoDB把undo日志当成是数据,存放于表空间中,故在写undo之前,需要先写redo日志,redo日志将包含undo信息(可以根据redo日志重建undo日志链),也就是undo是受redo日志保护的。

b、然后用插入一条数据,将数据行的更新版本号设置为当前事务。

最后

笔者已经把面试题和答案整理成了面试专题文档

image

image

image

image

image

image

案整理成了面试专题文档**

[外链图片转存中…(img-tXOIDYZ2-1714426001490)]

[外链图片转存中…(img-Z7zXOaen-1714426001491)]

[外链图片转存中…(img-UKow5C1G-1714426001491)]

[外链图片转存中…(img-vpPpwkWq-1714426001491)]

[外链图片转存中…(img-DB6e2L3t-1714426001492)]

[外链图片转存中…(img-BL5IRPZb-1714426001492)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《python数据分析基础教程》 ⼀、导⼊常⽤numpy模块 from numpy import * //可以直接引⽤numpy中的属性XXX import numpy as np //引⽤numpy中的属性⼀定要np.XXX ⼆、常⽤函数以及转化关系 np.arange() 对应 python中的range() np.array() 对应 python中的list np.dtype() 对应 python中的type() tolist()函数可以将numpy数组转换成python列表: 列表转为数组: warning:Passing 1d arrays as data is deprecated in 0.17 and willraise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample. 这个warning主要就是有些函数参数应该是输⼊数组,当输⼊列表时就会警告!! 三、numpy中数组操作函数 数组组合函数 将ndarray对象构成的元组作为参数输⼊ (1)⽔平组合:hstack((a,b)) 或者concatenate((a,b),axis=1) (2)垂直组合:vstack((a,b)) 或者concatenate((a,b),axis=0) (3)列组合:column((a,b)) (4)⾏组合:row_stack((a,b)) 数组的分割函数 (1)⽔平分割:hsplit(a,3) 或者 split(a,3,axis=1) (2)垂直分割:vsplit(a,3) 或者 split(a,3,axis=0) 四、⽂件处理——os库 1.os.system() 运⾏shell命令 2.os.listdir(path) 获得⽬录中的内容 3.os.mkdir(path) 创建⽬录 4.os.rmdir(path) 删除⽬录 5.os.isdir(path) os.isfile(path) 判断是否为⽬录或者⽂件 6.os.remove(path) 删除⽂件 7.os.rename(old, new) 重命名⽂件或者⽬录 8.os.name 输出字符串指⽰正在使⽤的平台。如果是window 则⽤'nt'表⽰,对于Linux/Unix⽤户,它是'posix' 9.os.path.join() 在⽬录后⾯接上⽂件名 10.os.path.split() 返回⼀个路径的⽬录名和⽂件名 11.os.path.splitext() 分离⽂件名与扩展名 12.os.path.getsize(name) 获得⽂件⼤⼩,如果name是⽬录返回0L 14.os.path.abspath(")获得当前路径 15.os.path.dirname()返回⼀个路径的⽬录名 五、使⽤matplotlib画图(第九章 ) 前⾯⼏个列⼦主要讲解了通过多项式函数通过plt.plot()函数构建绘图,补充⼀下在机器学习中散点绘制 import numpy as np import matplotlib.pyplot as plt fig=plt.figure() ax=fig.add_subplot(111) x1=[2, 2.6, 2.8] y1=[2, 2.4, 3] x2=[4,5 ,6] y2=[1.3, 2, 1.2] ax.scatter(x1,y1,s=20,c='red') ax.scatter(x2,y2,s=50,c='blue') plt.show() 另外:做数据分析——sklearn库 from sklearn import preprocessing 数据预处理:归⼀化、标准化、正则化处理 from sklearn import preprocessing preprocessing.normalize(features, norm='l2')//正则化

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值