mysql相关日志学习笔记

相关日志

1. 错误日志:-log-err 在my.cnf中的mysqld节配置log-error=E:/wamp/logs/mysql_error.log,或是在启动数据库时 --log-error='/var/usr/local/mysql/log/local_error.log'

2. 查询日志(记录所有SQL语句):

show variables like '%general_log%'

set global general_log=1 --开启全局日志,开启后所有SQL,set global log_output='table',会被记录一张表中mysql.general_log,

或是set global log_output='file ,set global general_log_file='/tmp/general.log'

在my.cnf中的mysqld节配置,以上可以在mysqld节点配置,或是在数据库启动时--general-log=1开启或0关闭,--log-output='TABLE,FILE'可同时输出到表和文件,表是mysql.general_log,--general-log-file='/var/usr/local/mysql/log/general.log',如果在session级别控制,则可以在session中 set sql_log_off='on'或sql_log_off='off'

3. 慢查询日志:-log-slow-queries      

1) 查看慢查询时间     show variables like "long_query_time";默认10s   

2) 查看慢查询配置情况     show status like "%slow_queries%";    

3) 查看慢查询日志路径     show variables like "%slow%"; //存储位置、长SQL的阈值 E:\wamp\bin\mysql\mysql5.6.12\data\LittleHann-PC-slow.log long_query_time=5

set global slow_query_log=1临时开启慢查询日志

永久开启my.cnf

[mysqld]

slow_query_log=1

slow_query_log_file=/var/lib/mysql/xxx-slow.log

set long_query_time=5,是5秒,然后重新登录

开启慢查询日志后与创建存储过程冲突,用set global log_bib_trust_function_creators=1,这是临时解决方案,永久解决需要在my.cnf中的mysqld节加入log_bin_trust_function_creators=1配置

当用--slow_query_log=0或1关闭或开启, --slow_query_log_file=慢查询日志路径,可以使用--log-output=FILE或TABLE指定日志输出到文件或表mysql.slow_log

设置微秒级查询set global long_query_time=0.01,可以用mysqldumpslow查看慢日志文件内容。

mysqldumpslow -s r -t 3 文件名

mysqldumpslow -s c -t 3 文件名

mysqldumpslow -s s -t 10 -g 文件名

5. 二进制日志:-log-bin//记录除select语句之外的所有sql语句到日志中,可以用来恢复数据文件log-bin=E:/wamp/logs/bin;在启动是 --log-bin=0或1关闭或启动,如果没有给出文件名,会将主机名加上-bin作为文件名,默认写到datadir指定的目录。bin-log有三种格式:

statement、row、mixed,三种格式区别如下:

statement:日志中记录的都是sql语句,可以通过mysqlbinlog看到相关sql语句。优点:日志清晰易读,日志量少,对I/O影响小。缺点在某些情况下slave的日志会出错。

row:将每一行变更记录到日志中。优点:记录每一行记录变化的细节,不会出现在某些情况下无法复制的情况。 缺点:日志量大,对I/O影响较大。

mixed:这是mysql5.5的默认格式,mysql5.6的默认格式是statement,mysql5.7的默认格式是row。采用这种格式默认情况下用statement记录,但在一些特殊情况下用row来进行记录。比如采用了NDB存储引擎,此时对表的DML全部用row;客户端用了不确定的函数,比如current_user(),因不确定函数在主从中得到的值可能不同,导致主从数据库不一致。mixed尽可能利用他们的优点,避开他们的缺点。可以在global和session对binlog_format格式进行设置。

 

 

MySQL的binlog有有几种录入格式?分别有什么区别?

有三种格式,statement,row和mixed。

statement模式下,每一条会修改数据的sql都会记录在binlog中。不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。由于sql的执行是有上下文的,因此在保存的时候需要保存相关的信息,同时还有一些使用了函数之类的语句无法被记录复制。

row级别下,不记录sql语句上下文相关信息,仅保存哪条记录被修改。记录单元为每一行的改动,基本是可以全部记下来但是由于很多操作,会导致大量行的改动(比如alter table),因此这种模式的文件保存的信息太多,日志量太大。

mixed,一种折中的方案,普通操作使用statement记录,当无法使用statement的时候使用row。

此外,新版的MySQL中对row级别也做了一些优化,当表结构发生变化的时候,会记录语句而不是逐行记录。

 

binlog日志读取:mysqlbinlog log-file

日志删除:

方法1:rest master该命令将删除所有binlog日志,新日志编号从000001开始。查看删除前日志:

system ls -ltr 日志文件名前缀,如localhost-bin*

方法2:purge master logs to 'mysql-bin.00012'命令将删除12号之前所有日志

