一)事务的特性:
一致性:主要是在数据层面来说,不能说执行扣减库存的操作的时候用户订单数据却没有生成
原子性:主要是在操作层面来说,要么操作完成,要么操作全部回滚;
隔离性:是自己的事务操作自己的数据,不会受到到其他事务的影响;
持久性:事务进行提交以后,数据要真实的修改在磁盘上面,不能说系统宕机数据就丢失了
二)脏写:
2.1)数据丢失或者是脏写:当有两个事务或者是多个事务选择同一行,然后基于最初的值选定该行的时候,由于每一个事务都不知道其他事务的存在,就会发生数据丢失更新问题,最后的更新覆盖了其他事务所做的更新;
乐观锁:就是假设两个事务并发执行,一个事务想要把库存扣减3,另一个事务想要把库存扣减2,那么两个事务并发执行的时候,此时就会发生脏写问题,如何解决呢,可以使用版本号机制,给库存字段再加上一个版本号,每进行一次数据的更新操作,版本号+1,此时就可以解决脏写问题,此时一定会出现一个事务版本号小于等于内存版本号,更新失败,乐观锁适用于读比较多的场景,如果写非常多,就会失败次数很多,会导致CPU一直空转;
悲观锁:一个事务针对于要操作的数据加锁,其他事务想要操作数据,只能阻塞等待;
2.2)脏读:事务A读取到了事务B已经修改但是没有提交的数据,因为数据不稳定,发生脏读一定会发生不可能重复读和幻读;
2.3)不可重复读:事务A相同的查询语句在不同的时间查询到了不同的结果
可重复读就是不管其他变量对数据是否修改,第一查询只要查询的结果是true,后面只要当前事务不修改当前这个布尔值,那么读取到的始终是一条结果,侧重于已经存在但是修改过的数据
2.4)幻读:一个事务A会读取到事务B新增的数据
表锁:每次操作锁住整张表,开销小,加锁快,不会出现死锁,锁定粒度大,发生锁冲突的概率最高,并发度最低,一般用在整表数据迁移的场景,防止数据迁移数据发生变动;
手动增加表锁:lock table 表名称1 read(write),表名称2 read(write)
查看加上的表锁:show open tables
删除表锁:unlock tables;
加读锁:只能读取该表,不能写该表
加写锁:即可以读,又可以写,其他事务既不能读,也不可以写
行锁:每一次操作锁住一行记录,开销大,加锁慢,锁定粒度最小,发生所冲突的概率最低,并发程度最高,InnoDB和MYSIM存储引擎有两个区别:
1)InnoDB支持事务
2)InnoDB支持行级锁
行锁演示:一个Session开启事务以后不提交,另一个Session更新同一条记录的时候会发生阻塞,更新不同的记录的时候不会发生阻塞;
3)表锁开销小,加锁块,但是行锁开销大,加锁慢,这样子理解很简单,对于表来说只要找到这一张表,就可以直接给他加锁,速度很快,但是对于行锁来说,先要找到表,再来找行,效率很低,行锁的粒度肯定是比表锁小的,粒度越大,锁冲突的概率还是比较高的
4)MYSIM存储引擎在执行Select语句之前,会自动给设计所有的表加读锁,在执行update,insert,delete操作的时候会自动给涉及到的表加写锁,但是InnoDB存储引擎在执行查询语句Select操作的时候,因为有MVCC机制所以不加锁,但是update,insert和delete操作会加行锁,总而言之,就是读锁会阻塞写,但是不会阻塞读,但是写锁会把读和写都会阻塞
在数据库没有提交数据的时候,你更新的数据是在缓存进行更新的,事务与事务在并发进行的时候就叫作隔离级别,只有在提交之后,数据才从日志中把数据更新到数据库里面
三)MVCC:无论事务是否提交,undolog版本链的数据都是要记录下来的,因为事务要回滚,所以要记录,基于快照结果集+undolog版本链,undolog版本链只有一份;
1)begin和start transaction并不是一个事务的起点,在执行到第一个DML语句的时候,也就是执行到他们的第一个修改操作InnoDb的语句的时候,事务才算是真正的进行启动,才会向MYSQL中申请事务id,执行select操作是不会生成事务ID的
2)insert新插入的数据的版本连上面的记录的回滚指针的地址就是null,因为当前数据已经是最早的纪录了,不管事务是否提交,update更新的数据都会存放到undolog版本链中,一行数据由四个部分组成,当前事务操作操作完以后的数据完整记录+当前事务操作完成后的数据ID+聚簇索引ID+版本链(指针));
3)当一个事务id=60的事务新增了一条数据,那么这一行记录就变成
(userID=1,username="李四",60,聚簇索引ID,null(因为是事务新插入的第一条数据)
此时再来一个事务修改这条user数据username="王五",此时版本链的数据就变成了这样子:
0X666 (userID=1,username="王五",100,聚簇索引ID,0X777)| ---------------------------------------------------- | 0X777 (userID=1,username="李四",60,聚簇索引ID,null(因为是事务新插入的第一条数据)
4)在可重复读级别,当事务开启以后,执行任何的查询SQL都会生成当前事务的一致性视图,也叫做readView,该视图只会生成一次且在事务提交前不会发生任何变化,但是是如果是读已提交隔离级别下每一次执行查询SQL都会生成读视图(必须是当前读),但是从版本连中取数据一定是从最新的undolog版本连中的数据查找的;
5)当前进行比对的过程中是从当前undolog版本链的最新的记录的事务ID开始和读视图readView进行比对,从而来确定最终MYSQL读取的是哪一条记录,如果这条记录不符合要求,那么按照undolog版本链单向链表查询下一条符合要求的记录;
6)MYSQL会根据读视图中的最小事务ID和最大事务ID来划分区间
从而确定已提交事务和未提交事务
7)根据undolog版本链上的每一条记录的事务ID来判断当前这条记录是否已经在生成读视图之前提交了,小于min_id的一定是已提交事务,大于max_id一定是未提交事务,但是在min_id和max_id之间的记录有可能是已提交,也有可能是未提交;
8)事务操作中,update操作更新的是MYSQL中真实的数据;
比较规则:一个事务想要并可以读取到读视图生成之前事务提交的记录
1)trx_id=creator_trx_id,如果这条记录的事务ID等于创建读视图的事务ID,那么该数据记录的最后一次操作的事务就是当前事务,当前记录对当前事务可见;
2)trx_id<creator_trx_id,说明在生成读视图的时候这条记录的事务ID不在活跃列表里面,说明修改这条记录的事务已经在生成读视图之前提交了,所以当前记录可见;
3)trx_id>=max_trx_id,如果trx_id 值小于 Read View 中的 min_trx_id ,表示这个版本的记录是在创建 Read View后才启动的事务生成的,所以该版本的记录对当前事务不可见,否则会发生不可重复读的问题;
4)min_trx_id <= trx_id < max_trx_id:判断 trx_id 是不是在当前事务ID集合(m_ids)里面
四)一条SQL语句的执行流程:update user set name="张三" where userID=1;
简单来说 MySQL主要分为 Server 层和存储引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器等,还有一个通用binlog日志模块,用于整个数据库操作记录,主从复制的关键,存储引擎层主要负责数据的存储和读取
1)连接器
客户端想要对数据库进行操作时,连接器就是用来负责跟客户端建立连接、获取权限、维持和管理连接的同时为了避免频繁创建和销毁连接造成性能损失,可选择利用连接池进程管理
1.1)如果用户名或者是密码不对,你就会收到一个错误信息,然后客户端程序终止执行
1.2)如果用户名密码校验通过,连接器会去MYSQL中的权限表查出你所拥有的权限
这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限,修改完成后,只有再新建的连接才会使用新的权限设置。
2)查询缓存:
2.1)查询缓存主要用来缓存我们所执行的 select语句以及该语句的结果集,如果开启了查询缓存,执行查询语句的时候,会先查询缓存,如果缓存 key 被命中,就会直接返回给客户端,在数据变换频繁的表中,是不推荐使用的,因为当一张表的数据发生变化,其所有缓存都将清空;
2.2)一般MYSQL的缓存尽量在静态表中进行使用,就是很少更新的表,MYSQL服务器如果在查询缓存中发现了这一条SQL语句,(缓存的SQL-->key,结果----value)
那么就会直接将结果返回给客户端,如果没有,就直接进入到解析器,由于MYSQL命中缓存的概率非常低,所以MYSQL8.0就将这个功能给删除了
2.3)SQL语句作为key,查询结果是String,也是value
1.1)SQL有空格
1.2)函数调用,NOW()函数,虽然两个SQL相同,但是NOW()函数的结果不一样
3)分析器:法词分析,语义分析,知道SQL要做什么
3.1)词法分析:因为输入的命令是是由多个字符串和空格组成的一条SQL语句,MYSQL需要进行识别里面的字符串都是代表的什么含义,就比如MYSQL把你输入的这个select这个关键字识别出来,这是一个查询语句,也要把字符串user识别成表名,把userID识别成userID;
3.2)语法分析:把提取出的关键词转换为抽象语法树后进行检验。主要就是判断你输入的 sql 是否正确,是否符合 MySQL 的语法,并会提示you have an error in your syntax
4)优化器:
一条查询可能有很多种执行方式,列出所有可能的执行方案,最后都返回相同的结果,优化器就是在其中找到最好的执行计划,优化器会根据IO和CPU成本,选出代价最小的索引进行执行
4.1)逻辑查询优化:索引优化,在优化器中就会确定出SQL的执行路径比如说是全表检索还是索引检索,还有可能说就是这个字段有多个索引,那么优化器会最终判断到底要走哪一条索引,最终生成执行执行计划
4.2)语法查询优化:比如说子查询改成多表连接,就是通过SQL的等价变换来提升查询效率,直白一点说就是换一种写法可能查询效率更高,改变各个表的连接顺序
select * from user where username="张三" and gender="男"
五)执行器:
执行器会判断你是否具有相关操作的权限,没有权限就会发生报错,如果具备权限,就执行SQL进行返回,如果设置了查询缓存那么就会将查询结果进行缓存,最终会调用存储引擎的API也就是一些接口,调用存储引擎之后再去调用文件系统,实现对数据的查询
执行引擎根据执行计划查询数据,并把结果集返回客户端
六)BufferPool
BufferPool起到一个缓存的作用,MySQL 的数据最终是存储在磁盘中的,如果没有 Buffer Pool,那么每次的数据库请求都会磁盘中查找,这样必然会存在 IO 操作,但是有了 Buffer Pool,只有第一次在查询的时候会将查询的结果存到 Buffer Pool 中,这样后面再有请求的时候就会先从缓冲池中去查询,如果没有再去磁盘中查找,然后在放到 Buffer Pool 中
整个MYSQL的增删改查都是基于buffer Pool来做的
如果没有索引查询,那么MYSQL会从第一个数据页开始从磁盘加载到执行引擎的缓存池中
一条sql语句在MySQL的执行过程_update user set username where id=4-CSDN博客
1)执行器:调用执行引擎的接口把SQL语句丢给存储引擎层来进行执行
2)首先检查buffer pool缓冲池中有没有对应的数据,正常来说一些常用的数据都被加载到buffer pool里面来提高MYSQL的性能,如果buffer pool中没有,就去加载缓存数据;
3)把id=1的记录所在的16K页的数据加载到buffer pool中,并对该条记录加锁;
4)写入更新数据的旧值到undoLog回滚日志里面,用于回滚,将老的值写入到undolog回滚日志文件里面,如果事务提交失败需要进行回滚操作,可以使用undo log中的日志的数据恢复buffer pool中的缓存数据;
5)更新bufferpoo也就是l内存的数据;
6)把更新修改后的数据写入到redo log buffer里面,redolog日志会定期的把redologbuffer中的数据定期的刷新到redolog重做日志文件里面,这是一个prepare阶段,它是属于一个物理修改,大概在物理磁盘上面的哪一个页位置做了修改的值,不是记录的是具体的SQL语句,但是对于binlog日志来说直接记录的是name="张三";
7)准备提交事务,将binLog日志写入到binlog文件中,binlog属于归档日志文件,属于Server层,内存中的数据已经刷新到磁盘上面去了,如果程序员不下心删了几条记录,binlog主要用于恢复数据库中磁盘的数据,但是redolog中的数据还没有刷新到磁盘中,还有binlog是属于整个Server层,所有存储引擎都共享Server层的功能;
8)当用户进行执行commit操作的时候,binog会将commit标记到redolog文件日志里面,此时提交事务完成,该标记就是为了保证事务提交以后binlog和redo log数据的一致性,这也就是两阶段提交,第一阶段prepare阶段,两个日志各写各的,第二个是commit操作,代表binlog日志和redolog日志已经全部完成了,两阶段提交就是为了保证事务执行完成以后两个文件都是写入成功的,二段性提交就是为了保证MYSQL的两个日志文件保持一致性;
9)MYSQL会开启一个后台线程,在系统空闲的时候将buffer Pool随机写会到磁盘里面,是以page为单位进行写入的,不是刷新一条数据,而是整个页的数据都会刷新到磁盘里面去,这一步执行完成磁盘中的数据才真正修改了,ibd表文件才是真正地被修改了;
如果事务提交成功,bufferPool中的数据还没有来得及写入到磁盘里面,此时系统如果当机了,可以使用redo log日志中的数据恢复buffer pool中的缓存数据,然后再让后台线程将bufferPool中的数据刷新到磁盘里面,注意是恢复buffer pool中的数据,而不是写入到磁盘
10)为什么要使用redolog日志?
为了程序执行的效率,因为假设现在要执行10条SQL语句,操作10张表,此时的随机IO性能比较低,因为10张表的数据在不同的位置,磁针要来回地旋转找数据,磁头旋转比较慢,但是此时使用redolog日志里面都记录着具体的数据在那一个数据页上修改,最终进行写会到磁盘的时候是顺序IO,效率非常高,写磁盘是随机IO,要转动磁头更新数据,写日志是顺序IO只需要一条一条的纪录即可,来一条数据写一次磁盘,效率非常低;
11)下一次MYSQL再去查询数据的时候select * from user where userID=1的时候,发现buffer Pool中已经存在缓存数据了,就不会再次读取磁盘,而是直接返回"张三"
WAL机制:磁盘文件预先写的机制,Write ahead logging,真正存储数据的时候,先写磁盘的日志文件,再来刷新内存的数据到不同的.ibd表文件里面;
redolog:侧重于修改的数据还没有刷新到磁盘里面的时候,用于数据恢复的,假设数据库提交的时候系统突然宕机了,内存中的数据还没有来得及刷新到磁盘里面,此时redolog就用了起来
binlog:用于程序员不小心删除数据进行数据恢复
redolog的写入过程:writepos+checkpoint
1)redolog从第一个文件开始写,写完一个文件之后再来写另外一个文件,写到最后一个文件末尾之后又回到第一个文件开头来写,那么第一个文件的数据就会覆盖掉,环形写
2)write_pos代表当前记录的位置,一边写一边向后移动,写到第三个文件末尾以后就会到第0个文件开头,check point是当前要擦除的位置,他也是向后推移并且循环的,从上面的图来看,check point顺时针向下的数据都是真实的数据,如果发现write pos指针快要更新到check point那里了,于是就暂停,会尝试把check point后面的数据刷新到磁盘ibd文件里面,擦除记录前要把记录更新到数据文件里面,write_pos区间到check_point之间的顺时针数据就是可以写的部分,如果write_pos最终追上了check_point代表redo_log日志写满了,这个时候不能再执行新的更新,得停下来先擦除掉一些新的记录,将check_point向前推进一下;
3)redolog日志参数:
4)innodb_flush_log_at_trx_commit,这个参数用于控制redo log buffer中的数据写入到磁盘的过程:
4.1)设置为0表示每一次事务提交的时候都是把redo log中的数据留到redo log buffer中,数据库宕机可能会丢失数据,数据库如果宕机,那么数据直接丢失,效率是最高的,因为不会涉及到内存和磁盘的交互,如果允许数据库丢点数据,如果是大促,那么设置成0就可以,向银行的转账数据日志,重要数据一点也不能丢失,所以一般不设置成0,但是一般是电商的评论数据,可以设置成0;
4.2)设置为1(默认值)表示每次事务提交时都将redolog直接持久化到磁盘,数据最安全,不会因为数据库宕机丢失数据,但是效率最低,线上系统推荐这个设置,但是可靠性是最好的
4.3)设置为2:表示每次事务提交时都只是把redolog写到操作系统的缓存pagecache里,这种情况如果数据库宕机是不会丢失数据的,但是操作系统如果宕机了,pagecache里的数据还没来得及写入磁盘文件的话就会丢失数据,MYSQL宕机不会数据丢失,但是操作系统挂了,数据就没了,除此之外InnoDB还存在一个后台线程,每隔1s就会将redo log buffer中的日志写入到调用操作系统的write写入到文件系统的pathe中,在调用操作系统的函数fsysc刷新到磁盘文件;
查看innodb_flush_log_at_trx_commit参数值: 2show variables like'innodb_flush_log_at_trx_commit'; 3#设置innodb_flush_log_at_trx_commit 参数值(也可以在my.ini或my.cnf文件里配置): 4se tglobal innodb_flush_log_at_trx_commit=1;
redologbuffer是MYSQL接管的内存,oscache是操作系统内部接管的内存,只要将redo log buffer中的数据加载到os cache中,那么这里的数据基本都会刷新到磁盘上面去,如果对于数据的持久性要求没有那么高,那么MYSQL就认为写到page cache中就相当于存储成功,它的存在就是为了解决内存率先拿到磁盘效率比较低的问题;
五)binlog日志:二进制归档文件
binlog二进制日志文件记录保存了所有的执行过的修改操作语句,不会保存查询操作,如果MYSQL意外停止,可以通过二进制日志文件进行排查用户操作或者是表结构操作,从而来恢复数据库数据,但是开启binlog记录功能,会影响服务器性能,但是如果要开启恢复数据或者要实现主从复制,那么好出则大于服务器的影响,重启数据库后我们再去看data数据目录会多出两个文件,第一个就是binlog日志文件,第二个是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录;
show variables like "%bin_bin%",在MYSQL5.7中,binlog默认是关闭的,8.0版本默认是打开的,上图中的log_bin的值是OFF就代表binlog是关闭状态,打开binlog功能就需要修改配置文件中的my.ini(windows)和my.cnf(linux),然后重启数据库
1)binlog文件是可以稳定增长的,binlog大概有两种文件,mysql_binlog+数字(如果放满了胜场下一个文件,数字+1),mysql_binlog+index记录binlog一共有几个文件,会管理所有binlog文件的数目;
2)开启bing log配置以后往往还是需要开启一个参数叫做server-id,因为binlog要做主从同步,这个参数就是数据库的唯一标识,随便写一个数,主机和从机的ID不可以重复,不写也报错;
3)展示bin_log的个数:show binary binlogs;
4)expire_logs_day:执行自动删除距离当前15天以前的binlog日志文件的天数,默认是0,表示不自动删除,这个参数和恢复数据和MYSQL的备份策略有关系,配置这个参数让MYSQL定期去删除多少天之前binlog中的数据;
5)sql_log_bin来模拟主从复制异常,参数是ON表示SQL语句会写到binlog文件,OFF不需要写入;
查看和删除binlog日志文件:
1)可以用mysql自带的命令工具mysqlbinlog查看binlog日志内容,里面包含了具体执行的SQL语句以及执行时的相关情况,这是根据命令工具将binlog内容进行分析以后可见的,但是实际上是存储的二进制;
mysqlbinlog ‐‐no‐defaults‐v‐‐base64‐output=decode‐rows+binlog文件路径/文件名字
2)查看bin‐log二进制文件(带查询条件)
mysqlbinlog ‐‐no‐defaults‐v‐‐ base64‐output=decode‐rows D:/dev/mysql5.7.25winx64/data/mysql‐binlog.000007 start‐datetime="2023‐01‐2100:00:00" stop‐datetime="2023‐02‐0100:00:00" start‐position="5000"stop‐position="20000"
删除binlog文件日志:
删除指定日志文件之前的所有日志文件+删除指定日期之前的日志索引中的binlog日志文件
binlog的日志格式:
使用参数binlog_format来设置binlog文件的记录格式,MYSQL支持三种格式类型:
1)基于SQL语句的复制:STATEMENT,基于SQL语句的复制,每一条会修改数据的SQL都会记录到master机器的binlog里面,这种方式日志量比较小,节省IO资源的开销,提升性能,但是对于一些在执行过程中才会确定的函数,比如说UUID和SYSDATE()等函数如果随着SQL同步到从机上去执行,结果可能和主机上执行的最终结果不一样;
2)ROW:是基于行的复制算法,日志中会进行记录每一行被修改的时候的格式,然后slave机器再针对相同的数据做一下每一啊行数据被修改的细节,可以有效地解决函数存储过程等在slave从机中复制问题,但是这种方式日志量比较大,性能不如第一种,举个例子,假设update语句更新10行数据,Statement方式就记录这条update语句,Row方式会记录被修改的10行数据;
3)混合模式复制:混合模式复制,实际就是前两种模式的结合,在Mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种,如果sql里有函数或一些在执行时才知道结果的情况,会选择Row,其它情况选择Statement,推荐使用这一种
binlog的写入磁盘机制:
redolog是在存储引擎层的,里面有redo log buffer和操作系统的缓存,但是binlog是Server层,只是存在着操作系统的缓存,要么写磁盘文件,要么写到操作系统缓存里面
binlog写入磁盘的策略是按照sync_binlog的参数来进行控制的,默认值是0
1)当这个值是0的时候,表示每一次提交事务的时候都只是写到操作系统的page cache中,有系统决定什么时候写入到binlog磁盘里面,虽然性能得到了提升但是如果机器宕机,page cache中的binlog数据会丢失
2)当这个值设置成1的时候,表示每一次提交事务的时候都会有fysc写入到磁盘,这种方式最安全;
3)还有一种比较折中的方式,可以设置成N,表示每一次提交事务的时候都先写到page cache,N个事务提交以后才写入到磁盘,但是这种情况下事务宕机会丢失N个事务的数据
当发生以下事件的时候,binlog文件会重新生成:
1)服务器启动或者是重新启动
2)服务器刷新日志,执行命令 flush logs
3)日志文件大小达到max_binlog_size的值,默认值是1GB
binlog磁盘数据恢复:本质上就是回放,执行binlog中的SQL语句,再来执行一次
找到两条插入数据的sql,每条sql的上下都有BEGIN和COMMIT,我们找到第一条sqlBEGIN前面的文件位置标识at219,这是文件的位置标识,再找到第二条sqlCOMMIT后面的文件位置标识at701
1)at+数据表示binlog文件的偏移位置,就是MYSQL在进行记录binlog文件的时候会记录一些关键偏移位置,binlog还有一些时间戳,特别是执行一些特殊的SQL语句就是一个事务都会有时间戳的,开启一个事务是啥时间会记录下来,结束事务的时候也会有时间戳;
假设原来我新增了两条数据,有执行了修改操作,现在有程序员不小心把这两条数据删了
2.1)首先查询binlog文件的内容:定位到原来的新增的SQL语句和修改的SQL语句,注意删除的SQL语句就不要再做数据恢复了;
2.2)有两种恢复方式,第一种是根据文件的偏移量,找到第一条SQL语句事务begin开启时候的上面的最近偏移位置,一些事务的开启都会记录偏移位置,然后记录最后一条SQL语句执行完成之后的最近的文件偏移量,也可以根据时间戳,但是要进行格式转换
mysqlbinlog ‐‐no‐defaults ‐‐start‐position=219 ‐‐stop‐position=701 ‐‐database=testD:/dev/mysql‐5.7.25‐winx64/data/mysql‐binlog.000009 |mysql ‐uroot ‐p 123456 ‐v test
mysqlbinlog --nodefaults是固定写法
第二行表示要回滚binlog的起始位置和终止位置,第三个参数表示下面是binlog文件位置,你要恢复哪一个数据库;
1)刚才这种情况只是删除了几条记录,做数据恢复只需要找到对应的binlog文件找到开始点和结束点就可以了,但是假设把数据库全删了,该如何进行数据恢复呢,如果说你的binlog文件一直没有被删除,那么可以找到第一个binlog文件,逐个去进行恢复,就不需要加时间参数,一个一个地去恢复,binLog文件在MYSQL服务启动之初就一直存在;
2)但是一般来说不可能存放全量的binlog,防止把磁盘撑爆,expire_logs_day这个参数可以让MYSQL定期去清理bin_log文件,可以让MYSQL定期清理多少天之前的binlog文件,这个值具体要配置多少还是要根据数据库的备份策略来做,只会存储最近的修改的修改的bin log日志文件;
3)如果把数据库全删了,假设binlog是记录的最近15天的数据,那么你必须有一次备份是在15天以内的,如果你备份的是20天以前的数据,那么中间5天的数据就会丢失,你必须先把20天以前的数据恢复,中间的数据没了,所以恢复失败;你的binlog删除时间和数据库的备份策略尽可能有关联,推荐一天备份一次,比如说每天凌晨当天数据库最空闲的时候,做一次全量数据库备份,万一binlog那个参数等于7,那么7天之前的数据都会删除掉,假设今天下午2点公司员工删库跑路,使用当天2点钟备份见整个数据库中的记录恢复到2点钟那一时刻,然后从binlog文件恢复凌晨两点钟到如今的所有binlog文件数据,在binlog删除7天之内的数据的时候必须有一次数据备份;
4)虽然是每天备份一次,但是不要binlog只是保留一天,不要这么干,binlog有效时间尽量要比备份时间多几天,因为假设今天早上备份脚本没有跑成功,如果binlog配置的是一天或者是半天,所以数据一定丢失,或者是昨天没有备份成功;
错误日志:MYSQL还有一个比较重要的日志是错误日志,它记录了数据库启动和停止,以及运行过程中的发生任何严重错误的时候的相关信息,当数据库发生任何故障导致无法正常使用的时候建议先查看此日志,在MYSQL种错误查询日志是默认开启的况且无法进行关闭
1#查看错误日志存放位置 2showvariableslike'%log_error%';
通用查询日志:通用查询日志记录着用户的所有操作,包括开启和启动MYSQL服务器,所有用户开始的连接和截止时间,发给MYSQL所有的SQL指令,比如说show select等等,无论是SQL的执行成功还是失败都会记录下来,通用查询日志用于准确定位一些疑难问题,比如说重复支付等问题;
六)binlog和redolog的区别?
1)binlog是MYSQL的服务器层的日志,用于记录对于数据库执行的所有修改操作,包括插入删除更新操作等等,她以二进制的格式被记录,主要用于主从复制和数据恢复等操作,但是redolog是存储引擎层的日志,只有InnoDB存储引擎存在,用于确保数据库数据的持久性,确保在数据发生崩溃的时候对于数据库的修改可以恢复;
2)binlog记录的是逻辑上面的操作,就是执行的SQL的语句或者是记录行,但是redo log记录的是数据页的物理层面上的修改
3)binlog是事务提交以后才会生成,他是持久化的,是循环写入的,它的数据写入到磁盘上的文件中在发生崩溃时,通过 redolog的重做操作,可以将数据库恢复到崩溃前的一致状态
4)binlog 可以被配置为不同的格式,包括基于语句的复制(statement-based replication)、基于行的复制(row-based replication)和混合复制(mixed replication)
5)binlog 用于记录逻辑层面的操作,可以用于数据复制和恢复,而 redolog 用于记录物理层面的操作,确保事务的持久性和崩溃恢复。它们在功能和使用上有一些不同,但都是 MySQL 中重要的日志机制
七)distinct和group by有什么区别?
1)查询的结果集不同:当使用到distinct进行去重的时候,查询结果集只有去重的列的信息,但是group by查询时可以查询一个或者是多个字段的,group by可以进行单列去重,group by的原理是先对结果进行分组排序,然后返回每组中的第一条数据;
2)使用场景不同:统计去去重后的总数量需要使用到distinct,而统计分组明细,在分组明细的基础上去添加查询条件,就需要使用到group by了
3)执行效率不同:当去重的字段有索引的时候它们的性能都是差不多的,但是当驱虫的字段没有索引的时候,distinct的性能就要高于group by,因为在MYSQL8.0之前group by有一个隐藏的功能会进行默认的排序