如何破坏数据库:制造损坏

本页目录

有时候,你可能想要破坏一个数据库 — 用于学习目的,模拟故障,学习如何处理这些故障,测试缓解措施等。

让我们讨论一些破坏的方法。

⚠️ 不要在生产环境中尝试,除非你是一名混沌工程师 ⚠️

数据损坏

有很多类型的损坏,并且有非常简单的方法可以使数据库损坏,例如:

👉 直接修改系统目录:

PSQL
nik=# create table t1(id int8 primary key, val text);
CREATE TABLE

nik=# delete from pg_attribute where attrelid = 't1'::regclass and attname = 'val';
DELETE 1

nik=# table t1;
ERROR:  pg_attribute catalog is missing 1 attribute(s) for relation OID 107006
LINE 1: table t1;
          ^

更多方法可以在这篇文章中找到:How to corrupt your PostgreSQL database,其中一些有趣的方法包括:

一个有用的方法是使用 dd 直接写入数据文件。此方法可以用于模拟通过校验和验证检测到的损坏 (Day 37: How to enable data checksums without downtime)。在这篇文章中也有展示:pg_healer: repairing Postgres problems automatically。

首先,创建一个表并查看数据文件所在位置:

PSQL
nik=# show data_checksums;
 data_checksums
----------------
 on
(1 row)

nik=# create table t1 as select i from generate_series(1, 10000) i;
SELECT 10000

nik=# select count(*) from t1;
 count
-------
 10000
(1 row)

nik=# select format('%s/%s',
  current_setting('data_directory'),
  pg_relation_filepath('t1'));
                      format
---------------------------------------------------
 /opt/homebrew/var/postgresql@15/base/16384/123388
(1 row)

现在,使用 dd 直接写一些垃圾数据至文件中 (请注意,这里我们使用的是 macOS 版本,其中 dd 有选项 oseek - 在 Linux 上,它是 seek_bytes),然后重启 Postgres 以确保表不再存在于缓冲池中:

Shell
❯ echo -n "BOOoo" \
  | dd conv=notrunc bs=1 \
    oseek=4000 count=1 \
    of=/opt/homebrew/var/postgresql@15/base/16384/123388
 1+0 records in
 1+0 records out
 1 bytes transferred in 0.000240 secs (4167 bytes/sec)

❯ brew services stop postgresql@15
 Stopping `postgresql@15`... (might take a while)
 ==> Successfully stopped `postgresql@15` (label: homebrew.mxcl.postgresql@15)

❯ brew services start postgresql@15
 ==> Successfully started `postgresql@15` (label: homebrew.mxcl.postgresql@15)

成功损坏 — 数据校验和机制对此发出了警告:

PSQL
nik=# table t1;
WARNING:  page verification failed, calculated checksum 52379 but expected 35499
ERROR:  invalid page in block 0 of relation base/16384/123388

🔜 未完待续 ...

讨论与补充

在 GitHub 查看讨论
其他历史讨论(1)

支持作者

感谢支持 PostgreSQL Howto 的长期维护。

微信赞赏码

读者交流群

二维码若已过期,可通过公众号 PostgreSQL 学徒或邮件联系。

PostgreSQL 学徒读者交流群二维码