方法3:purge master logs to 'yyyy-mm-dd hh24:mi:ss',将删除该日期之前所产生的所有日志。

方法4:设置参数,--expire_logs_days=122,此参数的含义是设置日志的过期天数,过了指定的天数后将自动删除。在my.cnf中的mysqld节点expire_logs_day=3;用mysqladmin flush-log 触发日志文件更新。--binlog-do-db=db_name告诉主服务器只记录该数据的binlog,--binlog-ignore-db=db_name不将该数据库的binlog记录到日志中。如果有多个就需要多次引用 --binlog-ignore=db=xxx,或--binlog-db-name=sdd;

 

 

启动binlog:set sql_log_bin=0或1关闭或是开启;--innodb-safe-binlog此选项经常的--sync-binlog=N(是批积累了多少个事务后同步到磁盘数据文件)

 

如果想在主库上执行一些操作,但不复制到slave库上,可以通过修改参数sql_log_bin来实现。

比如想在主库上修改某个表的定义,但是在slave库上不做修改:

master mysql> set sql_log_bin=0;#设为0后,在Master数据库上执行的语句都不记录binlog

master mysql> alter table test1 drop index idx_id add index (id,username);

master mysql> set sql_log_bin=1;

 

 

6. 分析海量数据

show profiles --默认关闭,会记录所有查询语句

show variables like '%profiling%'

set profiling=on ;

show query for 上面查询出来的query id

show profile all(或是cpu block io) for query 上面查询出来的query id

 

redolog和binglog

存储引擎在修改表的数据时只需要修改其内存拷贝,再把修改行为的记录持久到硬盘上的事务日志中,而不用每次都将数据本身持久到磁盘。事务日志采用追加的方式,因此写日志操作是操作磁盘内顺序I/O,会非常快,事务持久以后,被修改的数据可在后台慢慢的刷回到磁盘。这种方式称为write-ahead-logging,修改数据需要写两次磁盘。如果修改的数据已记录到事务日志并持久化,但还还没有写回磁盘,此时发生系统崩溃,在重启时会自动恢复这部分修改的数据。

修改事务隔离级别:set session transaction isolation level read commited;

 

innodb的redolog和binlog只记录了数据页的改变部分,并未记录数据页完整的镜像。

用系统表空间中一段连接磁盘空间(100个数据页,2M)作为doubble write buffer。当进行刷脏页时,首先将脏页(内存中的数据)的副本写到系统表空间的doubble write buffer(即redo log 在磁盘中的顺序存储空间),然后调用fsync()刷新操作系统的I/O缓存。确保副本被真正写磁盘(即redo log 在磁盘中的顺序存储空间),最后innodb后台IO线程将脏页(内存中的数据)刷新到磁盘数据文件。(这里需要参考redolog和binlog的两阶段提交过程及相关参数设置,并不一定是脏页,可能是redolog磁盘数据,即double write buffer)。

 

1、正常运行中的实例,数据写入后的最终更新磁盘,是把内存中的数据页写盘。这个过程与redolog毫无关系。

