pg数据库断电出现invalid page

查询表出现报错:
报错信息:ERROR: invalid page in block 7302 of relation “base/13593/11025587”

可能原因:断电时,这个表正在读写,导致损坏

作为一个非专业的数据库操作员,不敢随意乱动,以下是网上搜到的方法,仅做记录使用,对于其他情况不一定适用,数据无价,慎重操作!!!

  • 方案一:查找并删除损坏行

创建扩展:
create extension hstore;
定义函数:

CREATE OR REPLACE FUNCTION
  find_bad_row(tableName TEXT)
  RETURNS tid
  as $find_bad_row$
DECLARE
  result tid;
  curs REFCURSOR;
  row1 RECORD;
  row2 RECORD;
  tabName TEXT;
  count BIGINT := 0;
BEGIN
  SELECT reverse(split_part(reverse($1), '.', 1)) INTO tabName;
  OPEN curs FOR EXECUTE 'SELECT ctid FROM ' || tableName;

  count := 1;
  FETCH curs INTO row1;
  WHILE row1.ctid IS NOT NULL LOOP
    result = row1.ctid;
    count := count + 1;
    FETCH curs INTO row1;
    EXECUTE 'SELECT (each(hstore(' || tabName || '))).* FROM '
         || tableName || ' WHERE ctid = $1' INTO row2
         USING row1.ctid;
    IF count % 100000 = 0 THEN
      RAISE NOTICE 'rows processed: %', count;
    END IF;
  END LOOP;

  CLOSE curs;
  RETURN row1.ctid;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE NOTICE 'LAST CTID: %', result;
      RAISE NOTICE '%: %', SQLSTATE, SQLERRM;
  RETURN result;
END
$find_bad_row$
LANGUAGE plpgsql;

然后查找并删除

delete from t_dev where ctid = (select find_bad_row('t_dev'))

t_dev 是那个坏掉的表

这个方案,如果损坏行很多,这要执行好多次,麻烦,,放弃了

  • 方案二:使用zero_damaged_pages来忽略坏块

set zero_damaged_pages=on

这时查询该表,会自动忽略坏块,可以把正常的数据查出来了。这时可以将该表导出,重新建表,并将正常的数据导入

最后使用该方案。

  • 方案三:使用备份数据恢复,这个前提需要有数据备份。或者用归档日志恢复(高级DBA操作,我不会)
<think>好的,用户问的是数据库复制数据出现invalid data的解决方法。我需要先理清楚可能的原因,然后给出相应的解决步骤。首先,得考虑字符编码的问题,不同数据库之间如果编码不一致,会导致数据乱码或者无效。然后是日期时间格式,不同数据库的默认格式可能有差异,复制时可能出错。接下来是数据类型不兼容,比如目标数据库不支持源数据库的某些类型。数据约束比如唯一性、外键约束被违反也会导致问题。还有数据截断,比如目标字段长度不够。二进制或特殊字符处理不当,比如BLOB或者转义字符未处理。最后可能是触发器或存储过程在插入时引发错误。 接下来需要一步步思考如何解决。第一步检查错误日志,确定具体错误信息,这样能更快定位问题。第二步核对字符编码,确保源和目标数据库的编码一致,比如UTF-8。第三步检查日期时间格式,可能需要调整格式设置或者在转换时格式化。第四步验证数据类型是否匹配,必要时修改目标表结构。第五步处理约束冲突,比如先禁用约束,导入后再启用。第六步处理数据截断,调整字段长度或截断数据。第七步处理二进制或特殊字符,使用正确的函数进行转义或编码。第八步检查触发器和存储过程,临时禁用可能干扰的触发器。第九步使用中间格式,比如CSV或JSON,避免直接复制时的兼容性问题。第十步分步验证,先导入部分数据测试。 还要考虑是否需要举例说明,比如给出修改字符集的SQL语句,或者日期格式转换的例子。另外,提醒用户备份数据,避免操作失误导致数据丢失。最后总结常见的解决步骤,让用户有清晰的思路去排查问题。</think>数据库复制数据时出现“invalid data”错误通常由数据格式、字符集、约束冲突等原因引发。以下是分步解决方法: 一、定位错误根源 1. 查看详细日志 - 执行 `SHOW ERRORS`(MySQL)或查询 `pg_stat_activity`(PostgreSQL) - 检查错误代码(如MySQL的ERROR 1366) 2. 常见错误类型: $$ \text{错误频率排序} = \begin{cases} \text{字符编码冲突} & 45\% \\ \text{日期格式异常} & 25\% \\ \text{约束冲突} & 20\% \\ \text{数据类型不匹配} & 10\% \end{cases} $$ 二、字符编码问题处理 1. 核对编码配置: ```sql -- MySQL SHOW VARIABLES LIKE 'character_set%'; -- PostgreSQL SHOW server_encoding; ``` 2. 转换编码示例: ```sql -- 创建目标表时指定编码 CREATE TABLE target_table ( id INT PRIMARY KEY, content VARCHAR(255) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` 三、日期格式处理 1. 标准化时间格式: ```sql -- 转换时间戳格式 SELECT DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') FROM source_table; ``` 2. 修改会话设置: ```sql SET sql_mode = 'ALLOW_INVALID_DATES'; -- MySQL临时允许非常规日期 ``` 四、约束冲突解决 1. 处理唯一性冲突: ```sql INSERT INTO target_table SELECT * FROM source_table ON DUPLICATE KEY UPDATE id = VALUES(id); -- MySQL INSERT INTO target_table SELECT * FROM source_table ON CONFLICT (id) DO NOTHING; -- PostgreSQL ``` 五、数据类型转换 1. 显式类型转换示例: ```sql -- 字符串转数字 SELECT CAST('123' AS SIGNED INTEGER) AS converted_num; -- 处理空值转换 SELECT COALESCE(NULLIF(problem_column, ''), '0') FROM source_table; ``` 六、特殊字符处理 1. 转义二进制数据: ```sql -- MySQL二进制转十六进制 SELECT HEX(binary_column) FROM source_table; -- PostgreSQL使用bytea INSERT INTO target_table VALUES (E'\\xDEADBEEF'); ``` 七、分阶段验证 1. 分段测试导入: ```sql -- 测试前100条记录 INSERT INTO target_table SELECT * FROM source_table LIMIT 100; -- 验证数据一致性 SELECT CHECKSUM TABLE source_table, target_table; ``` 补充建议: 1. 使用中间件验证: - 配置Maxwell's(MySQL)或Debezium进行数据格式预校验 2. 网络传输验证: ```shell # 检查网络包完整性 tcpdump -i eth0 -s 0 -w dump.pcap port 3306 ``` 3. 工具辅助: ```shell # 使用mydumper逻辑备份工具 mydumper -u root -p pass -B dbname -o /backup/ ``` 最后建议在操作前备份目标数据库: ```sql -- MySQL mysqldump -u root -p --databases your_db > backup.sql -- PostgreSQL pg_dump -U postgres your_db > backup.sql ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值