1.优化渠道删除失败问题
This commit is contained in:
127
server/db/fix_bt_backup_view_tables.php
Normal file
127
server/db/fix_bt_backup_view_tables.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* 解决宝塔面板备份偶发报错:
|
||||
* “备份文件中缺少表: xxx__view_backup”
|
||||
*
|
||||
* 原因通常是:数据库存在 VIEW,但宝塔的备份校验按“表”去匹配,
|
||||
* 或其内部会期望存在 xxx__view_backup 之类的“视图备份表”标记。
|
||||
*
|
||||
* 本脚本会:
|
||||
* - 扫描当前库所有 VIEW
|
||||
* - 为每个 VIEW 创建一个同名的备份表:<view_name>__view_backup
|
||||
* - 在该表写入 SHOW CREATE VIEW 的结果(若权限不足则写入空串)
|
||||
*
|
||||
* 用法(在 server 目录执行):
|
||||
* php db/fix_bt_backup_view_tables.php
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
if (class_exists(\Dotenv\Dotenv::class) && is_file(dirname(__DIR__) . '/.env')) {
|
||||
if (method_exists(\Dotenv\Dotenv::class, 'createUnsafeMutable')) {
|
||||
\Dotenv\Dotenv::createUnsafeMutable(dirname(__DIR__))->load();
|
||||
} else {
|
||||
\Dotenv\Dotenv::createMutable(dirname(__DIR__))->load();
|
||||
}
|
||||
}
|
||||
|
||||
$host = getenv('DB_HOST') ?: '127.0.0.1';
|
||||
$port = getenv('DB_PORT') ?: '3306';
|
||||
$dbName = getenv('DB_NAME') ?: '';
|
||||
$user = getenv('DB_USER') ?: '';
|
||||
$pass = getenv('DB_PASSWORD') ?: '';
|
||||
|
||||
if ($dbName === '' || $user === '') {
|
||||
fwrite(STDERR, "Missing DB_NAME/DB_USER in .env\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$dsn = "mysql:host={$host};port={$port};dbname={$dbName};charset=utf8mb4";
|
||||
$pdo = new PDO($dsn, $user, $pass, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
]);
|
||||
|
||||
$views = $pdo
|
||||
->query("SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME")
|
||||
->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
if (!$views) {
|
||||
echo "No views found; nothing to do.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$created = 0;
|
||||
$updated = 0;
|
||||
$failed = 0;
|
||||
|
||||
foreach ($views as $viewName) {
|
||||
$viewName = (string) $viewName;
|
||||
$backupTable = $viewName . '__view_backup';
|
||||
|
||||
if (!preg_match('/^[a-zA-Z0-9_]+$/', $backupTable)) {
|
||||
$failed++;
|
||||
echo "[skip] invalid name: {$backupTable}\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo->exec(
|
||||
"CREATE TABLE IF NOT EXISTS `{$backupTable}` (
|
||||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`view_name` VARCHAR(255) NOT NULL,
|
||||
`create_sql` LONGTEXT NOT NULL,
|
||||
`updated_at` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_view_name` (`view_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
||||
);
|
||||
$created++;
|
||||
} catch (Throwable $e) {
|
||||
$failed++;
|
||||
echo "[fail] create table {$backupTable}: " . $e->getMessage() . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$createSql = '';
|
||||
try {
|
||||
$stmt = $pdo->query("SHOW CREATE VIEW `{$viewName}`");
|
||||
$row = $stmt ? $stmt->fetch(PDO::FETCH_ASSOC) : false;
|
||||
if ($row) {
|
||||
// SHOW CREATE VIEW 返回字段名可能是 "Create View" 或类似
|
||||
foreach ($row as $k => $v) {
|
||||
if (is_string($k) && stripos($k, 'create') !== false && is_string($v)) {
|
||||
$createSql = $v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
// 权限不足也不阻断,只是留空,保证备份表存在
|
||||
$createSql = '';
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare(
|
||||
"INSERT INTO `{$backupTable}` (`view_name`, `create_sql`, `updated_at`)
|
||||
VALUES (:view_name, :create_sql, :updated_at)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`create_sql` = VALUES(`create_sql`),
|
||||
`updated_at` = VALUES(`updated_at`)"
|
||||
);
|
||||
$stmt->execute([
|
||||
'view_name' => $viewName,
|
||||
'create_sql' => $createSql,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
$updated++;
|
||||
echo "[ok] {$viewName} -> {$backupTable}\n";
|
||||
} catch (Throwable $e) {
|
||||
$failed++;
|
||||
echo "[fail] upsert {$backupTable}: " . $e->getMessage() . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done. created={$created}, updated={$updated}, failed={$failed}\n";
|
||||
|
||||
Reference in New Issue
Block a user