Skip to content

MySQL - 修复表

重要提示:REPAIR TABLE 与存储引擎

Section titled “重要提示:REPAIR TABLE 与存储引擎”

重要提示: REPAIR TABLE 语句几乎专为 MyISAM 存储引擎设计。现代 MySQL 安装使用 InnoDB 作为默认存储引擎,它是一个具有自动恢复机制的事务性、崩溃安全引擎。在 InnoDB 表上运行 REPAIR TABLE 将导致错误,指出存储引擎不支持修复。 本教程侧重于在预期上下文中使用 REPAIR TABLE:维护旧版 MyISAM 表。

在尝试修复之前,请务必检查表的存储引擎:

SHOW CREATE TABLE your_table_name;

查找输出中的 ENGINE= 值。如果显示 InnoDB,请不要使用 REPAIR TABLE。相反,请依靠 MySQL 的崩溃恢复或从备份中恢复。

MyISAM 表与 InnoDB 不同,它们不是事务性的,更容易因意外服务器关机、硬件故障或操作系统崩溃等事件而损坏。损坏可能表现为尝试从表中读取时出错、返回不正确的数据或完全无法访问表。

REPAIR TABLE 语句通过检查表的数据文件 (.MYD) 和索引文件 (.MYI) 并纠正其发现的任何不一致性来尝试修复这些问题。

REPAIR [TABLE] table_name [, table_name] ... [QUICK] [EXTENDED] [USE_FRM];

让我们明确使用 MyISAM 引擎创建一个表进行演示。

CREATE TABLE LegacyLogs (
id INT AUTO_INCREMENT PRIMARY KEY,
message VARCHAR(255) NOT NULL,
log_time TIMESTAMP
) ENGINE=MyISAM; -- 明确将引擎设置为 MyISAM
INSERT INTO LegacyLogs (message, log_time) VALUES ('System start', NOW());

现在,假设此表已损坏。要修复它,您可以运行:

REPAIR TABLE LegacyLogs;

输出是一个结果集,指示修复操作的状态。在未损坏的表上成功修复将如下所示:

表操作消息类型消息文本
your_database.legacylogsrepairstatusOK

如果表已损坏,Msg_type 和 Msg_text 将显示 info(信息)、warning(警告)或 error(错误)消息,详细说明发现并修复的问题。

您可以通过提供逗号分隔的列表,在一个命令中修复多个表。

CREATE TABLE OldUsers (id INT) ENGINE=MyISAM;
CREATE TABLE OldSettings (id INT) ENGINE=MyISAM;
-- 同时修复两个表
REPAIR TABLE OldUsers, OldSettings;

结果集将包含每个已处理表的一行。

REPAIR TABLE 选项(QUICK、EXTENDED、USE_FRM)

Section titled “REPAIR TABLE 选项(QUICK、EXTENDED、USE_FRM)”

QUICK 选项执行更快的修复,只检查索引文件 (.MYI),不修改数据文件 (.MYD)。这对于修复轻微的索引损坏很有用。

REPAIR TABLE LegacyLogs QUICK;

EXTENDED 选项执行最彻底的修复。它逐行遍历数据文件并从头开始重新创建索引。这要慢得多,但可以修复其他方法无法修复的损坏。

REPAIR TABLE LegacyLogs EXTENDED;

USE_FRM 选项是一种最后手段,当 .MYI 索引文件丢失或其头部损坏时使用。它告诉 MySQL 根据表定义文件 (.frm) 和数据文件 (.MYD) 中的信息重建索引文件。

REPAIR TABLE LegacyLogs USE_FRM;

您可以从任何客户端程序执行 REPAIR TABLE。关键是正确解析多行结果集以检查每个已修复表的状态。

Node.js (mysql2)
Python (mysql-connector-python)
Java (JDBC)
PHP (mysqli)
此 Node.js 示例修复多个表并记录每个表的结果。
```javascript
// 必需:npm install mysql2
const mysql = require('mysql2/promise');
async function repairLegacyTables() {
let connection;
try {
connection = await mysql.createConnection({
host: 'localhost', user: 'root', password: 'your_password', database: 'your_database'
});
console.log('Connected. Attempting to repair tables...');
const [results] = await connection.query('REPAIR TABLE LegacyLogs, OldUsers, OldSettings');
console.log('Repair operation finished. Results:');
results.forEach(result => {
console.log(`- Table: ${result.Table}, Operation: ${result.Op}, Status: ${result.Msg_type}, Message: ${result.Msg_text}`);
});
} catch (error) {
console.error(`An error occurred: ${error.message}`);
} finally {
if (connection) await connection.end();
}
}
repairLegacyTables();

Python 的 mysql-connector-python 可用于执行命令并迭代结果。

// 必需:pip install mysql-connector-python
import mysql.connector
def repair_legacy_tables():
try:
with mysql.connector.connect(user='root', password='your_password', database='your_database') as conn:
with conn.cursor(dictionary=True) as cursor:
print('Connected. Attempting to repair tables...')
cursor.execute('REPAIR TABLE LegacyLogs, OldUsers, OldSettings')
print('Repair operation finished. Results:')
for result in cursor.fetchall():
print(f"- Table: {result['Table']}, Op: {result['Op']}, Status: {result['Msg_type']}, Message: {result['Msg_text']}")
except mysql.connector.Error as err:
print(f"Database error: {err}")
repair_legacy_tables()

在 Java 中,您执行查询并遍历 ResultSet 以获取每个表的状态。

import java.sql.*;
public class RepairTableExample {
private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database";
private static final String USER = "root";
private static final String PASS = "your_password";
public static void main(String[] args) {
String sql = "REPAIR TABLE LegacyLogs, OldUsers, OldSettings";
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
System.out.println("Repair operation finished. Results:");
while (rs.next()) {
System.out.printf("- Table: %s, Op: %s, Status: %s, Message: %s%n",
rs.getString("Table"),
rs.getString("Op"),
rs.getString("Msg_type"),
rs.getString("Msg_text"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

PHP 的 mysqli 扩展可以运行 REPAIR TABLE 查询并获取结果。

<?php
$mysqli = new mysqli('localhost', 'root', 'your_password', 'your_database');
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
$sql = "REPAIR TABLE LegacyLogs, OldUsers, OldSettings";
if ($result = $mysqli->query($sql)) {
echo "Repair operation finished. Results:\n";
while ($row = $result->fetch_assoc()) {
printf("- Table: %s, Op: %s, Status: %s, Message: %s\n",
$row['Table'],
$row['Op'],
$row['Msg_type'],
$row['Msg_text']);
}
$result->free();
} else {
echo "Error repairing tables: " . $mysqli->error;
}
$mysqli->close();
?>