目录
1.ANALYZE TABLE语句
1.1 输出
1.2 KEY分布分析
1.3 直方图统计分析
2.CHECK TABLE语句
2.1 输出
2.2 检查版本兼容性
2.3 检查数据一致性
2.4 InnoDB表的CHECK TABLE的使用说明
2.5 MyISAM表的CHECK TABLE使用说明
3.CHECKSUM TABLE语句
3.1 性能注意事项
4.OPTIMIZE TABLE语句
4.1 输出
4.2 InnoDB详细信息
4.3 MyISAM 详细信息
4.4 其他注意事项
5.REPAIR TABLE语句
5.1 REPAIR TABLE存储引擎和分区支持
5.2 REPAIR TABLE输出
5.3 表修复注意事项
1.ANALYZE TABLE语句
ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]TABLE tbl_name [, tbl_name] ...ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]TABLE tbl_nameUPDATE HISTOGRAM ON col_name [, col_name] ...[WITH N BUCKETS]ANALYZE [NO_WRITE_TO_BINLOG | LOCAL] TABLE tbl_nameUPDATE HISTOGRAM ON col_name [USING DATA 'json_data']ANALYZE [NO_WRITE_TO_BINLOG | LOCAL]TABLE tbl_nameDROP HISTOGRAM ON col_name [, col_name] ...
HISTOGRAM 的英文意思是:直方图
ANALYZE TABLE生成表统计信息:
不带HISTOGRAM的ANALYZE TABLE执行KEY分布分析并存储表的分布。
对于MyISAM表,用于KEY分布分析的ANALYZE TABLE等效于使用 myisamchk --analyze.
使用UPDATE HISTOGRAM子句的ANALYZE TABLE生成表列的直方图统计信息,并将其存储在数据字典中。此语法只允许使用一个表名。
MySQL 8.0.31及更高版本还支持将单列的直方图设置为用户定义的JSON值。
使用DROP HISTOGRAM子句的ANALYZE TABLE从数据字典中删除命名表列的直方图统计信息。此语法只允许使用一个表名。
此语句要求对表具有SELECT和INSERT执行权限。
ANALYZE TABLE适用于InnoDB、NDB和MyISAM表。它不适用于视图。
如果启用了innodb_read_only系统变量,ANALYZE TABLE可能会失败,因为它无法更新innodb的数据字典中的统计表。
对于更新KEY分布的ANALYZE TABLE操作,即使该操作更新了表本身(例如,如果它是MyISAM表),也可能发生故障。
若要获取新的统计信息,设置information_schema_stats_expiry=0。
分区表支持ANALYZE TABLE,您可以使用ALTER TABLE....ANALYZE PARTITION可分析一个或多个分区;
有关更多信息,请参阅“ALTER TABLE语句”和“分区的维护”。
在分析过程中,表被InnoDB和MyISAM的读锁锁定。
默认情况下,服务器将ANALYZE TABLE语句写入binlog,以便它们复制到副本。要抑制日志记录,请指定 NO_WRITE_TO_BINLOG关键字或LOCAL。
以前,ANALYZE TABLE需要一个flush锁。这意味着,当调用 ANALYZE TABLE时,有长时间运行的语句或事务仍在使用表时,任何后续语句和事务都必须等待这些操作完成,然后才能释放flush锁。
这个问题在MySQL 8.0.24(及更高版本)中得到了解决,其中ANALYZE TABLE不再导致后续操作等待。
1.1 输出
ANALYZE TABLE返回一个结果集,其列如下表所示。
列 | 值 |
---|---|
Table | 表名 |
Op | 分析或直方图 |
Msg_type | 状态、错误、信息、注释或警告 |
Msg_text | 信息消息 |
1.2 KEY分布分析
不带HISTOGRAM子句的ANALYZE TABLE执行键分布分析并存储表的分布。任何现有的直方图统计数据都不受影响。
如果自上次KEY分布分析以来该表没有更改,则不会再次分析该表。
MySQL使用存储的KEY分布来决定表的联接顺序,以便在常量以外的对象上进行联接查询。此外,在决定为查询中的特定表使用哪些索引时,可以使用KEY分布。
要检查存储的KEY分布基数,请使用SHOW INDEX语句或INFORMATION_SCHEMA库的STATISTICS表。
参见“SHOW INDEX语句”和“INFORMATION_SCHEMA库STATISTICS表”。
对于InnoDB表,ANALYZE TABLE通过对每个索引树执行随机查询并相应地更新索引基数估计来确定索引基数。因为这些只是估计,重复运行ANALYZE TABLE可能会产生不同的数字。
这使得ANALYZE TABLE在InnoDB表上快速,但不是100%准确,因为它没有考虑所有行。
如第“配置持久优化器统计参数”中所述,通过启用innodb_stats_persistent,可以使ANALYZE TABLE收集的统计数据更加精确和稳定。
启用innodb_stats_persistent后,在索引列数据发生重大更改后运行ANALYZE TABLE非常重要,因为统计信息不会定期重新计算(例如在服务器重新启动后)。
如果启用了innodb_stats_persistent,则可以通过修改innodb_tats_persistent_sample_pages系统变量来更改随机dives次数。如果innodb_stats_persistent被禁用,请改为修改innodb_tats_transient_sample_pages。
官网这里用的dives,不确定是什么意思,我猜测应该是随机更新统计数据的次数。
有关InnoDB中KEY分布分析的更多信息,
请参阅“配置持久优化器统计参数”
和“估计InnoDB表的ANALYZE表复杂性”。
MySQL在联接查询优化中使用索引基数估计。如果联接没有以正确的方式优化,请尝试运行ANALYZE TABLE。在少数情况下,ANALYZE TABLE不能为您的特定表生成足够好的值,您可以在查询中使用FORCE INDEX来强制使用特定索引,或者设置max_seeks_for_key系统变量,以确保MySQL更喜欢索引查找而不是表扫描。请参阅“优化器相关问题”。
1.3 直方图统计分析
使用HISTOGRAM子句的ANALYZE TABLE可以管理表列值的直方图统计信息。有关直方图统计信息,请参阅“优化器统计”。
这些直方图操作可用:
带有UPDATE HISTOGRAM子句的ANALYZE TABLE生成命名表列的直方图统计信息,并将其存储在数据字典中。此语法只允许使用一个表名。
可选的WITH N BUCKETS子句指定直方图的桶数。N的值必须是介于1到1024之间的整数。如果省略此项,则存储桶的数量为100。
带有DROP HISTOGRAM子句的ANALYZE TABLE从数据字典中删除表的直方图统计信息。此语法只允许使用一个表名。
存储的直方图管理语句只影响命名列。考虑以下陈述:
ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c2, c3 WITH 10 BUCKETS;
ANALYZE TABLE t UPDATE HISTOGRAM ON c1, c3 WITH 10 BUCKETS;
ANALYZE TABLE t DROP HISTOGRAM ON c2;
第一条语句更新列c1、c2和c3的直方图,替换这些列的任何现有直方图。
第二个语句更新c1和c3的直方图,使c2直方图不受影响。
第三条语句删除了c2的直方图,使c1和c3的直方图不受影响。
当作为构建直方图的一部分对用户数据进行采样时,并不是读取所有值;
这可能会导致丢失一些被认为重要的值。
在这种情况下,修改直方图或根据自己的标准(如完整的数据集)明确设置自己的直方图可能会很有用。
MySQL 8.0.31添加了对ANALYZE TABLE tbl_name UPDATE HISTOGRAM ON col_name USING DATA 'json_DATA'的支持,用于使用以相同json格式提供的数据更新直方图表的列,该格式用于显示Information Schema库的COLUMN_STATISTICS 表中的HISTOGRAM列值。使用JSON数据更新直方图时,只能修改一列。
我们可以通过首先在表t的c1列上生成直方图来说明USING DATA的使用,如下所示:
mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1;
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics created for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+
我们可以在COLUMN_STATISTICS表中看到生成的直方图:
mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: mydbTABLE_NAME: t
COLUMN_NAME: c1HISTOGRAM: {"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],
"data-type": "int", "null-values": 0.0, "collation-id": 8, "last-updated":
"2022-10-11 16:13:14.563319", "sampling-rate": 1.0, "histogram-type":
"singleton", "number-of-buckets-specified": 100}
现在我们去掉直方图,当我们检查COLUMN_STATISTICS时,它现在是空的:
mysql> ANALYZE TABLE t DROP HISTOGRAM ON c1;
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics removed for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+mysql> TABLE information_schema.column_statistics\G
Empty set (0.00 sec)
我们可以通过插入之前从COLUMN_STATISTICS 表的HISTOGRAM列获得的JSON表示来恢复丢失的直方图,当我们再次查询该表时,我们可以看到直方图已经恢复到以前的状态:
mysql> ANALYZE TABLE t UPDATE HISTOGRAM ON c1 -> USING DATA '{"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],-> "data-type": "int", "null-values": 0.0, "collation-id":-> 8, "last-updated": "2022-10-11 16:13:14.563319",-> "sampling-rate": 1.0, "histogram-type": "singleton",-> "number-of-buckets-specified": 100}';
+--------+-----------+----------+-----------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------+-----------+----------+-----------------------------------------------+
| mydb.t | histogram | status | Histogram statistics created for column 'c1'. |
+--------+-----------+----------+-----------------------------------------------+mysql> TABLE information_schema.column_statistics\G
*************************** 1. row ***************************
SCHEMA_NAME: mydbTABLE_NAME: t
COLUMN_NAME: c1HISTOGRAM: {"buckets": [[206, 0.0625], [456, 0.125], [608, 0.1875]],
"data-type": "int", "null-values": 0.0, "collation-id": 8, "last-updated":
"2022-10-11 16:13:14.563319", "sampling-rate": 1.0, "histogram-type":
"singleton", "number-of-buckets-specified": 100}
加密表(为了避免在统计信息中暴露数据)或临时表不支持生成直方图。
直方图生成适用于除几何体类型(空间数据)和JSON之外的所有数据类型的列。
可以为存储列和虚拟生成列生成直方图。
无法为被单列唯一索引覆盖的列生成直方图。
直方图管理语句试图执行尽可能多的请求操作,并报告其余操作的诊断消息。
例如,如果UPDATE HISTOGRAM语句命名了多个列,但其中一些列不存在或有不受支持的数据类型,则会为其他列生成直方图,并为无效列生成消息。
直方图受以下DDL语句的影响:
DROP TABLE 删除已删除表中列的直方图。
DROP DATABASE 会删除已删除数据库中任何表的直方图,因为该语句会删除数据库中的所有表。
RENAME TABLE 不删除直方图。相反,它将重命名与新表名关联的重命名的直方图。
删除或修改列的ALTER TABLE语句将删除该列的直方图。
ALTER TABLE ... CONVERT TO CHARACTER SET 会删除字符列的直方图,因为它们会受到字符集更改的影响。非字符列的直方图不受影响。
histogram_generation_max_mem_size系统变量控制可用于生成直方图的最大内存量。
全局值和会话值可以在运行时设置。
更改全局histogram_generation_max_mem_size值需要足够的权限来设置全局系统变量。
更改会话histogram_generation_max_mem_size值需要足够的权限来设置受限制的会话系统变量。
参见“系统变量权限”。
【MySQL精通之路】系统变量-系统变量权限-CSDN博客
如果估计要读取到内存中用于生成直方图的数据量超过histogram_generation_max_mem_size定义的限制,MySQL将对数据进行采样,而不是将所有数据读取到内存。采样均匀地分布在整个表格上。MySQL使用SYSTEM采样,这是一种页面级的采样方法。
可以查询 Information Schema库COLUMN_STATISTICS表的HISTOGRAM列中的采样率值,以确定为创建直方图而采样的数据的分数。采样率是一个介于0.0和1.0之间的数字。值为1表示已读取所有数据(无采样)。
以下示例演示为了确保数据量超过本示例中的histogram_generation_max_mem_size限制,在为employees表的birth_date列生成直方图统计信息之前,将该限制设置为低值(2000000字节)。
mysql> SET histogram_generation_max_mem_size = 2000000;mysql> USE employees;mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************Table: employees.employeesOp: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.mysql> SELECT HISTOGRAM->>'$."sampling-rate"'FROM INFORMATION_SCHEMA.COLUMN_STATISTICSWHERE TABLE_NAME = "employees"AND COLUMN_NAME = "birth_date";
+---------------------------------+
| HISTOGRAM->>'$."sampling-rate"' |
+---------------------------------+
| 0.0491431208869665 |
+---------------------------------+
采样率值0.049143120869665意味着来自birth_date列的大约4.9%的数据被读取到存储器中以生成直方图统计。
从MySQL 8.0.19开始,InnoDB存储引擎为存储在InnoDB表中的数据提供了自己的采样实现。当存储引擎不提供自己实现时,MySQL使用的默认采样实现,需要全表扫描,这对于大表来说代价高昂。InnoDB采样实现通过避免全表扫描来提高采样性能。
sampled_pages_read和sampled_pages_skipped INNODB_METRICS计数器可用于监控INNODB数据页的采样。
(有关INNODB_METRICS计数器的一般用法信息,请参阅“INFORMATION_SCHEMA INNODB_METRICS表”。)
【MySQL精通之路】INFORMATION_SCHEMA库-INNODB_METRICS表-CSDN博客
以下示例演示了采样计数器的使用情况,这需要在生成直方图统计信息之前启用计数器。
mysql> SET GLOBAL innodb_monitor_enable = 'sampled%';mysql> USE employees;mysql> ANALYZE TABLE employees UPDATE HISTOGRAM ON birth_date WITH 16 BUCKETS\G
*************************** 1. row ***************************Table: employees.employeesOp: histogram
Msg_type: status
Msg_text: Histogram statistics created for column 'birth_date'.mysql> USE INFORMATION_SCHEMA;mysql> SELECT NAME, COUNT FROM INNODB_METRICS WHERE NAME LIKE 'sampled%'\G
*************************** 1. row ***************************NAME: sampled_pages_read
COUNT: 43
*************************** 2. row ***************************NAME: sampled_pages_skipped
COUNT: 843
此公式近似基于采样计数器数据的采样率:
sampling rate = sampled_page_read/(sampled_pages_read + sampled_pages_skipped)
基于采样计数器数据的采样率与Information Schema库COLUMN_STATISTICS 表的HISTOGRAM列中的采样率值大致相同。
有关为生成直方图而执行的内存分配的信息,请监控Performance Schema库memory/sql/histograms组件。参见“内存汇总表”。
其他注意事项
ANALYZE TABLE从Information Schema库 INNODB_TABLESTATS表中清除表统计信息,并将STATS_INITIALIZE列设置为Uninitialized。下次访问表时会再次收集统计信息。
2.CHECK TABLE语句
CHECK TABLE tbl_name [, tbl_name] ... [option] ...option: {FOR UPGRADE| QUICK| FAST| MEDIUM| EXTENDED| CHANGED
}
CHECK TABLE 检查一个或多个表是否有错误。CHECK TABLE还可以检查视图中是否存在问题,
例如视图定义中引用的不再存在的表。
若要检查表,您必须拥有该表的某些特权。
CHECK TABLE适用于InnoDB、MyISAM、ARCHIVE和CSV表。
在InnoDB表上运行CHECK TABLE之前,请参阅CHECK TABLE-InnoDB表的使用说明。
分区表支持CHECK TABLE,并且可以使用ALTER TABLE。。。CHECK PARTITION可检查一个或多个分区;
有关更多信息,请参阅“ALTER TABLE语句”和“分区的维护”。
CHECK TABLE忽略未编入索引的虚拟生成列。
2.1 输出
CHECK TABLE返回一个结果集,其列如下表所示。
Column | Value |
---|---|
Table | The table name |
Op | Always check |
Msg_type | status , error , info , note , or warning |
Msg_text | An informational message |
该语句可能会为每个选中的表生成许多行信息。最后一行的Msg_type值为status,Msg_text通常应为OK。表已经是最新的,这意味着该表的存储引擎指示无需检查该表。
2.2 检查版本兼容性
FOR UPGRADE选项检查命名表是否与当前版本的MySQL兼容。
使用FOR UPGRADE,服务器会检查每个表,以确定自创建表以来,表的任何数据类型或索引中是否存在任何不兼容的更改。
否则,检查成功。否则,如果可能存在不兼容,服务器会对表进行全面检查(这可能需要一些时间)。
由于数据类型的存储格式已更改或其排序顺序已更改,可能会发生不兼容。
我们的目标是避免这些更改,但偶尔它们对于修改比版本之间的不兼容更糟糕的问题是必要的。
FOR UPGRADE发现这些不兼容性:
InnoDB和MyISAM表的TEXT列中结束空间的索引顺序在MySQL 4.1和5.0之间发生了变化。
新DECIMAL数据类型的存储方法在MySQL 5.0.3和5.0.5之间发生了变化。
有时会对需要重新生成表索引的字符集或排序规则进行更改。
有关这些更改的详细信息,请参阅“MySQL 8.0中的更改”。
有关重建表的信息,请参阅“重建或修复表或索引”。
MySQL 8.0不支持旧版本MySQL中允许的2位数YEAR(2)数据类型。
对于包含YEAR(2)列的表,CHECK TABLE建议使用REPAIR TABLE,它可以将2位数的YEAR(1)列转换为4位数的YEER列。
触发器创建时间保持不变。
如果表包含5.6.4之前格式的旧时态列(TIME、DATETIME和TIMESTAMP列不支持小数秒精度),并且avoid_temporal_upgrade系统变量被禁用,则报告该表需要重新生成。
这有助于MySQL升级过程检测和升级包含旧时态列的表。如果启用了avoid_temporal_upgrade,FOR UPDATE将忽略表中存在的旧临时列;
因此,升级过程不会升级它们。
若要检查包含此类临时列并需要重新生成的表,请在执行CHECK TABLE ... FOR UPGRADE之前禁用avoid_temporal_upgrade
对于使用非本机分区的表发出警告,MySQL 8.0删除了非本机划分。参见 分区。
分区是个大类知识点,需要慢慢啃完。
2.3 检查数据一致性
下表显示了可以提供的其他检查选项。这些选项将传递给存储引擎,存储引擎可能会使用或忽略它们。
类型 | 意义 |
---|---|
QUICK | 不要扫描行以检查不正确的链接。适用于InnoDB和MyISAM表和视图。 |
FAST | 只检查未正确关闭的表。InnoDB忽略;仅适用于MyISAM表和视图。 |
CHANGED | 只检查自上次检查以来已更改或未正确关闭的表。InnoDB忽略;仅适用于MyISAM表和视图。 |
MEDIUM | 扫描行以验证已删除的链接是否有效。这还会计算行的密钥校验和,并使用计算的密钥校验值进行验证。InnoDB忽略;仅适用于MyISAM表和视图。 |
EXTENDED | 对每一行的所有关键点进行完整的关键点查找。这样可以确保表是100%一致的,但需要很长时间。InnoDB忽略;仅适用于MyISAM表和视图。 |
您可以组合检查选项,如以下示例所示,该示例对表进行快速检查以确定表是否正确关闭:
CHECK TABLE test_table FAST QUICK;
注意:
如果CHECK TABLE没有发现标记为“损坏”或“未正确关闭”的表有问题,CHECK TABLE可能会删除该标记。
如果表损坏,问题很可能出现在索引中,而不是数据部分。前面所有的检查类型都会彻底检查索引,因此应该会发现大多数错误。
要检查您认为可以检查的表,请使用no check选项或QUICK选项。
后者应该在紧急的时候使用,并且可以承担QUICK在数据文件中没有发现错误的非常小的风险。(在大多数情况下,在正常使用情况下,MySQL应该会在数据文件中发现任何错误。如果出现这种情况,则表被标记为“已损坏”,在修复之前无法使用。)
FAST和CHANGED主要用于从脚本(例如,从cron执行)中定期检查表。
在大多数情况下,FAST优先于CHANGED。(唯一不推荐的情况是怀疑在MyISAM代码中发现了错误。)
EXTENDED只有在您运行了正常检查,但当MySQL尝试更新行或按键查找行时,仍然会从表中得到错误后才能使用。如果正常检查成功,这种情况就不太可能发生。
使用CHECK TABLE ... EXTENDED 可能会影响查询优化器生成的执行计划。
CHECK TABLE报告的某些问题无法自动更正:
找到auto_increment列的值为0的行。
这意味着表中有一行AUTO_INCREMENT索引列包含值0。(通过使用UPDATE语句显式地将AUTO_INCREMENT列设置为0,可以创建AUTO_INCREMENT列为0的行。)
这本身不是错误,但如果您决定转储表并还原它,或者对表执行ALTER table操作,则可能会导致问题。在这种情况下,AUTO_INCREMENT列根据AUTO_INCREMENT列的规则更改值,这可能会导致重复键错误等问题。
要消除警告,请执行UPDATE语句,将列设置为0以外的某个值。
2.4 InnoDB表的CHECK TABLE的使用说明
以下释适用于InnoDB表:
如果CHECK TABLE遇到损坏的页面,服务器将退出以防止错误传播(Bug#10132)。
如果损坏发生在辅助索引中,虽然表数据可读,但运行CHECK TABLE仍可能导致服务器退出。
如果CHECK TABLE在聚集索引中遇到损坏的DB_TRX_ID或DB_ROLL_PTR字段,CHECK TABLE可能会导致InnoDB访问无效的redolog记录,从而导致MVCC相关的服务器退出。
如果CHECK TABLE在InnoDB表或索引中遇到错误,它会报告一个错误,通常会标记索引,有时还会将表标记为已损坏,从而阻止索引或表的进一步使用。此类错误包括辅助索引中的条目数量不正确或链接不正确。
如果CHECK TABLE在辅助索引中发现不正确的条目数,则会报告错误,但不会导致服务器退出或阻止对该文件的访问。
CHECK TABLE调查索引页面结构,然后调查每个关键条目。它不验证指向集群记录的键指针,也不验证BLOB指针。
当InnoDB表存储在自己的.ibd文件中时,.ibd的前3页包含头信息,而不是表或索引数据。CHECK TABLE语句无法检测仅影响标头数据的情况。
要验证InnoDB.ibd文件的全部内容,请使用innocchecksum命令。
在大型InnoDB表上运行CHECK TABLE时,CHECK TABLE执行过程中可能会阻塞其他线程。为了避免超时,CHECK TABLE操作的信号量等待阈值(600秒)延长了2小时(7200秒)。如果InnoDB检测到信号量等待240秒或更长时间,它将开始将InnoDB监视器输出打印到错误日志中。如果锁定请求超出了信号量等待阈值,InnoDB将中止该过程。要完全避免信号量等待超时的可能性,请运行CHECK TABLE QUICK而不是CHECK TABLE。
InnoDB SPATIAL索引的CHECK TABLE功能包括R树有效性检查和确保R树行数与聚集索引匹配的检查。
CHECK TABLE支持对InnoDB下的虚拟生成列的二级索引。
从MySQL 8.0.14开始,InnoDB支持并行集群索引读取,可以提高CHECK TABLE的性能。InnoDB在CHECK TABLE操作期间读取聚集索引两次。第二次读取可以并行执行。innodb_parallel_read_threads会话变量必须设置为大于1的值,才能进行并行聚集索引读取。默认值为4。
用于执行并行聚集索引读取的实际线程数由innodb_parallel_read_threads设置或要扫描的索引子树数(以较小者为准)决定。
2.5 MyISAM表的CHECK TABLE使用说明
以下适用于MyISAM表:
CHECK TABLE更新MyISAM表的键统计信息。
如果CHECK TABLE输出没有返回OK,或者TABLE已经是最新的,则通常应该运行该表的修复。请参阅“MyISAM表维护和故障恢复”。
如果未指定CHECK TABLE选项QUICK、MEDIUM或EXTENDED,则动态格式MyISAM表的默认检查类型为MEDIUM。
这与在表上运行myisamchk--介质检查tbl_name的结果相同。对于静态格式的MyISAM表,默认检查类型也是MEDIUM,除非指定了CHANGED或FAST。在这种情况下,默认值为QUICK。CHANGED和FAST将跳过行扫描,因为这些行很少损坏。
3.CHECKSUM TABLE语句
CHECKSUM TABLE tbl_name [, tbl_name] ... [QUICK | EXTENDED]
CHECKSUM TABLE报告表内容的校验和。
您可以使用此语句来验证在备份、回滚或其他旨在将数据恢复到已知状态的操作之前和之后的内容是否相同。
此语句需要表的SELECT权限。
视图不支持此语句。如果对视图运行CHECKSUM TABLE,则校验和值始终为NULL,并返回警告。
对于不存在的表,CHECKSUM table返回NULL并生成警告。
在校验和操作期间,表被InnoDB和MyISAM的读锁锁定。
3.1 性能注意事项
默认情况下,逐行读取整个表,并计算校验和。
对于大型表,这可能需要很长时间,因此您只能偶尔执行此操作。
这种逐行计算被用于InnoDB和其他存储引擎(除MyISAM之外)的EXTENDED子句创建的表,或未使用CHECKSUM=1子句创建的MyISAM表所获得的结果。
对于使用CHECKSUM=1子句、CHECKSUM TABLE或CHECKSUM TABLE创建的MyISAM表,CHECKSUM TABLE ... QUICK可以很快返回的“LIVE”表校验和。
如果表不满足所有这些条件,QUICK方法将返回NULL。InnoDB表不支持QUICK方法。有关CHECKSUM子句的语法,请参阅“CREATE TABLE语句”。
校验和值取决于表的行格式。如果行格式发生变化,校验和也会发生变化。
例如,TIME、DATETIME和TIMESTAMP等时态类型的存储格式在MySQL 5.6.5之前的MySQL 5.6中发生了更改,因此,如果5.5表升级到MySQL 5.6,校验和值可能会发生更改。
重要:
如果两个表的校验和不同,那么几乎可以肯定的是,这两个表在某种程度上是不同的。但是,由于CHECKSUM TABLE使用的哈希函数不能保证没有冲突,因此两个不相同的表产生相同校验和的可能性很小。
4.OPTIMIZE TABLE语句
OPTIMIZE [NO_WRITE_TO_BINLOG | LOCAL]TABLE tbl_name [, tbl_name] ...
OPTIMIZE TABLE重新组织表数据和相关索引数据的物理存储,以减少存储空间并提高访问表时的I/O效率。对每个表所做的确切更改取决于该表所使用的存储引擎。
根据表的类型,在这些情况下使用OPTIMIZE TABLE:
在对具有自己的.ibd文件的InnoDB表执行大量插入、更新或删除操作之后,因为它是在启用innodb_file_per_table 选项的情况下创建的。
表和索引被重新组织,磁盘空间可以回收供操作系统使用。
对InnoDB表中FULLTEXT索引的一部分列执行大量插入、更新或删除操作后。
首先设置配置选项innodb_optimize_fulltext_only=1。
要将索引维护期保持在合理的时间内,请设置innodb_ft_num_word_optimize选项以指定要在搜索索引中更新的单词数,并运行一系列OPTIMIZE TABLE语句,直到搜索索引完全更新。
删除MyISAM或ARCHIVE表的大部分,或对具有可变长度行的MyISAM和ARCHIVE(具有VARCHAR、VARBINARY、BLOB或TEXT列的表)进行多次更改后。
已删除的行将保存在链表中,随后的INSERT操作将重用旧的行位置。您可以使用OPTIMIZE TABLE回收未使用的空间并对数据文件进行碎片整理。
在对表进行大量更改后,此语句还可以提高使用该表的语句的性能,有时甚至可以显著提高性能。
此语句要求对表具有SELECT和INSERT特权。
OPTIMIZE TABLE适用于InnoDB、MyISAM和ARCHIVE表。
内存中NDB表的动态列也支持OPTIMIZE TABLE。
它不适用于内存表的固定宽度列,也不适用于磁盘数据表。
OPTIMIZE在NDB Cluster表上的性能可以使用--NDB优化延迟进行调整,该延迟控制OPTIMIZETABLE处理批次行之间的等待时间长度。
有关更多信息,请参阅“NDB集群8.0中解决的先前NDB集群问题”。
对于NDB Cluster表,可以通过(例如)终止执行OPTIMIZE操作的SQL线程来中断OPTIMIZETABLE。
默认情况下,OPTIMIZE TABLE不适用于使用任何其他存储引擎创建的表,并返回一个表示缺乏支持的结果。
通过使用--skip-new选项启动mysqld,可以使OPTIMIZE TABLE适用于其他存储引擎。
在这种情况下,OPTIMIZE TABLE只是映射到ALTER TABLE。
此语句不适用于视图。
分区表支持OPTIMIZE TABLE。有关将此语句用于分区表和表分区的信息,请参阅第26.3.4节“分区的维护”。
默认情况下,服务器将OPTIMIZE TABLE语句写入二进制日志,以便它们复制到副本。要关闭日志记录,请指定可选的NO_WRITE_TO_BINLOG关键字或LOCAL。
4.1 输出
Column | Value |
---|---|
Table | 表名 |
Op | Always optimize |
Msg_type | status , error , info , note , or warning |
Msg_text | An informational message |
OPTIMIZE TABLE表捕获并抛出将表统计信息从旧文件复制到新创建的文件时发生的任何错误。
例如如果的所有者的用户ID为.MYD或.MYI文件与mysqld进程的用户ID不同,OPTIMIZE TABLE会生成一个“无法更改文件所有权”错误,除非mysqld由根用户启动。
4.2 InnoDB详细信息
对于InnoDB表,OPTIMIZE TABLE被映射到ALTER TABLE...FORCE,它重建表以更新索引统计信息并释放聚集索引中未使用的空间。
当您在InnoDB表上运行OPTIMIZE TABLE时,它会显示在输出中,如下所示:
mysql> OPTIMIZE TABLE foo;
+----------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+----------+----------+----------+-------------------------------------------------------------------+
| test.foo | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.foo | optimize | status | OK |
+----------+----------+----------+-------------------------------------------------------------------+
OPTIMIZE TABLE对常规和分区的InnoDB表使用在线DDL,这减少了并发DML操作的停机时间。
OPTIMIZE TABLE触发的表重建已就地完成。
独占表锁只在操作的准备阶段和提交阶段短暂使用。
在准备阶段,将更新元数据并创建一个中间表。
在提交阶段,将提交表元数据更改。
OPTIMIZE TABLE在以下条件下使用表复制方法重建表:
启用old_alter_table系统变量时。
当使用--skip-new选项启动服务器时。
对于包含FULLTEXT索引的InnoDB表,不支持使用在线DDL的OPTIMIZE TABLE操作。而是使用表复制方法。
InnoDB使用页分配方法存储数据,不会像传统存储引擎(如MyISAM)那样出现碎片。
在考虑是否运行优化时,请考虑服务器预计要处理的事务的工作负载:
预计会出现一定程度的碎片化。
InnoDB只填充93%的页面,以便在不需要拆分页面的情况下为更新留出空间。
删除操作可能会留下空白,导致页面填充不足,这可能会使优化表变得值得。
当有足够的空间时,根据数据类型和行格式,对行的更新通常会重写同一页中的数据。
参见“InnoDB表的压缩工作原理”
【MySQL精通之路】InnoDB(9)-表和页压缩(2)-页压缩-CSDN博客
和“InnoDB行格式”。
【MySQL精通之路】行-数据结构-CSDN博客
随着时间的推移,高并发工作负载可能会在索引中留下空白,因为InnoDB通过其MVCC机制保留了同一数据的多个版本。参见“InnoDB多版本”。
【MySQL精通之路】InnoDB(3)-MVCC多版本管理-CSDN博客
4.3 MyISAM 详细信息
对于MyISAM表,OPTIMIZE TABLE的工作原理如下:
1.如果该表已删除或拆分行,请修复该表。
2.如果索引页未排序,请对其进行排序。
3.如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),请更新它们。
4.4 其他注意事项
OPTIMIZE TABLE是针对常规和分区的InnoDB表在线执行的。否则,MySQL会在OPTIMIZE TABLE 运行期间锁定该表。
OPTIMIZE TABLE不对R树索引进行排序,例如POINT列上的空间索引。(错误号23578)
5.REPAIR TABLE语句
REPAIR [NO_WRITE_TO_BINLOG | LOCAL]TABLE tbl_name [, tbl_name] ...[QUICK] [EXTENDED] [USE_FRM]
REPAIR TABLE修复可能损坏的表,仅适用于某些存储引擎。
此语句要求对表具有SELECT和INSERT权限。
尽管通常不应该运行REPAIR TABLE,但如果灾难发生,此语句很可能会从MyISAM表中获取所有数据。
如果您的表经常损坏,请尝试查找原因,以消除使用REPAIR TABLE的依赖。
请参阅“如果MySQL持续崩溃该怎么办”和“MyISAM表问题”。
REPAIR TABLE检查该表以查看是否需要升级。
如果是,它将执行升级,遵循与CHECK TABLE ... FOR UPGRADE.相同的规则
有关更多信息,请参见“CHECK TABLE语句”。
重要:
在执行表修复操作之前,先备份表;
在某些情况下,操作可能会导致数据丢失。可能的原因包括但不限于文件系统错误。
请参阅备份和恢复。
如果服务器在REPAIR TABLE操作过程中退出,则在重新启动后,必须立即对表执行另一条REPAIR TABLE语句,然后再对其执行任何其他操作。
在最坏的情况下,可能会有一个新的干净索引文件,但没有数据文件的信息,然后执行的下一个操作可能会覆盖数据文件。这是一种不太可能但有可能的情况,所以要先备份。
如果源上的表损坏,并且您对其运行REPAIR TABLE ,则对原始表的任何更改都不会传播到副本。
5.1 REPAIR TABLE存储引擎和分区支持
NO_WRITE_TO_BINLOG 或 LOCAL
默认情况下,服务器将REPAIR TABLE语句写入二进制日志,以便它们复制到副本。要抑制日志记录,请指定可选的NO_WRITE_To_BINLOG关键字或其别名LOCAL。
QUICK
如果使用QUICK选项,REPAIR TABLE将尝试只修复索引文件,而不修复数据文件。这种类型的修复就像myisamchk --recover --quick一样
EXTENDED
如果使用EXTENDED选项,MySQL会逐行创建索引,而不是通过排序一次创建一个索引。这种类型的修复就像myisamchk --safe-recover一样。
USE_FRM
USE_FRM选项可用于以下情况。
MYI索引文件丢失或其标头已损坏。此选项告诉MySQL不要信任中的信息。
MYI文件头,并使用数据字典中的信息重新创建它。
这种修复不能用myisamchk来完成。
注意:
仅当不能使用常规的REPAIR模式时,才使用USE_FRM选项。
告诉服务器 忽略.MYI文件使重要的表元数据存储在中.MYI无法用于修复过程,这可能会产生有害后果:
1 当前AUTO_INCREMENT值丢失。
2 表中已删除记录的链接将丢失,这意味着此后已删除记录所用的可用空间仍将未被占用。
3 这个MYI头指示表是否被压缩。如果服务器忽略此信息,则无法判断表是否已压缩,修复可能会导致表内容的更改或丢失。这意味着USE_FRM不应与压缩表一起使用。无论如何,这应该不是必要的:压缩表是只读的,所以它们不应该被破坏。
如果对由与当前运行的MySQL服务器版本不同的MySQL服务器创建的表使用USE_FRM,REPAIR table不会尝试修复该表。
在这种情况下,REPAIR TABLE返回的结果集包含一行,其Msg_type值为error,Msg_text值为Failed repairing incompatible .FRM文件。
如果使用USE_FRM,REPAIR TABLE不会检查表以查看是否需要升级。
5.2 REPAIR TABLE输出
REPAIR TABLE返回一个结果集,其列如下表所示。
Column | Value |
---|---|
Table | The table name |
Op | Always repair |
Msg_type | status , error , info , note , or warning |
Msg_text | An informational message |
REPAIR TABLE语句可能为每个修复的表生成许多行信息。
最后一行的Msg_type值为status,Msg_test通常应该是OK。
对于MyISAM表,如果您没有得到OK,您应该尝试使用myisamchk--safe recover修复它。(REPAIR TABLE并没有实现myisamchk的所有选项。通过myisamckh--safe recover,您还可以使用REPAIR TABLE不支持的选项,例如--max记录长度。)
5.3 表修复注意事项
如果REPAIR TABLE包含5.6.4之前格式的旧时期字段(TIME、DATETIME和TIMESTAMP列不支持小数秒精度),并且avoid_temporal_upgrade系统变量被禁用,则REPAIR TABLE将升级表。
如果启用了avoid_temporal_upgrade,REPAIR TABLE将忽略表中存在的旧时期字段,并且不升级它们。
若要升级包含此类临时列的表,请在执行REPAIR TABLE之前禁用avoid_temporal_upgrade。
您可以通过设置某些系统变量来提高REPAIR TABLE的性能。
请参阅“优化REPAIR TABLE语句”。