当 secure_delete 打开时,SQLite 会用零覆盖已删除的内容。 1
SQLite 如何“用零覆盖已删除的内容”?这些 删除的内容可能位于数据库文件的中间。
SQLite是否通过重写之后的每个字节来实现这种机制 删除的内容?这样,可能会引入大量的磁盘IO。 例如,当删除的内容后面有2GB数据时,这 安全删除过程需要重写以下所有内容 2GB 数据到文件系统。那会花费很多时间。
secure_delete 打开或关闭可能没有什么区别,因为在任何一种情况下,更改后的所需页面都必须写入文件。
也许考虑以下内容(相当于约 1.5GB,即 417826 个页面,每页 4k)。
删除单表所有行后的最终结果是页数减少到4。
DROP TABLE IF EXISTS t1;
CREATE TABLE IF NOT EXISTS t1(id INTEGER PRIMARY KEY, v1 TEXT, v2 TEXT);
WITH cte(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM cte LIMIT 100000000)
INSERT INTO t1 (v1,v2) SELECT 'XXX','YYY' FROM cte;
PRAGMA page_count;
PRAGMA secure_delete;
PRAGMA secure_delete = 'off';
PRAGMA secure_delete;
DELETE FROM t1 WHERE id % 2;
PRAGMA page_count;
SELECT * FROM t1;
PRAGMA secure_delete;
PRAGMA secure_delete = 'on';
PRAGMA secure_delete;
DELETE FROM t1 WHERE NOT id % 2;
PRAGMA page_count;
SELECT count(*) FROM t1;
DROP TABLE IF EXISTS t1;
运行时插入大约需要 74 秒:-
WITH cte(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM cte LIMIT 100000000)
INSERT INTO t1 (v1,v2) SELECT 'XXX','YYY' FROM cte
> Affected rows: 100000000
> Time: 74.017s
当 secure_delete 关闭时,第一次删除 50% 的行大约需要 40 秒:-
DELETE FROM t1 WHERE id % 2
> Affected rows: 50000000
> Time: 40.71s
虽然在 secure_delete 打开的情况下第二次删除剩余行的时间稍微短一些,大约为 38 秒:-
DELETE FROM t1 WHERE NOT id % 2
> Affected rows: 50000000
> Time: 34.383s
当然,时间取决于执行环境。还应该注意的是,记录模式可能会影响计时。
当然上面的代码可以根据需要进行修改。