2、在做崩溃恢复时,如果发现不一致的页,即一个数据页可能在崩溃恢时丢失了更新,将磁盘数据读到内存,innodb会用系统表空间的doublewrite buffer区相应的副本来恢复读入内存的数据页(即将redolog file 中的变更应用到内存,然后如果内存数据页和磁盘的数据不一致,即将可能发生刷脏页

3、默认double write是开启的,对于要求超高性能。可以设置innodb_doublewrte=0,来满足性能。

 

redolog:重做日志,innodb引擎特有的。固定大小,一组4个文件,每个1GB,物理日志,可循环写,保证innodb具有crash safe 能力。redolog file存在磁盘中一小块有序存储空间。redo log 只是用来作崩溃恢复用的,即将redo log中的变更数据应用到相应的内存数据页中。

 

redolog在prepare阶段是指已将日志写到redolog buffer,即mysql的进程的内存中,不是每次生成后都要写到redo log 的磁盘顺序空间,因为这时还没有到commit步骤(不是sql语句的commit,这个),即使crash了,日志丢了也没关系;另外在还没有到commit步骤(不是sql语句的commit)时,redo log buffer中的数据也是有可能写到redo log file中的,即磁盘顺序空间。

redolog三种状态:

a:在内存中,即redo log buffer中

b:物理上是在page cache中,即磁盘顺序写空间,但没有持久化fsync

c:持久化到磁盘,对应的是hard disk

写redo log buffer 是很快的要,write到page cache(page files)也差不多,但持化到磁盘速度慢多了。

innodb_flush_log_at_trx_commit:控制redo log写入策略。控制redo log buffer(在内存中)更新记录写入到日志文件(一小块顺序磁盘存储空间)以及将日志文件数据(内存中数据页即脏页)刷到磁盘数据文件的时机。

0:表示在事务提交时,不会立即触发将缓存日志(内存中的redolog数据)写到磁盘(顺序I/O)文件,而是每秒触发一次缓存日志(内存中的redolog数据)写到顺序存储空间,并调用操作系统fsync刷(I/O)缓存(内存中的数据脏页)到磁盘数据文件中。只是将redolog 留在redo log buffer中。

 

1:表示立即写到磁盘(page cache顺序I/O),并调用fsync刷(I/O)缓存(内存中的数据脏页)到磁盘数据文件。每次事务提交时都将redlo log直接持久化到磁盘 page cache(顺序写空间)。

 

2:表示立即写到磁盘(page cache顺序I/O),但并不马上调用fsync来刷I/O缓存(内存中的数据脏页),而是每秒只做一次磁盘I/O缓存(内存中的数据脏页)刷新操作。设置为2,如果数据库崩溃,由于日志已写到顺序磁盘空间(page cache顺序I/O),只要不发生操作系统崩溃,重启后不会数据丢失(根据下面的崩溃改恢复逻辑)。每次事务提交时都只是把redolog写到page cache(顺序写空间)

innodb 有一个后台线程,每隔1秒,就会把redolog buffer 中的日志调用write写到文件系统中的page cache,然后调用fsync持久化到磁盘。

 

注意:事务执行中间过程的redolog也是直接写在redo log buffer中的, 这些redo log 也会被后台线程一起持久化到磁盘。也就是说,一个没有提交的事务的redolog也是可能已经持久化到磁盘的。

这有两种情况:

a:redo log buffer占用的空间达到innodb_log_buffer_size的一半时,后台线程主动写盘,即将内存中的redo log直接定到磁盘顺序空间(只write ,没有调用fsync,redolog 留在了page cache中)。

b:并行事务提交时顺带将这个事务的redo log buffer持久化到磁盘(page cache ,只调用了write,没有调用fsync)。

需要说明的是,两阶段提交的时候,时序上redo log 先prepare,再写binlog,最后再把redo log commit,如果innodb_flush_log_at_trx_commit=1,那么redolog在prepre阶段就要持久化一次,因为有一个崩溃恢复逻辑要依赖于prepare的redolog,再加上binlog来恢复的。每秒一次的后台轮询刷盘,再加上崩溃恢复的逻辑,innodb就认为redo log 在commit的时候就不需要fsync了,只会write到文件系统的page cache中就够了。

 

redolog崩溃恢复过程:

a:redolog和binlog都没有提交,即两个文件中都没有commit标识,则在数据库崩溃恢复后,通过redolog直接回滚事务

b:redolog和binlog都提交了,即redolog中有commit标识,binlog在statement格式下有commit标识,在row格式下有xid event,则在数据库崩溃恢复后,通过redolog提交事务

c:redolog提交了,即redolog中有commit标识,则在数据库崩溃恢复后,从redolog提交事务,此时会产生新的binlog(用于复制等异构计算),不会再次生这个redolog。

d:redolog有prepare,无commit标识,再判断binlog是否存在并完整,若完整 ,则通过redolog提交事务,否则回滚事务

redolog和binlog是怎么关联起来的:

有一个共同的字段xid,崩溃恢复时,按顺序扫描redolog

a:如果碰到既有prepare又有commi的redolog就直接提交

b:如果碰到只有prepare,而没有commit的redolog,就拿关xid去binlog找对应的事务。

binlog没有能力恢复数据页,redolog file在page cache中不是完整的数据页,所以,刷脏页是指将内存中的数据写入磁盘中的数据文件。

 

binglog:归档日志,mysql server层实现的,所有引擎都可以使用。大小不定,逻辑日志,追加写达到一定大小会切换到下一个文件,不会覆盖以前的日志。只是用来作为归档和复制及其他异构计算使用。

binlog写入机制:事务执行过程中,先把日志写到binglog cache中,即内存中,没有到commit步骤(这里不是指sql语句的commit)时,再把binlog cache 写到binlog文件即磁盘的数据文件。一个事务的binlog是不能拆开的,因此不论这事务多大也要确定一次性写入。系统给binlog cache分配了一片内存,每个线程参数binlog_cache_size用于控制单个线程内binlog cache所占内存的大小。如果超过了这个参数规定的大小,就要暂存到磁盘。

 

到了commit(非sql的commit)步骤时,执行器把binlog cache中的完整事务写入到binlog(就是顺序写磁盘page cache)中,并清空binlog cache。每个线程有自己的binlog cache,但共用同一份binlog文件。

write指的就是把日志写入到文件系统的page cache binlog files(就是顺序写磁盘page cache binlog files),并没有持久化到磁盘,所以速度比较快;fsync才是将数据持久到磁盘操作,才占IOPS;

提升binlog组提交效果:设置binlog_group_commit_sync_delay表示延迟多少秒后才调用fsync和binlog_group_commit_sync_no_delay_count表示累积多少次后才调用fsync。两个条件是或关系,只要有一个条件满足就会调用fsync.当binlog_group_commit_sync_delay=0时,binlog_group_commit_sync_no_delay_count也就无效了。组提交机制可以大幅降低磁盘的IOPS消耗。

 

sync_binlog:此参数控制write和fsync的时机。

设置为1时表示每次事务提交binlog都持久化到磁盘,即执行fsync。设置1可以保证mysql异常重启之后的binlog不丢失。0:每次提交事务只write,即写到page cache中,并没有持久化到磁盘,不fsync;sync_binlog=N(N>1),表示每次提交事务都write,即写到page cache中,但累积N个事务后才fsync,即持久化到磁盘。比较常见的是将其设置为100到1000中的某个数值。

innodb_log_file_size:是指redo log的日志文(顺序磁盘空间)件大小;

innodb_log_buffer_size:表示redlo log 在内存中的大小,默认8M,增加此量的大小:可以避免innodb在事务提交前就执行不必要的日志写入磁盘操作,即执行过程还没有commit(两阶段的commit),就将缓存写到了redo log的顺序空间。所以增加此值可以减少日志写磁盘操作。从而提高事务处理性能。

两阶段提交流程:深色在执行器内执行,浅色在innodb引擎中执行

 

 

undolog:innodb每个事务有一个唯一的事务id,叫作transaction id ,在事务开始时向innodb事务系统申请的,申请时按顺序严格递增的,每行数据有多个版,每次事务更新时,都会生成一个新的数据版本,且把transaction id赋值给这个数据版本的事务id,记为row trx_id,同时,旧的数据版本要保留,并且在新的数据版本中能够有信息可直接拿到它。也就是说数据表中一行记录,可能有多个版本(row),每个版本有自己的 row trx_id。如图所示就是一条记录被多个事务连续更新后的状态:

 

有4个版本,最新是V4。row trx_id和transaction id相同。图中的u1和u2,u3就是undolog。v1、v2、v3并不是物理上真实的存在,每次需要时候根据当前版本和undo log计算出来的。

 

innodb是怎么快速定义快照的。按可重复读定义:一个事务启动的时候能够看到所有已经提交的事务结果,但是之后,在这个事务执行期间,其他事务的更新对它不可见。 innodb为每个事务构造了一个数组,用来保存这个事务启动瞬间当前正在活跃的所有事务ID,活跃是指启动了但还没提交。数组里面事务id最小值记为低水位,当前系统里面已经创建过的事务id的最大值加1记为高水位。这个视频数组和高水位就组成了当前事务的一致性视图。而数据版本的可见性规则,就是基于数据的row trx_id的这个一致性视图的对比结果得到的。这个视图数组把所有的row trx_id分成了几种不同的情况:

 

 

 

row trx_id有三种情况:

a:绿色部分,表示这个版本日已提交或是自己生成的事务,可见

b:红色部分,表示这个版本是由将来的启动的事务生成的,是肯定不可见的。

c:黄色部分,有两种情况c-1:若row trx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见,c-2:若row trx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。

innodb利用了所有数据都有多个版本的这个特必,实现了秒级创建快照的能力

 

show engine innodb status命令查看当前日志的写入情况。

更新数据操作流程:

1、将数据读入innodb buffer pool中,对相关记录加独占锁

2、将undo信息写入到undo表空间的回滚段中

3、更改缓存页中的数据,并将更新记录写入redo log buffer中

4、提交时,根据innodb_flush_log_at_trx_commit,用不同的方式将redo log buffer刷 到redo log file(顺序写),然后释放独占锁

5、IO线程根据需要择机将缓存(内存中的数据页,即脏页)中的更新过的数据刷新到磁盘数据文件中

 

分析日志工具

可以用mysqlsla工具,是mysql statement log analyzer的缩写,可以从http://hackmysql.com/mysqlsla下载

最基本用法:

mysqlsla --log-type slow LOG ; mysqlsla --log-type general LOG;

解析二进制日志

mysqlbinlog LOG| mysqlsla --log-type binary -; 解析微秒日志: mysqlsla --log-type msl LOG

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值