MySQL技术内幕 - 文件

参数文件

  • 作用:mysql实例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数,这些参数通常定义了某种内存结构多大等。
  • 查看参数:
代码
show variables;
  • 参数类型有哪些?
    动态参数:可以修改的参数,通过SET命令修改。
    静态参数:只读参数,不可修改。
代码
mysql> show variables like 'read_buffer_size';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| read_buffer_size | 131072 |
+------------------+--------+
1 row in set (0.00 sec)

## 修改动态参数
mysql> set read_buffer_size=524288;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'read_buffer_size';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| read_buffer_size | 524288 |
+------------------+--------+
1 row in set (0.00 sec)

套接字文件

  • 作用:unix系统下本地连接Mysql采用unix域套接字方式,这种方式需要一个套接字文件。
代码
## 通过参数文件查看套接字文件的位置
mysql> show variables like 'socket'\g;
+---------------+-----------------------------+
| Variable_name | Value                       |
+---------------+-----------------------------+
| socket        | /var/run/mysqld/mysqld.sock |
+---------------+-----------------------------+
1 row in set (0.01 sec)
## 查找套接字文件
bash-4.4# find / -name mysqld.sock
/run/mysqld/mysqld.sock

pid文件

  • 作用:当mysql实例启动时,会将自己的进程ID写入一个文件,该文件就是pid文件。文件由参数pid_file控制,默认位于数据库目录下,文件名未主机名.pid。
代码
bash-4.4# find / -name *.pid
/var/run/mysqld/mysqld.pid

表结构定义文件

  • 作用:mysql数据的存储是根据表进行的,每个表都有对应文件。mysql表结构定义文件以frm为后缀名,与此同时frm文件也存放视图定义。
  • mysql8将表定义文件写在.ibd文件中。

innodb存储引擎文件

  • 表空间文件:innodb将存储的数据按表空间进行存放设计。默认初始大小为10MB,名为ibdata1文件。使用innodb_data_file_path参数设置共享表空间。若设置了参数innodb_file_per_table,则用户可以将每个基于innodb存储引擎产生的表都放到一个独立表空间。命名规则为表名.ibd。
代码
## 查看配置的共享表空间文件,12M用完自动增长
mysql> show variables like 'innodb_data_file_path';
+-----------------------+------------------------+
| Variable_name         | Value                  |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
+-----------------------+------------------------+
1 row in set (0.05 sec)

## 查看是否开启了独立表空间
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

查看共享表空间和独立表空间位置:

代码
bash-4.4# find / -name ibdata1
/var/lib/mysql/ibdata1
bash-4.4# find / -name *.ibd
/var/lib/mysql/education/edu_stu.ibd
/var/lib/mysql/education/edu_teacher.ibd

单独表空间文件仅存放表的数据、索引和插入缓冲Bitmap,其余的还是在共享表空间文件中。
image

  • 重做日志文件:默认情况下,innodb引擎下的数据目录存在两个名为ib_logfile0和ib_logfile1文件,就是重做日志文件。
  • 重做日志文件作用:记录了innodb存储引擎的事务日志(实际就是每个数据页Page的更改物理情况)。每个innodb存储引擎至少有1个重做日志文件组,每个文件组下至少有2个重做日志文件,如默认的ib_logfile0和ib_logfile1。
    image

注意:重做日志文件太大会带来很长的恢复时间,太小可能会让一个事务多次切换重做日志文件,还会频繁的发生async checkpoint,造成性能抖动。重做日志有一个检查点,如果超过了这个检查点,那么必须将缓冲池中脏页列表中的部分脏数据页写回磁盘,导致用户线程的阻塞。

写入重做日志过程:先写入重做日志缓冲区(redo log buffer),然后按照一定条件顺序写入日志文件。重做日志缓冲往磁盘写入时,是按512个字节,也就是一个扇区大小写入。因为扇区是写入的最小单位,可以保证必定写入成功,所以不需要双写(double write)。

什么是double write:为了提高innodb的可靠性,因为innodb在写数据过程中,只写了部分数据就写失败了,为了保证数据持久性,将剩下的脏数据写到了磁盘上,就是写到了共享空间ibdata1中,之前的一份写到了真正的数据永久保存,写了两次脏数据的过程叫double write。

日志缓冲区写入到重做日志文件的时机:1.主线程master中每秒会将重做日志缓冲写入磁盘的重做日志中,不论事务是否已经提交。2.写磁盘过程由参数innodb_flush_log_at_trx_commit参数控制,表示在提交操作时,处理重做日志的方式。

代码
mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)

"0"代表当提交事务时,不将事务的重做日志写入磁盘的日志文件,而是等待主线程每秒的刷新。"1"代表在执行commit时,将重做日志缓冲同步到磁盘上(即伴有fsync的调用)。"2"代表将重做日志异步写到磁盘。

日志文件

  • 错误日志:主要记录了mysql的启动、运行、关闭。
