タグの自動伝播時の競合処理オプションについて整理してみる #SnowflakeDB
はじめに
2025年5月のアップデートでユーザー定義のタグが下流のオブジェクトに自動伝播(Automatic propagation)する機能が一般提供となりました。また、2025年7月のアップデートでは、タグの自動伝播の監視方法としてイベントテーブルを使用する機能が一般提供となっています。
異なるソースオブジェクトから同じターゲットオブジェクトにタグが伝播されると、競合が発生する可能性があります。競合発生時の処理オプションについて整理しておきたく、イベントテーブルでのモニタリングとあわせて検証しましたので記事としました。
タグ伝播の競合
前提として、タグの自動伝播については以下の記事が参考になると思います。
タグ伝播の競合(Tag propagation conflicts)は、異なるソースオブジェクトから同じターゲットオブジェクトに同じタグが伝播される際に、そのタグが各ソースオブジェクトで異なる値を持っている場合に発生します。
ただし、以下のケースでは競合とはみなされません。
- ターゲットオブジェクトに手動でタグが適用される場合
- 手動で設定されたタグ値が、伝播された値よりも優先される
- ターゲットオブジェクトがSnowflakeのオブジェクト階層で上位のオブジェクトから値を継承している場合
競合発生時の処理方法は以下の3つのオプションが用意されています。
- 競合するタグ値を「CONFLICT」で置き換え
- デフォルトの操作
- タグのプロパティである
ON_CONFLICT
を設定していない場合は、このオプションが適用される
- タグのプロパティである
- 競合発生時のタグの値は自動的に
CONFLICT
という文字列に置き換えられる
- デフォルトの操作
- ユーザー定義の文字列で値を置き換え
- タグのプロパティである
ON_CONFLICT
に、競合時に使用したい特定の文字列を指定することで、対象のタグで競合が発生した際は、この値が使用される
- タグのプロパティである
- タグの
ALLOWED_VALUES
パラメータで定義された値の順序を使用ON_CONFLICT = ALLOWED_VALUES_SEQUENCE
として設定することで、タグのALLOWED_VALUES
リストで定義された順序に基づいて、競合する値のうち、リスト内でより早く出現する値が優先される
タグ自動伝播の監視
タグの自動伝播の監視方法にはイベントテーブルを使用できます。タグの自動伝播に関するテレメトリデータを収集するには、ログレベルの設定とアカウントレベルの ENABLE_TAG_PROPAGATION_EVENT_LOGGING パラメータを有効化します。
これにより、競合イベントの一元管理と、特定のイベントが発生時のアラート構成などが可能です。
また、ログレベルの設定に応じて収集される競合時のオプションが異なります。詳細は以下をご参照ください。
試してみる
ここでは、タグの自動伝播による競合を発生させ、各オプションでの挙動を確認します。あわせてイベントテーブルにログを収集し、こちらも確認してみます。
事前準備
事前に以下の手順で検証用のテーブル、タグ、イベントテーブルを作成しました。
USE ROLE SYSADMIN;
CREATE OR REPLACE DATABASE test_db;
CREATE SCHEMA test_db.tags;
CREATE SCHEMA test_db.events;
-- 自動伝播できるtagを作成
USE SCHEMA test_db.tags;
CREATE OR REPLACE TAG MY_CLASSIFICATION
ALLOWED_VALUES 'CONFIDENTIAL', 'PUBLIC', 'INTERNAL'
PROPAGATE = ON_DEPENDENCY_AND_DATA_MOVEMENT;
-- タグを付与してスキーマを作成
CREATE SCHEMA test_db.tagged_schema
WITH TAG (TEST_DB.TAGS.MY_CLASSIFICATION = 'INTERNAL');
>SELECT * FROM TABLE(
information_schema.tag_references('test_db.tagged_schema', 'schema')
);
+--------------+------------+-------------------+-----------+--------+-----------------+---------------+---------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+-----------+--------+-----------------+---------------+---------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | INTERNAL | SCHEMA | TEST_DB | NULL | TAGGED_SCHEMA | SCHEMA | NULL | NULL |
+--------------+------------+-------------------+-----------+--------+-----------------+---------------+---------------+--------+-------------+--------------+
-- テーブルを作成:手動で値を設定
USE SCHEMA test_db.tagged_schema;
CREATE OR REPLACE TABLE TABLE_A (
ID INT,
NAME VARCHAR(50)
)
WITH TAG (TEST_DB.TAGS.MY_CLASSIFICATION = 'CONFIDENTIAL');
--タグと値を確認
>SELECT * FROM TABLE(
information_schema.tag_references('TABLE_A', 'table')
);
+--------------+------------+-------------------+--------------+-------+-----------------+---------------+-------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+--------------+-------+-----------------+---------------+-------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | CONFIDENTIAL | TABLE | TEST_DB | TAGGED_SCHEMA | TABLE_A | TABLE | NULL | MANUAL |
+--------------+------------+-------------------+--------------+-------+-----------------+---------------+-------------+--------+-------------+--------------+
--イベントテーブルを作成
USE ROLE SYSADMIN;
USE SCHEMA test_db.events;
CREATE OR REPLACE EVENT TABLE tags_event;
--データベースにイベントテーブルを関連付け
ALTER DATABASE test_db SET EVENT_TABLE = test_db.events.tags_event;
SHOW PARAMETERS LIKE 'event_table' IN DATABASE test_db;
上記の手順ではテーブルの作成先となるスキーマにもタグと値(MY_CLASSIFICATION = 'INTERNAL'
)を割り当てています。さらにテーブル定義時には異なる値(CONFIDENTIAL
)を割り当てています。
この場合は、競合にならず元々のタグの性質にあわせて値が子オブジェクトでオーバライドされます。
イベントテーブルの設定やタグの性質については以下をご参照ください。
イベントテーブルの設定
イベントテーブルを作成しただけではログは収集されません。ログレベルの設定とタグの自動伝播に関する情報の場合は、アカウントのパラメータの有効化が必要です。
ここでは以下の通り、データベースに対してログレベルをINFO
として設定しました。
--データベースレベルのログレベル設定変更
----データベース所有者のSYSADMINを使用
USE ROLE SYSADMIN;
ALTER DATABASE test_db SET LOG_LEVEL = INFO;
--タグ伝播に関するテレメトリデータを収集するには、 ENABLE_TAG_PROPAGATION_EVENT_LOGGINGアカウントパラメータを有効にする
USE ROLE ACCOUNTADMIN;
ALTER ACCOUNT SET ENABLE_TAG_PROPAGATION_EVENT_LOGGING = TRUE;
タグの競合を起こす
ここでは同じタグの異なる値を割り当てたテーブルを別に作成し、先の手順で作成した別の値を割り当てたテーブルと結合することで新規テーブルを作成し、タグを自動伝播させます。双方のテーブルで異なるタグ値が設定されているので、値が競合します。
-- 別のテーブルを作成:タグ値は「PUBLIC」
USE SCHEMA test_db.tagged_schema;
CREATE OR REPLACE TABLE TABLE_B (
PRODUCT_ID INT,
PRODUCT_NAME VARCHAR(100)
)
WITH TAG (TEST_DB.TAGS.MY_CLASSIFICATION = 'PUBLIC');
;
--値を確認
>SELECT * FROM TABLE(
information_schema.tag_references('TABLE_B', 'table')
);
+--------------+------------+-------------------+-----------+-------+-----------------+---------------+-------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+-----------+-------+-----------------+---------------+-------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | PUBLIC | TABLE | TEST_DB | TAGGED_SCHEMA | TABLE_B | TABLE | NULL | MANUAL |
+--------------+------------+-------------------+-----------+-------+-----------------+---------------+-------------+--------+-------------+--------------+
--結合しテーブルを作成:タグの競合が起こる
USE SCHEMA test_db.tagged_schema;
CREATE OR REPLACE TABLE COMBINED_DATA_INNER AS
SELECT
A.ID AS USER_ID,
A.NAME AS USER_NAME,
B.PRODUCT_ID,
B.PRODUCT_NAME
FROM
TABLE_A AS A
INNER JOIN
TABLE_B AS B ON A.ID = B.PRODUCT_ID;
--タグの値を確認:「CONFLICT」
>SELECT * FROM TABLE(
information_schema.tag_references('COMBINED_DATA_INNER', 'table')
);
+--------------+------------+-------------------+-----------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+-----------+-------+-----------------+---------------+---------------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | CONFLICT | TABLE | TEST_DB | TAGGED_SCHEMA | COMBINED_DATA_INNER | TABLE | NULL | PROPAGATED |
+--------------+------------+-------------------+-----------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
最後のクエリで値を確認しています。値を見ると「CONFLICT」となっておりタグの競合が確認できました。また、タグのON_CONFLICT
パラメータは特に設定していないので、これはデフォルトオプションが適用されたことになります。
イベントテーブルを確認します。2つ目のクエリの [VALUE_RESOLUTION_TYPE] 列を確認すると、デフォルトオプションとわかります。
--イベントテーブルをクエリ
>SELECT * FROM test_db.events.tags_event;
+-------------------------+-----------------+-------------------------+-------+----------+------------------------------------------------------------+--------------------------------------------+------------------+-------------+----------------------------------------+---------------------------------------------------------------+------------------------------------------------+-----------+
| TIMESTAMP | START_TIMESTAMP | OBSERVED_TIMESTAMP | TRACE | RESOURCE | RESOURCE_ATTRIBUTES | SCOPE | SCOPE_ATTRIBUTES | RECORD_TYPE | RECORD | RECORD_ATTRIBUTES | VALUE | EXEMPLARS |
|-------------------------+-----------------+-------------------------+-------+----------+------------------------------------------------------------+--------------------------------------------+------------------+-------------+----------------------------------------+---------------------------------------------------------------+------------------------------------------------+-----------|
| 2025-07-22 00:15:32.646 | NULL | 2025-07-22 00:15:32.646 | NULL | NULL | { | { | NULL | EVENT | { | { | { | NULL |
| | | | | | "snow.database.id": 55, | "name": "snow.automatic_tag_propagation" | | | "name": "automatic_tag_propagation", | "entity_domain": "Table", | "additional_details": "", | |
| | | | | | "snow.database.name": "TEST_DB", | } | | | "severity_text": "WARN" | "entity_name": "TEST_DB.TAGGED_SCHEMA.COMBINED_DATA_INNER", | "conflict_values": "[PUBLIC, CONFIDENTIAL]", | |
| | | | | | "snow.query.id": "01bdd8ef-0002-a0a0-0002-79160019ec3a", | | | | } | "event_type": "CONFLICT", | "resolution_type": "default", | |
| | | | | | "snow.session.id": 303306, | | | | | "tag_name": "TEST_DB.TAGS.MY_CLASSIFICATION" | "resolved_value": "CONFLICT" | |
| | | | | | "snow.session.role.primary.id": 6, | | | | | } | } | |
| | | | | | "snow.session.role.primary.name": "SYSADMIN", | | | | | | | |
| | | | | | "snow.user.id": 1, | | | | | | | |
| | | | | | "snow.user.name": "TOMOKIYASUHARA" | | | | | | | |
| | | | | | } | | | | | | | |
+-------------------------+-----------------+-------------------------+-------+----------+------------------------------------------------------------+--------------------------------------------+------------------+-------------+----------------------------------------+---------------------------------------------------------------+------------------------------------------------+-----------+
--展開
>SELECT
-- RECORD カラムの展開
RECORD:name::VARCHAR AS record_name,
RECORD:severity_text::VARCHAR AS record_severity_text,
-- RECORD_ATTRIBUTES カラムの展開
RECORD_ATTRIBUTES:entity_domain::VARCHAR AS entity_domain,
RECORD_ATTRIBUTES:entity_name::VARCHAR AS entity_name,
RECORD_ATTRIBUTES:event_type::VARCHAR AS event_type,
RECORD_ATTRIBUTES:tag_name::VARCHAR AS tag_name,
-- VALUE カラムの展開
VALUE:conflict_values::ARRAY AS value_conflict_values,
VALUE:resolution_type::VARCHAR AS value_resolution_type,
VALUE:resolved_value::VARCHAR AS value_resolved_value
FROM
test_db.events.tags_event
;
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------+
| RECORD_NAME | RECORD_SEVERITY_TEXT | ENTITY_DOMAIN | ENTITY_NAME | EVENT_TYPE | TAG_NAME | VALUE_CONFLICT_VALUES | VALUE_RESOLUTION_TYPE | VALUE_RESOLVED_VALUE |
|---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------|
| automatic_tag_propagation | WARN | Table | TEST_DB.TAGGED_SCHEMA.COMBINED_DATA_INNER | CONFLICT | TEST_DB.TAGS.MY_CLASSIFICATION | [ | default | CONFLICT |
| | | | | | | "[PUBLIC, CONFIDENTIAL]" | | |
| | | | | | | ] | | |
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------+
タグの設定を変更:ユーザー定義の文字列で値を置き換え
続けてタグのON_CONFLICT
パラメータを追加します。この値が設定されていると、競合発生時にここで指定した値でタグ値が置き換えられます。
CREATE OR ALTER TAG TEST_DB.TAGS.MY_CLASSIFICATION
ALLOWED_VALUES 'CONFIDENTIAL', 'PUBLIC', 'INTERNAL','HIGHLY CONFIDENTIAL'
PROPAGATE = ON_DEPENDENCY_AND_DATA_MOVEMENT
ON_CONFLICT = 'HIGHLY CONFIDENTIAL';
再度テーブルを作成し、タグを自動伝播させる
USE SCHEMA test_db.tagged_schema;
CREATE OR REPLACE TABLE COMBINED_DATA_INNER AS
SELECT
A.ID AS USER_ID,
A.NAME AS USER_NAME,
B.PRODUCT_ID,
B.PRODUCT_NAME
FROM
TABLE_A AS A
INNER JOIN
TABLE_B AS B ON A.ID = B.PRODUCT_ID;
--タグの値を確認:「HIGHLY CONFIDENTIAL」
>SELECT * FROM TABLE(
information_schema.tag_references('COMBINED_DATA_INNER', 'table')
);
+--------------+------------+-------------------+---------------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+---------------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | HIGHLY CONFIDENTIAL | TABLE | TEST_DB | TAGGED_SCHEMA | COMBINED_DATA_INNER | TABLE | NULL | PROPAGATED |
+--------------+------------+-------------------+---------------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
値を確認すると先の「CONFLICT
」ではなくON_CONFLICT
パラメータで指定した「HIGHLY CONFIDENTIAL
」となっています。
イベントテーブルを確認します。2つ目のクエリの [VALUE_RESOLUTION_TYPE] 列を確認すると「string_override」となっており、異なるオプションが適用されたことがとわかります。
>SELECT
-- RECORD カラムの展開
RECORD:name::VARCHAR AS record_name,
RECORD:severity_text::VARCHAR AS record_severity_text,
-- RECORD_ATTRIBUTES カラムの展開
RECORD_ATTRIBUTES:entity_domain::VARCHAR AS entity_domain,
RECORD_ATTRIBUTES:entity_name::VARCHAR AS entity_name,
RECORD_ATTRIBUTES:event_type::VARCHAR AS event_type,
RECORD_ATTRIBUTES:tag_name::VARCHAR AS tag_name,
-- VALUE カラムの展開
VALUE:conflict_values::ARRAY AS value_conflict_values,
VALUE:resolution_type::VARCHAR AS value_resolution_type,
VALUE:resolved_value::VARCHAR AS value_resolved_value
FROM
test_db.events.tags_event
WHERE
value_resolution_type = 'string_override'
;
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------+
| RECORD_NAME | RECORD_SEVERITY_TEXT | ENTITY_DOMAIN | ENTITY_NAME | EVENT_TYPE | TAG_NAME | VALUE_CONFLICT_VALUES | VALUE_RESOLUTION_TYPE | VALUE_RESOLVED_VALUE |
|---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------|
| automatic_tag_propagation | INFO | Table | TEST_DB.TAGGED_SCHEMA.COMBINED_DATA_INNER | CONFLICT | TEST_DB.TAGS.MY_CLASSIFICATION | [ | string_override | HIGHLY CONFIDENTIAL |
| | | | | | | "[CONFIDENTIAL, PUBLIC]" | | |
| | | | | | | ] | | |
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-----------------------+----------------------+
タグの設定を変更:ALLOWED_VALUES パラメータで定義された値の順序を使用
最後のオプションを試します。
ON_CONFLICT
パラメータをALLOWED_VALUES_SEQUENCE
とすることで、タグの ALLOWED_VALUES
パラメータで定義された値の順序を使用することができます。
以下のようにタグを変更します。
CREATE OR ALTER TAG TEST_DB.TAGS.MY_CLASSIFICATION
ALLOWED_VALUES 'CONFIDENTIAL', 'PUBLIC', 'INTERNAL','HIGHLY CONFIDENTIAL'
PROPAGATE = ON_DEPENDENCY_AND_DATA_MOVEMENT
ON_CONFLICT = ALLOWED_VALUES_SEQUENCE;
ここではALLOWED_VALUES
の順序がCONFIDENTIAL
, PUBLIC
となっているので、これらの値が競合する場合、先に来るCONFIDENTIAL
が使用されます。
再度テーブルを作成します。
USE SCHEMA test_db.tagged_schema;
CREATE OR REPLACE TABLE COMBINED_DATA_INNER AS
SELECT
A.ID AS USER_ID,
A.NAME AS USER_NAME,
B.PRODUCT_ID,
B.PRODUCT_NAME
FROM
TABLE_A AS A
INNER JOIN
TABLE_B AS B ON A.ID = B.PRODUCT_ID;
--タグの値を確認:「CONFIDENTIAL」となっている
>SELECT * FROM TABLE(
information_schema.tag_references('COMBINED_DATA_INNER', 'table')
);
+--------------+------------+-------------------+--------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
| TAG_DATABASE | TAG_SCHEMA | TAG_NAME | TAG_VALUE | LEVEL | OBJECT_DATABASE | OBJECT_SCHEMA | OBJECT_NAME | DOMAIN | COLUMN_NAME | APPLY_METHOD |
|--------------+------------+-------------------+--------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------|
| TEST_DB | TAGS | MY_CLASSIFICATION | CONFIDENTIAL | TABLE | TEST_DB | TAGGED_SCHEMA | COMBINED_DATA_INNER | TABLE | NULL | PROPAGATED |
+--------------+------------+-------------------+--------------+-------+-----------------+---------------+---------------------+--------+-------------+--------------+
イベントテーブルを確認します。2つ目のクエリの [VALUE_RESOLUTION_TYPE] 列を確認すると、allowed_values_sequence
となっており、3つ目のオプションが適用されていることがわかります。
>SELECT
-- RECORD カラムの展開
RECORD:name::VARCHAR AS record_name,
RECORD:severity_text::VARCHAR AS record_severity_text,
-- RECORD_ATTRIBUTES カラムの展開
RECORD_ATTRIBUTES:entity_domain::VARCHAR AS entity_domain,
RECORD_ATTRIBUTES:entity_name::VARCHAR AS entity_name,
RECORD_ATTRIBUTES:event_type::VARCHAR AS event_type,
RECORD_ATTRIBUTES:tag_name::VARCHAR AS tag_name,
-- VALUE カラムの展開
VALUE:conflict_values::ARRAY AS value_conflict_values,
VALUE:resolution_type::VARCHAR AS value_resolution_type,
VALUE:resolved_value::VARCHAR AS value_resolved_value
FROM
test_db.events.tags_event
WHERE
value_resolution_type = 'allowed_values_sequence'
;
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-------------------------+----------------------+
| RECORD_NAME | RECORD_SEVERITY_TEXT | ENTITY_DOMAIN | ENTITY_NAME | EVENT_TYPE | TAG_NAME | VALUE_CONFLICT_VALUES | VALUE_RESOLUTION_TYPE | VALUE_RESOLVED_VALUE |
|---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-------------------------+----------------------|
| automatic_tag_propagation | INFO | Table | TEST_DB.TAGGED_SCHEMA.COMBINED_DATA_INNER | CONFLICT | TEST_DB.TAGS.MY_CLASSIFICATION | [ | allowed_values_sequence | CONFIDENTIAL |
| | | | | | | "[CONFIDENTIAL, PUBLIC]" | | |
| | | | | | | ] | | |
+---------------------------+----------------------+---------------+-------------------------------------------+------------+--------------------------------+----------------------------+-------------------------+----------------------+
さいごに
タグ自動伝播時の競合について整理してみました。
イベントテーブルに情報が収集されるようになったのは便利と思います。自動伝播が便利な機能ですが、意図しない競合が発生する可能性もがあるので、予め注意ができればと思いました。
こちらの内容が何かの参考になれば幸いです。