mysql的内部组件结构如下图所示
连接器
与客户端建立连接,检验登录密码,分配相应权限
查询缓存
执行sql语句时会先从这里找一下,这里数据的存储格式是key-value,key是sql语句,value是查询结果。只有当sql语句和查询缓存中的sql语句完全一致才会匹配成功,并且只要对表进行了更新操作就会清除查询缓存中的内容。mysql8.0已经移除了查询缓存
词法分析器
对sql语句进行解析,进行相应语法校验,一条select查询语句经过分析后的结果如下图所示
优化器
Mysql自动对sql语句进行相应的优化,存在多个索引时决定使用哪一个,多个表连接查询时决定谁驱动谁
执行器
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。
当使用InnoDB存储引擎执行一条update语句的大致流程如下:
经过server层后就到存储引擎层了,
当进行更新操作时就会生成redo log文件,它是用来保证事务的持久性的,事务提交前就会把内存中的redo log写入到磁盘中
redo log刷盘策略
mysql线程以秒为单位将内存中的日志刷新到磁盘
Redo log Buffer缓存池使用了1/2,就触发刷盘机制
默认情况下事务提交前,由innodb_flush_log_at_trx_commit
这个变量的值来决定提交时是否持久化redo log
当磁盘中Redo log文件不可重写部分占了75%容量时,就触发刷新Buffer pool中脏页的机制
关键参数
innodb_log_buffer_size
设置redo log buffer大小参数,默认16M ,最大值是4096M,最小值为1M。
show variables like '%innodb_log_buffer_size%';
innodb_log_group_home_dir
设置redo log文件存储位置参数,默认值为"./",即innodb数据文件存储位置,其中的 ib_logfile0 和 ib_logfile1 即为redo log文件。
show variables like '%innodb_log_group_home_dir%';
innodb_log_files_in_group
设置redo log文件的个数,命名方式如: ib_logfile0, iblogfile1… iblogfileN。默认2个,最大100个。
show variables like '%innodb_log_files_in_group%';
innodb_log_file_size
设置单个redo log文件大小,默认值为48M。最大值为512G,注意最大值指的是整个 redo log系列文件之和,即(innodb_log_files_in_group * innodb_log_file_size)不能大于最大值512G。
show variables like '%innodb_log_file_size%';
innodb_flush_log_at_trx_commit
这个参数控制 redo log 的写入策略,它有三种可能取值:
Redo log 写入磁盘文件大致过程
是交替循环写多个文件,写满一个文件后写下一个文件,但最后一个文件写满后又写第一个文件,大致如下图所示:
write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。
checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件里。
write pos 和 checkpoint 之间的部分就是空着的可写部分,可以用来记录新的操作。如果 write pos 追上checkpoint,表示redo log写满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。
当数据库进行更新操作时,就会记录相应操作到Bin log文件中,它的作用是:数据恢复、主从复制
在mysql5.7中Binlog默认是关闭的,在Mysql8.0版本中默认是开启的,
# 查看binlog相关参数
show variables like '%log_bin%';
log_bin的值是OFF就代表binlog是关闭状态,打开binlog功能,需要修改配置文件my.cnf,然后重启数据库。
# log-bin设置binlog的存放位置,可以是绝对路径,也可以是相对路径,这里写的相对路径,则binlog文件默认会放在data数据目录下
log-bin=mysql-binlog
# Server Id是数据库服务器id,随便写一个数都可以,这个id用来在mysql集群环境中标记唯一mysql服务器,集群环境中每台mysql服务器的id不能一样,不加启动会报错
server-id=1
# 其他配置
binlog_format = row # 日志文件格式,下面会详细解释,推荐使用MIXED混合模式
expire_logs_days = 15 # 执行自动删除距离当前15天以前的binlog日志文件的天数, 默认为0, 表示不自动删除
max_binlog_size = 200M # 单个binlog日志文件的大小限制,默认为 1GB
重启mysql服务后再通过上面的命令查看结果如下,此时就表示binlog已经开启了
Binlog的日志格式
mysql支持三种
binlog写入磁盘机制
binlog写入磁盘机制主要通过 sync_binlog 参数控制,默认值是 0。
binlog 文件重新生成策略
flush logs;
命令删除binlog日志
删除当前的binlog文件
reset master;
# 删除指定日志文件之前的所有日志文件,下面这个是删除6之前的所有日志文件,当前这个文件不删除
purge master logs to 'mysql-binlog.000006';
# 删除指定日期前的日志索引中binlog日志文件
purge master logs before '2023-01-21 14:00:00';
查看 binlog 日志文件
binlog文件中默认记录的是二进制的数据,可以使用如下方式进行查询其中的内容
# 查看bin-log二进制文件(命令行方式,不用登录mysql)
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 # 查看bin-log二进制文件(带查询条件)
mysqlbinlog --no-defaults -v --base64-output=decode-rows D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000007 start-datetime="2023-01-21 00:00:00" stop-datetime="2023-02-01 00:00:00" start-position="5000" stop-position="20000"
在binlog文件中每一个 BEGIN 或者是COMMIT 上下都有一个表示位置的数,比如 \# at 766
,可以拿到这个偏移量去进行数据恢复
binlog日志文件恢复数据
思路是首先通过上面的命令查看到binlog文件的内容,找到要恢复的一个起始和结束位置,在执行数据恢复命令,或者是直接执行整个binlog文件
mysqlbinlog --no-defaults --start-position=219 --stop-position=701 --database=test D:/dev/mysql-5.7.25-winx64/data/mysql-binlog.000009 | mysql -uroot -p123456 -v 数据库名
InnoDB对undo log文件的管理采用段的方式,也就是回滚段(rollback segment) 。每个回滚段记录了 1024 个 undo log segment ,每个事务只会使用一个undo log segment。
在MySQL5.5的时候,只有一个回滚段,那么最大同时支持的事务数量为1024个。在MySQL 5.6开始,InnoDB支持最大128个回滚段,故其支持同时在线的事务限制提高到了 128*1024 。
undo log日志什么时候删除
新增类型的,在事务提交之后就可以清除掉了。
修改类型的,事务提交之后不能立即清除掉,这些日志会用于mvcc。只有当没有事务用到该版本信息时才可以清除。