对表 pg_statistic 的访问仅限于超级用户,这样
普通用户就无法从中了解其他用户表的内容。一些选择性估算函数会使用
用户提供的操作符(查询中出现的操作符或相关操作符)来分析存储的统计
信息。例如,为了判断某个存储的最常见值是否适用,选择性估算器必须
运行相应的 = 操作符,将查询中的常量与存储的值进行
比较。因此 pg_statistic 中的数据可能会被传递
给用户定义的操作符。一个精心构造的操作符可以故意泄露被传递的操作数
(例如,把它们记录到日志或写入另一个表),也可能通过在错误消息中显示
它们的值而意外泄露。无论哪种情况,都可能把
pg_statistic 中的数据暴露给本不应看到它的
用户。
为了防止这种情况,所有内置的选择性估算函数都遵循以下规则。在规划
查询时,为了能够使用存储的统计信息,当前用户必须对表或相关列拥有
SELECT 权限,或者所使用的操作符必须是
LEAKPROOF(更准确地说,是该操作符所基于的函数)。
如果不满足,选择性估算器将表现得好像没有任何统计信息可用,规划器会
采用默认或回退假设继续工作。
psql 程序的
\do+
元命令可用于确定哪些操作符被标记为防泄露(leakproof)。
如果用户对表或列没有所需权限,那么在很多情况下查询最终会收到权限 拒绝错误,此时这一机制在实践中是不可见的。但如果用户正在读取一个 安全屏障视图,规划器可能会希望检查某个用户本无法访问的底层表的统计 信息。在这种情况下,操作符必须是防泄露的,否则统计信息将不会被使用。 对此没有直接的反馈,唯一的表现是计划可能欠优。如果怀疑是这种情况, 可以尝试用权限更高的用户运行该查询,看看是否会得到不同的计划。
这一限制只适用于规划器需要对来自 pg_statistic
的一个或多个值执行用户定义操作符的情形。因此,无论访问权限如何,
规划器都可以使用一般性的统计信息,例如空值比例或列中不同值的个数。
第三方扩展中包含的选择性估算函数如果可能用用户定义操作符处理统计 信息,也应遵循同样的安全规则。具体指导请查阅 PostgreSQL 源代码。