对表pg_statistic
的访问被限制于超级用户,因此普通用户无法从中知道其他用户的表的内容。某些选择度估计函数会使用用户提供的操作符(查询中出现的操作符或者有关的操作符)来分析存储的统计信息。例如,为了确定一个存储的最常用值是否适用,选择度估算器将必须运行适当的=
操作符来比较查询中的常量和存储的值。因此pg_statistic
中的数据有可能会被传给用户定义的操作符。精心制作的操作符可以有意地泄露传入的操作数(例如通过把它们记入一个不同的表中),或者无意中把它们的值显示在错误消息中,在两种情况中pg_statistic
中的数据都有可能被暴露给一个本不能看到它的用户。
为了防止这种事情的发生,下面的措施适用于所有内建的选择度估计函数。在规划一个查询时,为了能够使用存储的统计信息,当前用户必须具有该表或者涉及到的列上的SELECT
特权,或者用到的操作符必须是LEAKPROOF
(更准确地说是该操作符所基于的函数)。如果不满足这样的要求,则选择度估计函数的行为就好像没有统计信息可用一样,并且规划器将退回到使用默认的假定估计值。
如果一个用户在该表或列上没有所需的特权,那么在很多情况下查询将最终收到一个permission-denied错误,在这种情况下实际上这种机制是不可见的。但是如果用户正在从一个安全性屏障视图中读取,则规划器可能希望检查底层表的统计信息,而底层表的统计信息可能对用户是不可访问的。在这种情况下,操作符应该是防泄漏的,否则统计信息将不会被使用。但对于这样一种后果不会有任何直接的反馈信息,唯一的迹象是得到的计划并不是最优的。如果有人怀疑遇到了这种情况,他可以尝试以一个具有更高特权的用户来运行该查询,看看是否能得到一个不同的规划结果。
这种限制仅适用于规划器需要在pg_statistic
中一个或者多个值上执行用户定义的操作符的情况。因此,规划器被允许使用一般的统计性信息,例如空值所占的比例或者一列中可区分值的数量,而不需要考虑访问特权。
包含在第三方扩展中可能会用用户定义的操作符在统计信息上操作的选择度估计函数应该遵循相同的安全性规则。具体的指南请参考PostgreSQL的源代码。