代码
## 查看错误日志文件的位置
mysql> show variables like 'log_error';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| log_error     | stderr |
+---------------+--------+
1 row in set (0.00 sec)

stderr:该值意思是错误打印到控制台。

  • 慢查询日志:可以在mysql启动时设置一个最大值,将运行时间超过该值的sql语句都记录到慢查询日志中。通过参数long_query_time来设置,默认值为10,代表10秒。使用slow_query_log来启动慢查询日志。
代码
mysql> show variables like 'slow_query_log';
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | OFF   |
+----------------+-------+
1 row in set (0.00 sec)

## 开启慢查询日志
mysql> set global slow_query_log ='ON';
Query OK, 0 rows affected (0.01 sec)

## 查看慢查询的阙值
mysql> show VARIABLES like 'long_query_time%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

##慢查询日志的位置
mysql> show variables like 'slow_query_log_file';
+---------------------+--------------------------------------+
| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_query_log_file | /var/lib/mysql/23163e75e735-slow.log |
+---------------------+--------------------------------------+
1 row in set (0.00 sec)

参数log_queries_not_using_indexes设置将未使用索引的sql语句写入到慢查询日志。

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

慢查询日志会记录在mysql.slow_log表。

  • 查询日志:查询日志记录了所有对mysql数据库请求的信息,无论请求是否得到了正确的执行,默认文件名为主机.log。
    查询日志会记录在mysql.general_log表。
代码
## 查看查询日志是否开启
mysql> show variables like 'general_log';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| general_log   | OFF   |
+---------------+-------+
1 row in set (0.01 sec)
## 开启查询日志
mysql> set global general_log = 'ON';
Query OK, 0 rows affected (0.00 sec)
## 查询日志的位置
mysql> show variables like 'general_log_file';
+------------------+---------------------------------+
| Variable_name    | Value                           |
+------------------+---------------------------------+
| general_log_file | /var/lib/mysql/23163e75e735.log |
+------------------+---------------------------------+
1 row in set (0.00 sec)
  • 二进制日志:二进制日志记录了mysql执行更改的所有操作,不包括select和show操作。二进制文件的设置在my.cnf中为log-bin=mysql-bin,二进制日志的后缀名为二进制日志的序列号。
    作用:1.恢复:用户可以通过二进制日志进行point-in-time恢复。2.复制:通过复制和执行二进制日志使一台远程的mysql数据库(一般称为slave或者standby)与一台mysql数据库(一般成为master)进行实时同步。3.审计:用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入的攻击。
代码
## 执行update语句
update edu_user set password = '000000' where username = 'zhangsan';
## 查询master线程的状态
mysql> show master status;
+---------------+----------+--------------+-------------------------------------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+---------------+----------+--------------+-------------------------------------------------+-------------------+
| binlog.000002 |      531 |              | mysql,performance_schema,information_schema,sys |                   |
+---------------+----------+--------------+-------------------------------------------------+-------------------+
1 row in set (0.00 sec)
## 查看刚才update语句
mysql> show binlog events in 'binlog.000002';
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------------------------+
| Log_name      | Pos | Event_type     | Server_id | End_log_pos | Info                                                                                 |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------------------------+
| binlog.000002 |   4 | Format_desc    |         1 |         126 | Server ver: 8.0.29, Binlog ver: 4                                                    |
| binlog.000002 | 126 | Previous_gtids |         1 |         157 |                                                                                      |
| binlog.000002 | 157 | Anonymous_Gtid |         1 |         236 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                 |
| binlog.000002 | 236 | Query          |         1 |         337 | BEGIN                                                                                |
| binlog.000002 | 337 | Query          |         1 |         500 | use `education`; update edu_user set password = '000000' where username = 'zhangsan' |
| binlog.000002 | 500 | Xid            |         1 |         531 | COMMIT /* xid=54 */                                                                  |
+---------------+-----+----------------+-----------+-------------+--------------------------------------------------------------------------------------+
6 rows in set (0.00 sec)

二进制日志的参数:
1.max_binlog_size:单个二进制文件的最大值。
2.binlog_cache_size:基于会话的缓存。
3.binlog_cache_disk_use:记录了使用临时文件写二进制日志的次数。
4.binlog_format:参数指定二进制日志文件的格式。使用STATEMENT的好处就是它占用空间少,因为它只记录SQL语句,缺点就是如果语句中使用了UUID这类随机或依赖环境的函数,那么当需要通过二进制日志复制时就会出现数据不一致的问题。使用ROW的好处就是它不会出现数据不一致问题,还有什么启用这个就可以开启已提交读隔离级别,因为它相当于在日志中记录了整行修改后的快照。缺点就是占用空间极大。使用MIXED会在必要的时候使用ROW记录,其他时候使用STATEMENT记录。

posted @ 2023-04-24 22:22  sunpeiyu  阅读(13)  评论(0编辑  收藏  举报