【精选】MySQL日志(log 您所在的位置:网站首页 log和login的区别 【精选】MySQL日志(log

【精选】MySQL日志(log

2023-11-10 07:06| 来源: 网络整理| 查看: 265

文章目录 一、MySQL日志缓存二、MySQL错误日志(log_error)三、MySQL普通查询日志(general_log)四、MySQL慢查询日志(slow_query_log)五、二进制日志(log_bin)(一)开启二进制日志(二)二进制日志格式(三)日志读取(四)二进制日志的清理 六、InnoDB 事务日志重做日志(redo log)回滚日志(undo log)Checkpoint机制脏页(dirty page)日志序列号(log sequence number) 七、日志文件备份 日志是 mysql 数据库的重要组成部分,记录着数据库运行期间各种状态信息。

默认情况下,所有的MySQL日志以文件的方式存放在数据库根目录下(除过在/etc/my.cnf指定某些日志具体的存放位置):

[root@localhost ~]# cd /usr/local/mysql/data/ [root@localhost data]# ls auto.cnf ca.pem ib_logfile0 mysql.ibd server-key.pem binlog.000001 client-cert.pem ib_logfile1 performance_schema sys binlog.000002 client-key.pem ibtmp1 private_key.pem undo_001 binlog.index ib_buffer_pool #innodb_temp public_key.pem undo_002 ca-key.pem ibdata1 mysql server-cert.pem

MySQL的日志类型有以下几种:

错误日志(error),MySQL服务实例启动、运行或者停止等相关信息。普通查询日志(general),MySQL服务实例运行的所有SQL语句或者MySQL命令。二进制日志(binary),对数据库执行的所有更新语句,不包括select 和show语句。慢查询日志(slow),执行时间超过long_query_time 设置值的SQL语句,或者没有使用索引的SQL语句。事务日志:InnoDB存储引擎所特有。InnoDB事务日志包括重做(redo)日志,以及回滚(undo)日志 一、MySQL日志缓存

一个高速、稳定、可靠的系统,缓存在其中必定起着至关重要的作用。MySQL日志处理也使用了缓存机制。MySQL日志最初存放在MySQL服务器的内存中,若超过指定的存储容量,内存中的日志则写(或者刷新flush)到外存中,以数据库表或者以文件的方式永远的保存在硬盘中。

二、MySQL错误日志(log_error)

MySQL的错误日志主要记录MySQL服务实例每次启动、停止的详细信息,以及MySQL实例运行过程中产生的警告或者错误信息。和其他的日志不同,MySQL的error日志必须开启,无法关闭。

默认情况下,错误日志的文件名为: 主机名.err。 但error 日志并不会记录所有的错误信息,只有MySQL服务实例运行过程中发声的关键错误(critical)才会被记录下来。

mysql> show variables like 'log_error'\G *************************** 1. row *************************** Variable_name: log_error Value: /var/log/mysql-error.log 1 row in set (0.16 sec)

配置文件中写法:

log_error = /var/log/mysql-error.log 三、MySQL普通查询日志(general_log)

MySQL普通查询日志记录MySQL服务实例所有的操作,如select、update、insert、delete等操作,无论该操作是否成功执行。还有MySQL客户机与MySQL服务端连接及断开的相关信息,无论连接成功还是失败。与MySQL普通查询日志有关的参数有三个。

general_log mysql> show variables like 'general_log'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | general_log | OFF | +---------------+-------+ 1 row in set (0.05 sec) # 该日志功能关闭

可以通过 set @@global.general_log = 1的方式来开启普通查询日志。

mysql> set @@global.general_log =1; Query OK, 0 rows affected (0.18 sec) mysql> show variables like 'general_log'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | general_log | ON | +---------------+-------+ 1 row in set (0.07 sec)

但是通过这种方式修改MySQL的变量只会在当前的MySQL实例运行期间生效,一旦MySQL重启,则会重新恢复到默认的状态。

永久生效的方式是修改mysql 的my.cnf 文件。在配置文件后添加:

general_log = 1 general_log_file = /file/path general_log_file

普通查询日志一旦开启,MySQL服务实例将自动创建普通查询日志文件,general_log_file参数设置了普通查询日志文件的物理位置。如下:

mysql> show variables like 'general_log_file'; +------------------+-------------------------------------+ | Variable_name | Value | +------------------+-------------------------------------+ | general_log_file | /usr/local/mysql/data/localhost.log | +------------------+-------------------------------------+ 1 row in set (0.05 sec)

注意:由于普通查询日志几乎记录了MySQL的所有操作,对于数据访问频繁的数据库服务器而言,如果开启MySQL的普通查询日志将会大幅度的降低数据库的性能,因此建议关闭普通查询日志。只有在特殊时期,如需要追踪某些特殊的查询日志,可以临时打开普通的查询日志。

log_output

log_output参数设置了普通查询日志以及慢查询日志的内容存储到数据库表中。 可以使用set @@global.log_output='table'将普通查询日志及慢查询日志存入mysql系统数据库中的general 表 以及slow_log 表中。值得注意的是这两个表的存储引擎为CSV,此后查看新的普通查询日志内容时便可以使用SQL语句;

mysql> show variables like 'log_output'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_output | FILE | +---------------+-------+ 1 row in set (0.07 sec) mysql> set @@global.log_output = 'table'; Query OK, 0 rows affected (0.15 sec) mysql> show variables like 'log_output'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_output | TABLE | +---------------+-------+ 1 row in set (0.07 sec) mysql> desc mysql.general_log\G; *************************** 1. row *************************** Field: event_time Type: timestamp(6) Null: NO Key: Default: CURRENT_TIMESTAMP(6) Extra: DEFAULT_GENERATED on update CURRENT_TIMESTAMP(6) *************************** 2. row *************************** ……省略以下输出内容…… 四、MySQL慢查询日志(slow_query_log)

使用MySQL慢查询日志可以有效的跟踪 执行时间过长 或者 没有使用索引的查询语句。这种包括select 语句,update语句,delete语句,以及insert语句,为优化查询提供帮助。与普通查询日志不同的另一个区别在于,慢查询日志只包含成功执行过的查询语句。与MySQL慢查询日志有关的参数有5个。

slow_query_log

slow_query_log 设置慢查询日志是否开启。

mysql> show variables like 'slow_query_log'; +----------------+-------+ | Variable_name | Value | +----------------+-------+ | slow_query_log | OFF | +----------------+-------+ 1 row in set (0.08 sec)

可以通过set @@global.slow_query_log = 1的方式来开启普通查询日志。

mysql> set @@global.slow_query_log = 1; Query OK, 0 rows affected (0.19 sec)

以上方式是临时性的,永久配置要在/etc/my.cnf配置文件中设置:

slow_query_log = 1 slow_query_log_file

慢查询日志一旦开启,MySQL实例将自动创建慢查询日志文件。slowquerylog_file 所指定的文件,存放慢查询日志内容。

mysql> show variables like 'slow_query_log_file'; +---------------------+-------------------------+ | Variable_name | Value | +---------------------+-------------------------+ | slow_query_log_file | /var/log/mysql-slow.log | +---------------------+-------------------------+ 1 row in set (0.09 sec)

配置文件中写法:

slow_query_log_file = /file/path long_query_time

long_query_time 设置了慢查询的时间阈值。默认阈值是10s。

mysql> show variables like 'long_query_time'; +-----------------+-----------+ | Variable_name | Value | +-----------------+-----------+ | long_query_time | 10.000000 | +-----------------+-----------+ 1 row in set (0.08 sec)

修改:

mysql> set @@global.long_query_time=9;

或在配置文件中设置:

long_query_time =10 log_quries_not_using_indexes

log_quries_not_using_indexes 是否将不使用索引的查询语句记录到慢查询日志中,无论查询速度有多快。

mysql> show variables like 'log_queries_not_using_indexes'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | log_queries_not_using_indexes | OFF | +-------------------------------+-------+ 1 row in set (0.10 sec)

开启

mysql> set @@global.log_queries_not_using_indexes=1; Query OK, 0 rows affected (0.05 sec) mysql> show variables like 'log_queries_not_using_indexes'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | log_queries_not_using_indexes | ON | +-------------------------------+-------+ 1 row in set (0.07 sec)

或在配置文件中设置:

global.log_queries_not_using_indexes=1 log_output

log_output参数可以设置慢查询日志的输出形式。默认为FILE,可以设置为TABLE

mysql> show variables like 'log_output'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_output | TABLE | +---------------+-------+ 1 row in set (0.06 sec) mysql> desc mysql.slow_log; +----------------+---------------------+------+-----+----------------------+--------------------------------------------------+ | Field | Type | Null | Key | Default | Extra | +----------------+---------------------+------+-----+----------------------+--------------------------------------------------+ | start_time | timestamp(6) | NO | | CURRENT_TIMESTAMP(6) | DEFAULT_GENERATED on update CURRENT_TIMESTAMP(6) | | user_host | mediumtext | NO | | NULL | | | query_time | time(6) | NO | | NULL | | | lock_time | time(6) | NO | | NULL | | | rows_sent | int(11) | NO | | NULL | | | rows_examined | int(11) | NO | | NULL | | | db | varchar(512) | NO | | NULL | | | last_insert_id | int(11) | NO | | NULL | | | insert_id | int(11) | NO | | NULL | | | server_id | int(10) unsigned | NO | | NULL | | | sql_text | mediumblob | NO | | NULL | | | thread_id | bigint(21) unsigned | NO | | NULL | | +----------------+---------------------+------+-----+----------------------+--------------------------------------------------+ 12 rows in set (0.11 sec)

其中: lock_time表示该SQL执行时被锁阻塞的时间。 rows_send表示执行SQL后返回的内容行数。 rows_examined表示该SQL执行时实际扫描的记录条数。

但是使用TABLE来存储慢查询日志并不常见,业务量较大的情况下,对于系统的主服务会有影响。我们可以使用FILE 的方式来进行日志存储。安装MySQL的时候在MySQL的bin目录下已经默认安装了 mysqldumpslow 工具来进行慢查询的日志分析

mysqldumpslow命令用法: -s 表示按照何种方式排序 子选项: c、t、l、r c : SQL执行的次数 t : 执行时间 l : 锁等待时间 r : 返回数据条数 at、al、ar 是对应 t l r 的平均值。 -t :表示返回前 N 条记录。 -g: grep 缩写。包含模糊匹配

常用法如下:

# 返回访问次数最多的20条SQL语句 mysqldumpslow -s c -t 20 /var/log/mysql-slow.log # 返回return记录数最多的20条SQL语句 mysqldumpslow -s r -t 20 /var/log/mysql-slow.log # 返回含有like的SQL语句 mysqldumpslow -g 'like' 20 /var/log/mysql-slow.log 五、二进制日志(log_bin)

二进制日志:binary log。简称binLog。记录了对Mysql数据库执行更改的所有操作,但是不包括SELECT 和 SHOW这类操作。以二进制的形式保存在磁盘中。是属于Mysql Server层记录,任何存储引擎的 mysql 数据库都会记录binlog日志。并且binlog 还是 mysql 的逻辑日志。

逻辑日志:可以简单理解为记录的就是sql语句

物理日志:mysql 数据最终是保存在数据页的,物理日志记录的就是数据页变更

binlog 的主要使用场景有两个,分别是 主从复制 和 数据恢复

主从复制:在 Master 端开启 binlog,然后将 binlog 推送到各个 Slave 从端,Slave 端重放 binlog 从而达到主从数据一致

数据恢复:通过使用 mysqlbinlog 工具来恢复数据

二进制日志和前面提到的几种日志不同,二进制不能直接通过cat或者less 文本查看器查看。需要借助专业的工具。

二进制日志主要记录数据库的变化情况,因此可以用作主从库的同步。内容主要包括数据库所有的更新操作,use语句、insert语句、delete语句、update语句、create语句、alter语句、drop语句。用一句更简洁易懂的话概括就是:所有涉及数据变动的操作,都要记录进二进制日志中。

使用 show variables like ‘log_bin’\G 来查看二进制日志是否开启。

mysql> show variables like 'log_bin'\G; *************************** 1. row *************************** Variable_name: log_bin Value: OFF 1 row in set (0.08 sec)

log_bin 默认是不开启的,并且是个只读的变量,需要在my.cnf中配置,并配置MySQL日志的格式。然后重启MySQL。

(一)开启二进制日志 配置文件位置 : /etc/my.cnf日志存放位置 :配置时,给定了文件名但是没有指定路径,日志默认写入Mysql的数据目录(即配置文件中 datadir 所定义的目录下)。 #配置开启binlog日志, 日志的文件前缀为 mysqlbin -----> 生成的文件名如 : mysqlbin.000001,mysqlbin.000002 log_bin=mysqlbin #配置二进制日志的格式 binlog_format=STATEMENT # binlog 日志有三种格式,分别为:STATMENT、ROW 和 MIXED

重启MySQL后,在data目录会发现生成了一个binlog.000001的文件。实际上每次MySQL重启,在目录下都会生成一个这样的文件,文件名依次递增。此外,MySQL还会在该目录下创建一个二进制日志的索引文件,可以通过命令show variables like ‘log_bin_index’\G来查看索引文件的位置,然后使用cat命令看下。会发现,里面记录着二进制文件的相对路径。

# 根据配置文件中的设置生成的以 mysqlbin开始,日志格式为STATEMENT 的二进制文件 [root@localhost data]# ll mysqlbin* -rw-r-----. 1 mysql mysql 178 3月 8 15:58 mysqlbin.000001 -rw-r-----. 1 mysql mysql 178 3月 8 15:58 mysqlbin.000002 -rw-r-----. 1 mysql mysql 178 3月 8 16:01 mysqlbin.000003 -rw-r-----. 1 mysql mysql 178 3月 8 16:04 mysqlbin.000004 -rw-r-----. 1 mysql mysql 155 3月 8 16:09 mysqlbin.000005 -rw-r-----. 1 mysql mysql 155 3月 8 16:09 mysqlbin.000006 -rw-r-----. 1 mysql mysql 90 3月 8 16:09 mysqlbin.index # 二进制日志的索引文件 mysql> show variables like 'log_bin'; # 已开启 +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_bin | ON | +---------------+-------+ 1 row in set (0.10 sec) mysql> show variables like 'binlog_format'; # 查看二进制日志格式 +---------------+-----------+ | Variable_name | Value | +---------------+-----------+ | binlog_format | STATEMENT | +---------------+-----------+ 1 row in set (0.05 sec) mysql> show master status; # 查看当前使用的二进制日志文件 +-----------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +-----------------+----------+--------------+------------------+-------------------+ | mysqlbin.000006 | 155 | | | | +-----------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) mysql> show variables like 'log_bin_index'\G # 二进制日志的索引文件 *************************** 1. row *************************** Variable_name: log_bin_index Value: /usr/local/mysql/data/mysqlbin.index 1 row in set (0.00 sec) [root@localhost data]# cat mysqlbin.index ./mysqlbin.000001 ./mysqlbin.000002 ./mysqlbin.000003 ./mysqlbin.000005 ./mysqlbin.000006

MySQL二进制日志相关参数

mysql> show variables like '%binlog%'; +------------------------------------------------+----------------------+ | Variable_name | Value | +------------------------------------------------+----------------------+ | binlog_cache_size | 32768 | | binlog_checksum | CRC32 | | binlog_direct_non_transactional_updates | OFF | | binlog_encryption | OFF | | binlog_error_action | ABORT_SERVER | | binlog_expire_logs_seconds | 2592000 | | binlog_format | ROW | | binlog_group_commit_sync_delay | 0 | | binlog_group_commit_sync_no_delay_count | 0 | | binlog_gtid_simple_recovery | ON | | binlog_max_flush_queue_time | 0 | | binlog_order_commits | ON | | binlog_rotate_encryption_master_key_at_startup | OFF | | binlog_row_event_max_size | 8192 | | binlog_row_image | FULL | | binlog_row_metadata | MINIMAL | | binlog_row_value_options | | | binlog_rows_query_log_events | OFF | | binlog_stmt_cache_size | 32768 | | binlog_transaction_dependency_history_size | 25000 | | binlog_transaction_dependency_tracking | COMMIT_ORDER | | innodb_api_enable_binlog | OFF | | log_statements_unsafe_for_binlog | ON | | max_binlog_cache_size | 18446744073709547520 | | max_binlog_size | 1073741824 | | max_binlog_stmt_cache_size | 18446744073709547520 | | sync_binlog | 1 | +------------------------------------------------+----------------------+ 27 rows in set (0.08 sec)

max_binlog_size maxbinlogsize 单个二进制日志文件的大小。如果超过该值,则生成新的文件,后缀名+1;

binlog_cache_size binlogcachesize 内存中存放二进制日志的缓存大小

sync_binlog sync_binlog 缓存中写入几次二进制日志,开始同步刷新到外存(硬盘)中。

log_slave_updates logslvaeupdates 用于主从复制

(二)二进制日志格式

binlog 日志有三种格式,分别为 STATMENT、ROW 和 MIXED

(1)STATEMENT

该日志格式在日志文件中记录的都是SQL语句(statement),每一条对数据进行修改的SQL都会记录在日志文件中,通过Mysql提供的mysqlbinlog工具,可以清晰的查看到每条语句的文本。主从复制的时候,从库(slave)会将日志解析为原文本,并在从库重新执行一次。

优点:在 statement 模式下首先就是解决了 row 模式的缺点,不需要记录每一行数据的变化,从而减少了 binlog 的日志量,节省了 I/O 以及存储资源,提高性能。因为它只需要记录在 master 上执行的语句的细节以及执行语句的上下文信息。缺点:在 statement 模式下,由于它是记录的执行语句,所以,为了让这些语句在 slave 端也能正确执行,那么它还必须记录每条语句在执行的时候的一些相关信息,即上下文信息,以保证所有语句在 slave 端和在 master 端执行结果相同。另外就是,由于 MySQL 现在发展比较快,很多新功能不断的加入,使 MySQL 的复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug 也就越容易出现。在statement 中,目前已经发现不少情况会造成 MySQL 的复制出现问题,主要是在修改数据的时候使用了某些特定的函数或者功能才会出现,比如:sleep() 函数在有些版本中就不能被正确复制,在存储过程中使用了 last_insert_id() 函数,可能会使 slave 和 master 上得到不一致的 id 等等。由于 row 模式是基于每一行来记录变化的,所以不会出现类似的问题。

(2)ROW

该日志格式在日志文件中记录的是每一行的数据变更,而不是记录SQL语句。比如,执行SQL语句 :update tb_book set status=‘1’ , 如果是STATEMENT 日志格式,在日志中会记录一行SQL文件; 如果是ROW,由于是对全表进行更新,也就是每一行记录都会发生变更,ROW 格式的日志中会记录每一行的数据变更。

优点:在 row 模式下,binlog 中可以不记录执行的 sql 语句的上下文相关的信息,仅仅只需要记录哪一条记录被修改了,修改成什么样了,所以 row 的日志内容会非常清楚的记录下每一行数据的修改细节,非常容易理解。而且不会出现某些特定情况下的存储过程和 function,以及 trigger 的调用和触发无法被正确复制问题。缺点:在 row 模式下,当所有执行语句记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容。

(3)MIXED

这是目前MySQL默认的日志格式,即混合了STATEMENT 和 ROW两种格式。默认情况下采用STATEMENT,但是在一些特殊情况下采用ROW来进行记录。MIXED 格式能尽量利用两种模式的优点,而避开他们的缺点。

(三)日志读取

由于日志以二进制方式存储,不能直接读取,需要用MySQL 中自带的工具mysqlbinlog工具来查看

语法: mysqlbinlog binlogfiles -s 以精简的方式显示日志内容(只显示日志中包含的语句,不显示其它信息) -v 以详细的方式显示日志内容 -d=数据库名 只显示指定数据库的日志内容 -o=n 忽略日志中前n行MySQL命令 -r=file 将指定内容写入指定文件 --start-datetime 显示指定时间范围内的日志内容 --stop-datetime --start-position 显示指定位置间隔内的日志内容 --stop-position # 只显示指定二进制日志中包含的语句,不显示其它信息 [root@localhost ~]# mysqlbinlog -s /usr/local/mysql/data/mysqlbin.000006 # 在mysqlbinlog后面加上参数-vv使用--no-defaults参数可以避免字符集带来的影响 [root@localhost ~]# mysqlbinlog --no-defaults -vv /usr/local/mysql/data/mysqlbin.000001 # 根据时间查找后,还原 [root@localhost ~]]# mysqlbinlog --start-date="2010-09-29 18:00:00" --stop-date="2010-09-29 23:00:00" /usr/local/mysql/data/mysql-bin.000002 | mysql -u root -p # 根据数据库名查找 [root@localhost ~]# mysqlbinlog -d test /usr/local/mysql/data/mysql-bin.000002 # 根据位置查找(二进制文件中的at xxx) [root@localhost ~]# mysqlbinlog --start-position=20 --stop-position=100 /usr/local/mysql/data/mysql-bin.000002 # 根据数据库所在IP来查找 [root@localhost ~]# mysqlbinlog -h 192.1681.102 /usr/local/mysql/data/mysql-bin.000002 # 根据数据库端口来查找 [root@localhost ~]# mysqlbinlog -p 13306 /usr/local/mysql/data/mysql-bin.000002 # 根据数据库的ID来查找 [root@localhost ~]# mysqlbinlog --server-id=1 /usr/local/mysql/data/mysql-bin.000002

使用二进制日志恢复数据

[root@localhost ~]# mysqlbinlog -s 1.000001 | mysql -h 192.168.1.188 -u root -p # mysqlbinlog 之后可以跟 --start-datetime 、--stop-datetime 、start-position 、stop-position 等参数。 # --start-datetime 、--stop-datetime 这两个参数可以基于时间点进行数据恢复; # start-position 、stop-position 可以进行操作点更加细化的进行数据恢复;

获取当前使用的二进制日志文件

mysql> show master status; +---------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +---------------+----------+--------------+------------------+-------------------+ | binlog.000004 | 155 | | | | +---------------+----------+--------------+------------------+-------------------+ 1 row in set (0.12 sec) (四)二进制日志的清理

对于比较繁忙的系统,由于每天生成日志量大 ,这些日志如果长时间不清楚,将会占用大量的磁盘空间。下面讲解几种清理日志的常见方法

原则上要先将准备清理的日志通过物理备份的方式备份到其他存储设备上,永久留存。,然后清理

第一种:

# 清理指定日期之前的二进制日志文件 mysql> purge master logs before 'yyyy-mm-dd hh24:mm:ss'; # 或者 # 该命令将删除******编号之前的所有日志(不包括当前的) mysql> purge master logs to 'mysqlbin.******';

第二种:

直接在MySQL的配置文件my.cnf 中设置 expire_logs_days 参数来设置二进制文件的过期天数,过期的二进制文件将会被自动删除。建议在删除前另启一个周期计划任务,定期去备份二进制任务。免得一些数据若干天才发现出现了差错,而二进制日志被自动删除了。

expire_logs_days=90

第三种:

执行删除日志指令,会删除所有二进制日志文件(慎用)

mysql> Reset Master; Query OK, 0 rows affected (1.11 sec)

重启mysql服务,会使二进制日志文件截断,产生新的二进制日志文件进行记录;执行 flush logs 也会如此。

六、InnoDB 事务日志

MySQL会最大程度的利用缓存,从而提高数据的访问效率。那么换一句话来说,任何高性能的系统都必须利用到缓存,从各个层面来讲,缓存都发挥了巨大的作用。

再上升到一个高度提炼一下:缓存和队列是实现高性能的必走之路。那么对于数据库来说这个却是个很棘手的问题,要保证数据更高效率的读取和存储,所以要利用到缓存。但是要保证数据的一致性,则必须保证所有的数据都必须准确无误的存储到数据库中,及时发生意外,也要保证数据可恢复。

我们知道InnoDB是一个事务安全的存储引擎,而一致性是事务ACID中的一个重要特性。InnoDB存储引擎主要是通过InnoDB事务日志实现数据一致性的,InnoDB事务日志包括重做(redo)日志,以及回滚(undo)日志

InnoDB事务日志与前面提到的日志不同,InnoDB事务日志由InnoDB存储引擎自行维护,而且内容不能被数据库管理员读取

重做日志(redo log)

Redo log 是重做日志,属于 InnoDB储存引擎的日志。是物理日志,日志记录的内容是数据页的更改,这个页"做了什么改动"。

redo log 包括两部分: 一个是内存中的日志缓冲( redo log buffer ),另一个是磁盘上的日志文件( redo logfile)。

mysql 每执行一条 DML 语句,先将记录写入 redo log buffer,后续某个时间点再一次性将多个操作记录写到 redo log file。这种 先写日志,再写磁盘 的技术就是 MySQL 里经常说到的 WAL(Write-Ahead Logging) 技术。

在计算机操作系统中,用户空间( user space )下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space )缓冲区( OS Buffer )。

因此, redo log buffer 写入 redo logfile 实际上是先写入 OS Buffer ,然后再通过系统调用 fsync() 将其刷到 redo log file 中,过程如下: 在这里插入图片描述 mysql 支持三种将 redo log buffer 写入 redo log file 的时机,可以通过innodb_flush_log_at_trx_commit 参数配置,各参数值含义如下: 在这里插入图片描述 在这里插入图片描述 redo log与binlog区别 在这里插入图片描述

由 binlog 和 redo log 的区别可知:binlog 日志只用于归档,只依靠 binlog 是没有 crash-safe 能力的。(CrashSafe指MySQL服务器宕机重启后,能够保证:所有已经提交的事务的数据仍然存在;所有没有提交的事务的数据自动回滚) 但只有 redo log 也不行,因为 redo log 是 InnoDB特有的。

为什么 binlog 没有 crash-safe 功能?

redo log 和 binlog 有一个很大的区别就是,一个是循环写,一个是追加写。也就是说 redo log 只会记录未刷盘的日志,已经刷入磁盘的数据都会从 redo log 这个有限大小的日志文件里删除。binlog 是追加日志,保存的是全量日志。

当数据库 crash 后,想要恢复未刷盘但已经写入 redo log 和 binlog 的数据,binlog 是无法恢复的。虽然 binlog 拥有全量的日志,但没有一个标志让 innodb 判断哪些数据已经刷盘,哪些数据还没有。

保证 crash-safe 为啥要用两个日记,不能用一个日记吗(Redo log 或 Binglog)?

只有 binlog 日志,没有 redo log 是不能做到故障恢复的。那么针对只有 redo log日志,没有 binlog 日志,这也是不行的,因为 redo log 是 innodb 持有的,且日志上的记录落盘后会被抹掉。因此需要 binlog 和 redo log 两者同时记录,才能保证当数据库发生宕机重启时,数据不会丢失。

在默认情况下重做日志的值记录在ib_logfile0 以及ib_logfile1重做日志中

[root@localhost data]# ll -h ib* -rw-r-----. 1 mysql mysql 3.4K 3月 8 16:04 ib_buffer_pool -rw-r-----. 1 mysql mysql 12M 3月 8 16:09 ibdata1 -rw-r-----. 1 mysql mysql 512M 3月 8 16:09 ib_logfile0 -rw-r-----. 1 mysql mysql 512M 3月 8 11:26 ib_logfile1 -rw-r-----. 1 mysql mysql 12M 3月 8 16:04 ibtmp1 回滚日志(undo log)

回滚日志主要记录已经部分完成并且写入硬盘的未完成事务,默认情况情况下,回滚日志的信息记录在表空间文件,共享表空间文件ibdata1或者独享表空间中。

数据库事务四大特性中有一个是 原子性 ,具体来说就是 原子性是指对数据库的一系列操作,要么全部成功,要么全部失败,不可能出现部分成功的情况。

实际上, 原子性 底层就是通过 undo log 实现的。undo log主要记录了数据的逻辑变化,比如一条 INSERT 语句,对应一条DELETE 的 undo log ,对于每个 UPDATE 语句,对应一条相反的 UPDATE 的 undo log ,这样在发生错误时,就能回滚到事务之前的数据状态。

undo log 作用:

回滚数据:当数据发生异常错误时,根据执行 undo log 就可以回滚到事务之前的数据状态,保证原子性,要么全部成功,要么全部失败MVCC 一致性视图:通过 undo log 找到对应的数据版本号,是保证 MVCC 视图的一致性的必要条件

binlog、redo log、undo log三种日志。binlog是属于mysql Server层的,属于整个mysql的,而redo log、undo log是属于innodb存储引擎独有的,redo log、undo log是事务日志,binlog是二进制日志负责记录对mysql数据库有修改的sql操作

Checkpoint机制

MySQL服务器崩溃后,重新启动MySQL服务时,由于重做日志(redo)与回滚日志(undo)日志的存在,InnoDB通过回滚日志(undo)日志将所有已部分完成并写入硬盘的未完成事务进行回滚操作(rollback)。然后将重做日志(undo)日志中的事务全部重新执行一遍即可恢复所有的数据。但是数据量过大,为了缩短恢复的时间InnoDB引入了Checkpoint 机制。

脏页(dirty page)

当事务需要修改某条记录是,InnoDB首先将该数据所在的数据块从外存中读取到硬盘中,事务提交后,InnoDB修改数据页中的记录,这时缓存的数据页已经和外存中的数据块已经不一样了,此时缓存中的数据页称为脏页(dirty page),脏页刷新到外存中,变为干净页(clean page)。

日志序列号(log sequence number)

日志序列号(LSN)是日志空间中每条日志的结束点,用字节偏移量表示,在Checkpoin和恢复时使用。

Checkpoint 机制原理 假设在某个时间点,所有的脏页(dirty page)都被刷新到了硬盘上,这个时间点之前的所有重做日志(redo)就不需要重做了.系统就就下这个时间点重做日志的结尾位置作为Checkpoint,Checkpoint之前的重做日志也就不需要再重做了,可以放心的删除掉。为了更好的利用重做日志(redo)的空间,InnoDb采用轮循的策略使用重做日志空间,因此InnoDB的重做日志文件至少为2个。通过Checkpoint 机制,通过重做日志(redo)将数据库崩溃时已经完成但还没有来得及将缓存中已经修改但还未完全写入外存的事务进行重做(undo)操作,即可保证数据的一致性,也可以缩短恢复时间。

InnoDB重做日志(redo)的参数

innodb_log_buffer_size # 设置了重做日志缓存的大小。 innodb_log_files_in_group # 设置了日志文件组中重做日志(redo)日志的数量。 innodb_log_file_size # 设置了重做日志文件的大小,文件越大,恢复起来耗时越长。 innodb_mirrored_log_groups: # 重做日志镜像文件组数量,只能设置为1. innodb_log_group_home_dir: # 设置日志文件组存放的目录,默认在数据库根目录下。

InnoDB回滚日志(undo)的参数

innodb_undo_directory: # 设置回滚日志存放的目录。 innodb_undo_logs # 设置回滚日志的回滚段大小,默认为128k innodb_undo_tablespace # 设置了回滚日志由多少个回滚日志文件组成,默认为0. # 注意:安装MySQL后需要在my.cnf中设置回滚日志的参数,如果创建数据库以后再设置回滚日志的参数,MySQL就会报错,并且回滚日志建好后,就不能再次修改或者增加。 七、日志文件备份

备份的时候可以使用flush logs,关闭当前的所有日志文件,然后产生新的日志文件。关闭日志文件后,可以采用物理方式备份。 另外flush logs可以添加具体的日志类型:

mysql> flush error logs; mysql> flush general logs; mysql> flush binary logs; mysql> flush slow logs;


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有