暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MySQL面试宝典-文件篇

IT小Chen 2022-04-10
558

    一.请简述MySQL配置文件的加载顺序?
    二.MySQL启动时如果找不到配置(参数)文件,会报错还是启动?
    三.如何查看MySQL参数?
    四.如何修改MySQL参数?
    五:MySQL有哪些类型表空间,简述各自作用?
    六:请简述MySQL redo log和binlog区别?

    一.请简述MySQL配置文件的加载顺序?

    MySQL读取配置文件的顺序

    读取顺序:/etc/mysql/my.cnf>/etc/my.cnf>~/.my.cnf

    命令验证:

    方法1:

      [mysql@mysql01 bin]$ mysql --help|grep my.cnf
      /etc/mysql/my.cnf etc/my.cnf ~/.my.cnf
      order of preference, my.cnf, $MYSQL_TCP_PORT,

      [mysql@mysql01 bin]$ mysql --verbose --help | grep my.cnf
      /etc/mysql/my.cnf etc/my.cnf ~/.my.cnf
      order of preference, my.cnf, $MYSQL_TCP_PORT,

      方法2:  

        [mysql@mysql01 bin]$ my_print_defaults --help|grep -A2 -B2 my.cnf
        Default options are read from the following files in the given order:
        /etc/mysql/my.cnf etc/my.cnf ~/.my.cnf

        Variables (--variable-name=value)

        二.MySQL启动时如果找不到参数文件,会报错还是启动?

        MySQL数据库参数文件的作用和Oracle数据库的参数文件极其类似,不同的是,Oracle实例在启动时若找不到参数文件,是不能进行装载(mount)操作。

        MySQL稍微有所不同,MySQL实例可以不需要参数文件,这时所有的参数值取决于编译MySQL时指定的默认值和源代码中指定参数的默认值。

        如果MySQL实例在默认的数据库目录下找不到mysql架构,则启动同样会失败。

        三.如何查看MySQL参数?

        可以把数据库参数看成一个键/值(key/value)对。

        可以通过命令SHOW VARIABLES查看数据库中的所有参数,也可以通过LIKE来过滤参数名。

        从MySQL 5.1版本开始,还可以通过information_schema架构下的GLOBAL_VARIABLES视图来进行查找。

          show variables like '%timeout%';
          mysql> SHOW [{GLOBAL|SESSION}] VARIABLES [LIKE ''];
          mysql> SELECT @@{GLOBAL|SESSION}.VARIABLE_NAME;
          mysql> SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='VARIABLE_NAME';
          mysql> SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='VARIABLE_NAME';
          通过配置文件查看参数
          cat etc/my.cnf|grep -i "VARIABLE_NAME"

          四.如何修改MySQL参数?

          会话级别修改:

          set session innodb_lock_wait_timeout=50;

          对当前会话立即生效,退出后,参数失效,不影响后续的会话

          全局级别修改:

          set global innodb_lock_wait_timeout=50;

          当前会话不生效,对后续连接进来的会话生效

          修改配置文件

          五:MySQL有哪些类型表空间,简述各自作用?

          MySQL有五种表空间: 

          系统表空间(也叫共享表空间) 、独立表空间 、临时表空间 、undo表空间 、通用表空间。

          1.系统表空间

          主要用来存放undo信息、insert buffer 索引页、double write buffer 等数据。

          系统表空间系统表空间(system tablespace)是在初始化mysql实例时生成的,读取my.cnf中的innodb_data_file_path参数,初始对应大小的文件。

          mysql默认的系统表空间文件大小是12M,只有一个文件(ibdata1),它默认是保存在mysql实例的datadir变量的目录下。

          #### 在mysql实例中查看共享表空间的大小

            MySQL [cjcdb]> select @@global.innodb_data_file_path;
            +--------------------------------+
            | @@global.innodb_data_file_path |
            +--------------------------------+
            | ibdata1:12M:autoextend | # 共享表空间的文件是ibdata1,大小是12M
            +--------------------------------+ # autoextend自动扩展
            1 row in set (0.00 sec)

            #### 在mysql的datadir变量所指定的目录下查看系统表空间文件

              MySQL [cjcdb]> select @@global.datadir;
              +------------------------+
              | @@global.datadir |
              +------------------------+
              | /usr/local/mysql/data/ |
              +------------------------+
              1 row in set (0.00 sec)

              当系统表空间不够用时(也就是ibdata1文件),会自动扩展(autoextend),默认每次自动扩展64M。

                MySQL [cjcdb]> select @@innodb_autoextend_increment;
                +-------------------------------+
                | @@innodb_autoextend_increment |
                +-------------------------------+
                | 64 |
                +-------------------------------+
                1 row in set (0.00 sec)

                2.独立表空间

                从mysql 5.6.6版本开始,独立表空间(file-per-table tablespaces)默认是开启的(也就是innodb_file_per_table参数不设置时,默认等于1),在开启的情况下,创建一个innodb引擎的表,那么表有自己独立的一些数据文件。

                这些数据文件在操作系统上的文件体现如下所示:

                表名.frm   # 表的表结构文件(里面存放的是表的创建语句)

                表名.ibd   # 表的数据文件(当有数据往表中插入时,数据就保存之个文件中的)

                独立表空间的好处:

                01:表数据分开存放(不把所有鸡蛋放在1个蓝子里面);损坏1个文件不至于影响所有表

                02:容易维护,查询速度快(IO分散)

                03:使用MySQL Enterprise Backup快速备份或还原在每表文件表空间中创建的表,不会中断其他InnoDB 表的使用

                缺点:

                对fsync系统调用来说不友好,如果使用一个表空间文件的话单次系统调用可以完成数据的落盘,但是如果你将表空间文件拆分成多个。

                原来的一次fsync可能会就变成针对涉及到的所有表空间文件分别执行一次fsync,增加fsync的次数。

                独立表空间文件中仅存放该表对应数据、索引、insert buffer bitmap。

                其余的诸如:undo信息、insert buffer 索引页、double write buffer 等信息依然放在默认表空间,也就是共享表空间中。

                当innodb_file_per_table参数为0时,表示使用系统表空间,当为1时,表示使用独立表空间。

                innodb_file_per_table选项只对新建的表起作用,对于已经分配了表空间的表不起作用。

                如果想把已经分配到系统表空间中的表转移到独立表空间,可以使用下面语句:

                ALTER TABLE 表名 TABLESPACE [=] innodb_file_per_tables;

                如果要将已经存储在独立表空间的表转移到系统表空间:

                ALTER TABLE 表名 TABLESPACE [=] innodb_system;

                其中中括号里的=可有可无。

                与InnoDB不同,MyISAM并没有什么表空间一说,表的数据和索引都存放在对应的数据库子目录下。

                假如cjc表使用的是MyISAM存储引擎,那么他所在数据库对应的目录下会为cjc表创建下面3个文件:

                1.cjc.frm 表结构。2.cjc.MYD 表数据。3.cjc.MYI 表索引。

                3.临时表空间

                临时表空间用于存放用户创建的临时表和磁盘内部临时表。

                参数innodb_temp_data_file_path定义了临时表空间的一些名称、大小、规格属性

                  MySQL [cjcdb]> show variables like '%innodb_temp_data_file_path%';
                  +----------------------------+-----------------------+
                  | Variable_name | Value |
                  +----------------------------+-----------------------+
                  | innodb_temp_data_file_path | ibtmp1:12M:autoextend |
                  +----------------------------+-----------------------+
                  1 row in set (0.00 sec)

                  MySQL 5.7对于InnoDB存储引擎的临时表空间做了优化。

                  在MySQL 5.7之前,INNODB引擎的临时表都保存在ibdata里面,而ibdata的贪婪式磁盘占用导致临时表的创建与删除对其他正常表产生非常大的性能影响。

                  在MySQL5.7中,对于临时表做了下面两个重要方面的优化:

                  (1)MySQL 5.7 把临时表的数据以及回滚信息(仅限于未压缩表)从共享表空间里面剥离出来,形成自己单独的表空间,参数为innodb_temp_data_file_path。

                  (2)MySQL 5.7 把临时表的相关检索信息保存在系统信息表中:information_schema.innodb_temp_table_info.

                  而MySQL 5.7之前的版本想要查看临时表的系统信息是没有太好的办法。

                  select * frominformation_schema.innodb_temp_table_info;

                  需要注意的一点就是:

                  虽然INNODB临时表有自己的表空间,但是目前还不能自己定义临时表空间文件的保存路径,只能是继承innodb_data_home_dir。

                  此时如果想要拿其他的磁盘,比如内存盘来充当临时表空间的保存地址,只能用老办法,做软链。

                  MySQL临时表类型

                  1.外部临时表,通过create temporary table语法创建的临时表,可以指定存储引擎为memory,innodb, myisam等等,这类表在会话结束后,会被自动清理。

                  如果临时表与非临时表同时存在,那么非临时表不可见。show tables命令不显示临时表信息。

                  可通过informationschema.INNODBTEMPTABLEINFO系统表可以查看外部临时表的相关信息

                  2.内部临时表,通常在执行复杂SQL,比如group by, order by, distinct, union等,执行计划中如果包含Using temporary.

                  还有undo回滚的时候,但空间不足的时候,MySQL内部将使用自动生成的临时表,以辅助完成工作。

                  临时表参数

                  tmp_table_size

                  内部临时表在内存中的的最大值,与max_heap_table_size参数共同决定,取二者的最小值。如果临时表超过该值,就会从内存转移到磁盘上;

                  max_heap_table_size

                  用户创建的内存表的最大值,也用于和tmp_table_size一起,限制内部临时表在内存中的大小;

                  innodb_tmpdir

                  innodb_temp_data_file_path

                  innodb引擎下temp文件属性。建议限制innodbtempdatafilepath = ibtmp1:1G:autoextend:max:30G;

                  default_tmp_storage_engine

                  外部临时表(create temporary table创建的表)默认的存储引擎;

                  internal_tmp_disk_storage_engine

                  磁盘上的内部临时表存储引擎,可选值为myisam或者innodb。

                  使用innodb表在某些场景下,比如临时表列太多,或者行大小超过限制,可能会出现“ Row size too large or Too many columns”的错误,这时应该将临时表的innodb引擎改回myisam。

                  slave_load_tmpdir

                  tmpdir

                  表示磁盘上临时表所在的目录。

                  临时表目录,当临时表大小超过一定阈值,就会从内存转移到磁盘上;

                  max_tmp_tables

                  状态信息

                  Created_tmp_disk_tables

                  执行SQL语句时,MySQL在磁盘上创建的内部临时表数量,如果这个值很大,可能原因是分配给临时表的最大内存值较小,或者SQL中有大量排序、分组、去重等操作,SQL需要优化;

                  Created_tmp_files

                  创建的临时表数量;

                  Created_tmp_tables

                  执行SQL语句时,MySQL创建的内部临时表数量;

                  Slave_open_temp_tables

                  statement 或则 mix模式下才会看到有使用;

                  通过复制,当前slave创建了多少临时表

                  information_schema.innodb_temp_table_info

                  4.undo表空间

                  MySQL5.5时代的undo log

                  在MySQL5.5以及之前,InnoDB的undo log也是存放在ibdata1里面的。一旦出现大事务,这个大事务所使用的undo log占用的空间就会一直在ibdata1里面存在,即使这个事务已经关闭。

                  答案是没有直接的办法,只能全库导出sql文件,然后重新初始化mysql实例,再全库导入。

                  MySQL 5.6时代的undo log

                  MySQL 5.6增加了参数innodb_undo_directory、innodb_undo_logs和innodb_undo_tablespaces这3个参数,可以把undo log从ibdata1移出来单独存放。

                  innodb_undo_directory,

                  指定单独存放undo表空间的目录,默认为.(即datadir),可以设置相对路径或者绝对路径。

                  该参数实例初始化之后虽然不可直接改动,但是可以通过先停库,修改配置文件,然后移动undo表空间文件的方式去修改该参数;

                  innodb_undo_tablespaces,

                  指定单独存放的undo表空间个数,例如如果设置为3,则undo表空间为undo001、undo002、undo003,每个文件初始大小默认为10M。

                  该参数我们推荐设置为大于等于3,原因下文将解释。该参数实例初始化之后不可改动;

                  innodb_undo_logs,

                  指定回滚段的个数(早期版本该参数名字是innodb_rollback_segments),默认128个。每个回滚段可同时支持1024个在线事务。

                  这些回滚段会平均分布到各个undo表空间中。

                  该变量可以动态调整,但是物理上的回滚段不会减少,只是会控制用到的回滚段的个数。

                  实际使用方面,在初始化实例之前,我们只需要设置innodb_undo_tablespaces参数(建议大于等于3)即可将undo log设置到单独的undo表空间中。

                  MySQL 5.7时代的undo log

                  MySQL 5.7引入了新的参数,innodb_undo_log_truncate,开启后可在线收缩拆分出来的undo表空间。

                  在满足以下2个条件下,undo表空间文件可在线收缩:

                  innodb_undo_tablespaces>=2。因为truncate undo表空间时,该文件处于inactive状态,如果只有1个undo表空间,那么整个系统在此过程中将处于不可用状态。

                  为了尽可能降低truncate对系统的影响,建议将该参数最少设置为3;

                  innodb_undo_logs>=35(默认128)。

                  因为在MySQL 5.7中,第一个undo log永远在系统表空间中,另外32个undo log分配给了临时表空间,即ibtmp1,至少还有2个undo log才能保证2个undo表空间中每个里面至少有1个undo log;

                  满足以上2个条件后,把innodb_undo_log_truncate设置为ON即可开启undo表空间的自动truncate,这还跟如下2个参数有关:

                  (1)innodb_max_undo_log_size,undo表空间文件超过此值即标记为可收缩,默认1G,可在线修改;

                  (2)innodb_purge_rseg_truncate_frequency,指定purge操作被唤起多少次之后才释放rollback segments。当undo表空间里面的rollback segments被释放时,undo表空间才会被truncate。由此可见,该参数越小,undo表空间被尝试truncate的频率越高。

                  MySQL 8.0收缩UNDO

                  1、添加新的undo文件undo003。mysql8.0中默认innodb_undo_tablespace为2个,不足2个时,不允许设置为inactive,且默认创建的undo受保护,不允许删除。

                  2、将膨胀的 undo 临时设置为inactive,以及 innodb_undo_log_truncate=on,自动 truncate 释放膨胀的undo空间。

                  3、重新将释放空间之后的undo设置为active,可重新上线使用。


                  具体操作如下:

                    MySQL [cjcdb]> show variables like '%undo%';
                    +--------------------------+------------+
                    | Variable_name | Value |
                    +--------------------------+------------+
                    | innodb_max_undo_log_size | 1073741824 |
                    | innodb_undo_directory | ./ |
                    | innodb_undo_log_truncate | OFF |
                    | innodb_undo_logs | 128 |
                    | innodb_undo_tablespaces | 0 |
                    +--------------------------+------------+
                    5 rows in set (0.00 sec)

                    查看undo大小

                      mysql[(none)]> system du -sh  /app/dbdata/datanode3307/log/undo*
                      10G /app/dbdata/datanode3307/log/undo_001

                      添加新的undo表空间undo003。系统默认是2个undo,大小设置4G

                        mysql[(none)]> 
                        mysql[(none)]> create undo tablespace undo001 add datafile '/usr/local/mysql/data/undo/undo001.ibu';
                        Query OK, 0 rows affected (0.21 sec)

                        注意:创建添加新的undo必须以.ibu结尾,否则触发如下错误提示

                          mysql[(none)]> create undo tablespace undo003 add datafile '/app/dbdata/datanode3307/log/undo_003.' ;
                          ERROR 3121 (HY000): The ADD DATAFILE filepath must end with '.ibu'.

                          5.通用表空间

                          通用表空间(General Tablespaces)

                          通用表空间为通过create tablespace语法创建的共享表空间。

                          通用表空间可以创建于mysql数据目录外的其他表空间,其可以容纳多张表,且其支持所有的行格式。

                          通过create table tab_name ... tablespace [=] tablespace_name或alter table tab_name tablespace [=] tablespace_name语法将其添加与通用表空间内。

                          六:请简述MySQL redo log和binlog区别? 

                          redo log 和 binlog 的区别:

                          日志归属:

                          binlog由Server层实现,所有引擎都可以使用。

                          redo log是innodb引擎特有的日志。

                          日志类型:

                          binlog是逻辑日志,记录原始SQL或数据变更前后内容。

                          redo是物理日志,记录在哪些页上进行了哪些修改。

                          写入方式:

                          binlog是追加写,写满一个文件后创建新文件继续写。

                          redo log是循环写,全部写满后覆盖从头写。

                          适用场景:

                          binlog适用于主从恢复和误删除恢复。

                          redo log适用于崩溃恢复。


                          虽然在更新BufferPool后,也写入了binlog中,但binlog并不具备crash-safe的能力。因为崩溃可能发生在写binlog后,刷脏前。在主从同步的情况下,从节点会拿到多出来的一条binlog。所以server层的binlog是不支持崩溃恢复的,只是支持误删数据恢复。InnoDB考虑到这一点,自己实现了redo log。


                          因为最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。

                          而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力。

                          ###chenjuchao 20220410###

                          文章转载自IT小Chen,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论