4. 基于共享的直接数据分发
Snowflake 的共享(Share)是一种“零拷贝”的数据分发机制:数据仍然只存放在提供方账户的数据库中,消费者账户通过共享对象获得对指定对象的只读访问权,而不会产生数据副本。理解这一点非常关键——共享不是导出文件,也不是复制表,而是把“访问权”授予另一个账户。因此,一次完整的直接数据分发任务,本质上由四个动作构成:创建共享容器 → 向共享中授予对象权限 → 把消费者账户加入共享 → 以消费者身份验证访问。下面按真实操作顺序展开。
一、创建共享:先有容器,再谈内容
共享本身是一个空的命名容器,创建时并不包含任何数据对象。使用提供方账户的 ACCOUNTADMIN 角色(或拥有 CREATE SHARE 权限的角色)执行:
USE ROLE ACCOUNTADMIN;
CREATE SHARE sales_share_retail
COMMENT = '零售部门向外部合作方分发的销售汇总数据';
创建后可用 SHOW SHARES; 查看,此时 sales_share_retail 的 kind 为 OUTBOUND,表示这是一个对外共享。注意:共享是账户级对象,不属于某个数据库,因此命名时建议带上部门或用途前缀,便于多部门治理时区分归属。
二、授予对象权限:把“哪些对象、什么权限”放进共享
共享中只能放入数据库、模式、表、视图、安全视图、外部表、函数等对象,且授予的权限只能是 USAGE(对库和模式)与 SELECT(对表、视图等)。关键规则是:要共享一个表,必须先共享它所在的数据库和模式,否则消费者看不到路径。示例中提供方有一个数据库 retail_db,模式 sales_mart,其中有一张汇总表 monthly_sales_summary:
GRANT USAGE ON DATABASE retail_db
TO SHARE sales_share_retail;
GRANT USAGE ON SCHEMA retail_db.sales_mart
TO SHARE sales_share_retail;
GRANT SELECT ON TABLE retail_db.sales_mart.monthly_sales_summary
TO SHARE sales_share_retail;
这里有一个治理上的重要选择:如果直接共享基表,消费者能看到表内全部行与列;如果只想暴露部分数据,应先创建安全视图(Secure View),在视图里做行过滤或列裁剪,再共享视图。例如只暴露华东区域、且隐藏成本列:
CREATE OR REPLACE SECURE VIEW retail_db.sales_mart.v_region_sales
AS SELECT region, month, revenue
FROM retail_db.sales_mart.monthly_sales_summary
WHERE region = 'East';
GRANT SELECT ON VIEW retail_db.sales_mart.v_region_sales
TO SHARE sales_share_retail;
安全视图的定义对消费者不可见,消费者只能查询结果,这使共享在“直接分发”的同时仍保留最小权限原则。授予完成后,可用 SHOW GRANTS TO SHARE sales_share_retail; 核对共享内对象清单,确认没有多授、漏授。
三、添加消费者账户:把共享指向具体账户
共享必须绑定到具体的消费者账户。Snowflake 支持两种方式:一是按账户名直接添加(适用于同一区域内已知账户),二是通过账户定位符(account locator)或组织中的账户名添加。以直接添加为例:
ALTER SHARE sales_share_retail
ADD ACCOUNTS = partner_retail_acct;
如果消费者账户与提供方不在同一区域,则需要使用数据共享复制或跨区域共享能力,此时共享会先复制到目标区域再被消费。添加成功后,消费者账户会在其 SHOW SHARES; 中看到该共享,但此时还看不到任何数据——必须由消费者主动“挂载”。
四、消费者侧挂载与验证访问
消费者账户使用 ACCOUNTADMIN 角色,从共享创建数据库:
CREATE DATABASE partner_sales_db
FROM SHARE provider_acct.sales_share_retail;
SHOW OBJECTS IN DATABASE partner_sales_db;
创建后,消费者即可像查询本地表一样查询共享对象,但只能读、不能写:
SELECT region, month, SUM(revenue) AS total_rev
FROM partner_sales_db.sales_mart.v_region_sales
GROUP BY region, month
ORDER BY month;
验证访问是否真正生效,建议从三个角度检查:可见性——SHOW OBJECTS 能看到预期对象;可读性——查询返回数据且行数与提供方视图一致;权限边界——尝试对共享对象执行 INSERT/UPDATE 应报错,尝试访问未共享的表应提示对象不存在。若消费者看不到对象,优先检查提供方是否漏授了库或模式的 USAGE 权限;若查询报“insufficient privileges”,则检查表或视图的 SELECT 是否已授予共享。
五、治理要点与常见排障
直接数据分发虽然操作简洁,但在多部门场景下必须配合治理约束。第一,共享对象最小化:优先共享安全视图而非基表,避免把整张明细表暴露给外部。第二,权限可追溯:定期执行 SHOW GRANTS TO SHARE 与 SHOW SHARES,形成共享清单,明确“哪个共享、给了哪个账户、包含哪些对象”。第三,撤销要及时:合作结束时用 REVOKE SELECT ON ... FROM SHARE 收回对象权限,或用 ALTER SHARE ... REMOVE ACCOUNTS 移除消费者账户,二者作用不同,前者影响所有消费者,后者只影响指定账户。
常见问题与判断依据可以归纳为:消费者看不到数据库,通常是提供方未授予数据库或模式的 USAGE;能看到库但看不到表,通常是表或视图的 SELECT 未授予共享;查询报权限不足,通常是消费者角色未被授予对该共享数据库的 USAGE;跨区域消费者无法挂载,通常是共享未复制到目标区域。掌握这条“容器—权限—账户—验证”的链路,就能在多部门数据分发中既快速交付,又保持权限边界清晰。