
TDengine 脱敏函数用户手册
目录
- 概述
- 脱敏函数详解
- [MASK_FULL - 全脱敏](#MASK_FULL - 全脱敏)
- [MASK_PARTIAL - 部分脱敏](#MASK_PARTIAL - 部分脱敏)
- [MASK_NONE - 空脱敏](#MASK_NONE - 空脱敏)
- 使用场景
- 最佳实践
- 注意事项
概述
TDengine 提供了一组数据脱敏函数,用于保护敏感数据的安全。数据脱敏是一种重要的数据安全技术,可以在不影响数据可用性的前提下,对敏感信息进行变形处理,防止数据泄露。
脱敏函数的作用
- 数据保护:在数据查询、展示或共享时,隐藏敏感信息
- 合规要求:满足数据安全和隐私保护的法规要求
- 灵活控制:支持全脱敏和部分脱敏,满足不同场景需求
支持的函数
| 函数名称 | 功能描述 |
|---|---|
| MASK_FULL | 完全替换原始数据 |
| MASK_PARTIAL | 部分字符脱敏,保留首尾字符 |
| MASK_NONE | 不进行脱敏(测试用) |
脱敏函数详解
MASK_FULL - 全脱敏
语法
sql
MASK_FULL(str, replace_value)
参数说明
str:需要脱敏的字符串(VARCHAR 类型)replace_value:用于替换的字符串
返回值
- 类型:VARCHAR
- 说明:返回替换后的字符串
功能描述
将目标数据进行全脱敏处理,即完全用指定的替换值代替原始数据。
适用数据类型
- 输入:VARCHAR、NCHAR
- 输出:VARCHAR、NCHAR(与输入类型一致)
使用示例
示例 1:基本用法
sql
taos> SELECT MASK_FULL('mytext', 'CONFIDENTIAL');
mask_full('mytext', 'CONFIDENTIAL') |
======================================
CONFIDENTIAL |
Query OK, 1 row(s) in set (0.002790s)
示例 2:脱敏姓名
sql
-- 创建示例表
CREATE TABLE customers (
ts TIMESTAMP,
name VARCHAR(50),
phone VARCHAR(20)
);
-- 插入数据
INSERT INTO customers VALUES
(NOW, '张三', '13812345678'),
(NOW + 1s, '李四', '13987654321');
-- 查询时脱敏姓名
SELECT ts, MASK_FULL(name, '***') AS masked_name, phone
FROM customers;
-- 输出结果:
ts | masked_name | phone |
================================================================
2026-01-28 10:00:00.000 | *** | 13812345678 |
2026-01-28 10:00:01.000 | *** | 13987654321 |
示例 3:脱敏邮箱地址
sql
SELECT MASK_FULL('user@example.com', 'HIDDEN');
-- 结果:HIDDEN
示例 4:处理 NULL 值
sql
SELECT MASK_FULL(NULL, 'CONFIDENTIAL');
-- 结果:NULL(NULL 值不受影响)
应用场景
- 完全隐藏姓名、邮箱等个人信息
- 脱敏用户密码、密钥等高度敏感数据
- 对外展示或报表中需要完全隐藏的数据
MASK_PARTIAL - 部分脱敏
语法
sql
MASK_PARTIAL(str, prefix_length, suffix_length, mask_char)
参数说明
str:需要脱敏的字符串(VARCHAR 类型)prefix_length:从字符串开头保留的字符数suffix_length:从字符串末尾保留的字符数mask_char:用于遮蔽的字符
返回值
- 类型:VARCHAR
- 说明:返回部分脱敏后的字符串
功能描述
将目标数据进行部分脱敏处理,保留字符串的前缀和后缀部分,中间部分用指定字符替换。
适用数据类型
- 输入:VARCHAR、NCHAR
- 输出:VARCHAR、NCHAR(与输入类型一致)
使用示例
示例 1:基本用法
sql
taos> SELECT MASK_PARTIAL('mytext', 1, 2, '*');
mask_partial('mytext', 1, 2, '*') |
====================================
*yte** |
Query OK, 1 row(s) in set (0.002787s)
示例 2:脱敏手机号
sql
-- 保留前 3 位和后 4 位,中间用 * 替换
SELECT MASK_PARTIAL('13812345678', 3, 4, '*') AS masked_phone;
-- 结果:
masked_phone |
==================
138****5678 |
示例 3:脱敏身份证号
sql
-- 保留前 6 位和后 4 位
SELECT MASK_PARTIAL('110101199001011234', 6, 4, '*') AS masked_id;
-- 结果:
masked_id |
=======================
110101********1234 |
示例 4:脱敏银行卡号
sql
-- 保留前 4 位和后 4 位
SELECT MASK_PARTIAL('6222021234567890123', 4, 4, '*') AS masked_card;
-- 结果:
masked_card |
===========================
6222***********0123 |
示例 5:在表查询中使用
sql
CREATE TABLE user_info (
ts TIMESTAMP,
user_id INT,
phone VARCHAR(20),
id_card VARCHAR(18)
);
INSERT INTO user_info VALUES
(NOW, 1, '13812345678', '110101199001011234'),
(NOW + 1s, 2, '13987654321', '120102199502021234');
-- 查询时同时脱敏手机号和身份证号
SELECT
ts,
user_id,
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
MASK_PARTIAL(id_card, 6, 4, '*') AS id_card
FROM user_info;
-- 输出结果:
ts | user_id | phone | id_card |
=========================================================================
2026-01-28 10:00:00.000 | 1 | 138****5678 | 110101********1234 |
2026-01-28 10:00:01.000 | 2 | 139****4321 | 120102********1234 |
示例 6:处理短字符串
sql
-- 字符串长度不足时的处理
SELECT MASK_PARTIAL('ab', 1, 1, '*');
-- 结果:**
SELECT MASK_PARTIAL('a', 1, 2, '*');
-- 结果:*
示例 7:处理 NULL 值
sql
SELECT MASK_PARTIAL(NULL, 1, 2, '*');
-- 结果:NULL
应用场景
- 脱敏手机号码,保留地区码和后四位
- 脱敏身份证号,保留地区和校验位
- 脱敏银行卡号,保留卡种标识和部分尾号
- 脱敏邮箱地址,保留用户名首字母和域名
MASK_NONE - 空脱敏
语法
sql
MASK_NONE(str)
参数说明
str:字符串(VARCHAR 类型)
返回值
- 类型:VARCHAR
- 说明:返回原始字符串,不进行任何脱敏处理
功能描述
将目标数据进行空脱敏处理,即不对数据进行任何修改,原样返回。此函数主要用于测试和开发场景。
适用数据类型
- 输入:VARCHAR、NCHAR
- 输出:VARCHAR、NCHAR(与输入类型一致)
使用示例
示例 1:基本用法
sql
taos> SELECT MASK_NONE('mytext');
mask_none('mytext') |
======================
mytext |
Query OK, 1 row(s) in set (0.001474s)
示例 2:测试场景
sql
-- 在开发环境中使用,便于调试
SELECT
MASK_NONE(name) AS name,
MASK_NONE(phone) AS phone
FROM customers;
-- 结果保持原样,方便验证数据
示例 3:处理 NULL 值
sql
SELECT MASK_NONE(NULL);
-- 结果:NULL
示例 4:空字符串处理
sql
SELECT MASK_NONE('');
-- 结果:''(空字符串)
应用场景
- 开发和测试环境,需要查看原始数据
- 作为脱敏函数的占位符,便于环境切换
- 性能测试时避免脱敏开销
使用场景
1. 数据查询脱敏
在 SELECT 语句中对敏感字段进行脱敏展示:
sql
SELECT
user_id,
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
MASK_FULL(email, 'HIDDEN@EMAIL.COM') AS email,
MASK_PARTIAL(id_card, 6, 4, '*') AS id_card
FROM user_table
WHERE ts >= NOW - 1d;
2. 数据导出脱敏
导出数据前进行脱敏处理:
sql
-- 导出脱敏后的数据
SELECT
ts,
device_id,
MASK_PARTIAL(imei, 4, 4, '*') AS imei,
MASK_FULL(user_name, '***') AS user_name,
temperature,
humidity
FROM sensor_data
WHERE ts BETWEEN '2026-01-01' AND '2026-01-31'
INTO OUTFILE '/tmp/sensor_data_masked.csv';
3. 报表和可视化
在报表或数据可视化应用中展示脱敏数据:
sql
-- 生成日报数据
CREATE VIEW daily_report AS
SELECT
DATE_TRUNC('day', ts) AS report_date,
COUNT(*) AS total_users,
MASK_PARTIAL(phone, 3, 4, '*') AS sample_phone
FROM user_activity
GROUP BY DATE_TRUNC('day', ts);
4. 权限控制结合
配合 TDengine 的权限系统,对不同用户展示不同程度的脱敏:
sql
-- 普通用户查询(完全脱敏)
GRANT SELECT ON database.table TO normal_user;
-- 管理员用户可以看到部分脱敏数据
GRANT SELECT ON database.sensitive_table TO admin_user;
5. 数据共享
向第三方或合作伙伴共享数据时进行脱敏:
sql
-- 创建脱敏视图供外部访问
CREATE VIEW shared_customer_data AS
SELECT
customer_id,
MASK_FULL(name, '***') AS name,
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
city,
order_count,
total_amount
FROM customer_info;
最佳实践
1. 选择合适的脱敏方式
- 高敏感数据 :使用
MASK_FULL完全隐藏(如密码、密钥) - 中等敏感数据 :使用
MASK_PARTIAL保留部分信息(如手机号、身份证) - 低敏感数据:根据需要选择是否脱敏
2. 脱敏参数设置建议
| 数据类型 | 推荐脱敏方式 | 参数示例 |
|---|---|---|
| 手机号 | MASK_PARTIAL | (phone, 3, 4, '*') |
| 身份证 | MASK_PARTIAL | (id_card, 6, 4, '*') |
| 银行卡号 | MASK_PARTIAL | (card_no, 4, 4, '*') |
| 邮箱 | MASK_PARTIAL | (email, 3, 0, '*') 或 MASK_FULL |
| 姓名 | MASK_FULL | (name, '***') |
| 地址 | MASK_PARTIAL | (address, 6, 0, '*') |
3. 性能优化建议
sql
-- 避免在大规模查询中对所有行进行脱敏
-- 优化前:
SELECT MASK_PARTIAL(phone, 3, 4, '*') FROM huge_table;
-- 优化后:先过滤再脱敏
SELECT MASK_PARTIAL(phone, 3, 4, '*')
FROM huge_table
WHERE ts >= NOW - 1h -- 先缩小数据范围
LIMIT 100;
4. 环境区分
sql
-- 使用变量控制不同环境的脱敏策略
-- 生产环境
SELECT
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
MASK_FULL(name, '***') AS name
FROM users;
-- 开发环境
SELECT
MASK_NONE(phone) AS phone,
MASK_NONE(name) AS name
FROM users;
5. 脱敏日志记录
建议记录脱敏操作日志,满足审计要求:
sql
-- 创建脱敏访问日志表
CREATE TABLE mask_access_log (
ts TIMESTAMP,
user_name VARCHAR(50),
table_name VARCHAR(50),
column_name VARCHAR(50),
operation VARCHAR(20)
);
-- 在应用层记录脱敏访问
-- INSERT INTO mask_access_log VALUES (NOW, 'admin', 'user_info', 'phone', 'MASK_PARTIAL');
6. 与应用程序集成
python
# Python 示例
import taos
conn = taos.connect(host="localhost", user="root", password="taosdata", database="db")
cursor = conn.cursor()
# 查询脱敏数据
sql = """
SELECT
user_id,
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
MASK_FULL(email, 'HIDDEN') AS email
FROM user_info
LIMIT 10
"""
cursor.execute(sql)
results = cursor.fetchall()
for row in results:
print(f"User ID: {row[0]}, Phone: {row[1]}, Email: {row[2]}")
cursor.close()
conn.close()
注意事项
1. 数据类型支持
- 支持类型:VARCHAR、NCHAR
- 不支持类型:数值类型、TIMESTAMP、BOOL 等
- 输出类型与输入类型保持一致
2. NULL 值处理
sql
-- NULL 值不进行脱敏,直接返回 NULL
SELECT MASK_FULL(NULL, 'HIDDEN'); -- 返回 NULL
SELECT MASK_PARTIAL(NULL, 1, 2, '*'); -- 返回 NULL
SELECT MASK_NONE(NULL); -- 返回 NULL
3. 空字符串处理
sql
-- 空字符串的脱敏结果
SELECT MASK_FULL('', '***'); -- 返回 '***'
SELECT MASK_PARTIAL('', 1, 2, '*'); -- 返回 '*'
SELECT MASK_NONE(''); -- 返回 ''
4. 字符长度不足的情况
sql
-- 当字符串长度小于 prefix_length + suffix_length 时
SELECT MASK_PARTIAL('ab', 2, 2, '*'); -- 返回 '**'
SELECT MASK_PARTIAL('a', 1, 1, '*'); -- 返回 '*'
5. 字符编码
- 函数支持 UTF-8 编码的多字节字符
- 对中文、日文等字符按字符而非字节计算长度
sql
SELECT MASK_PARTIAL('张三李四', 1, 1, '*');
-- 结果:张**四(保留首尾各 1 个中文字符)
6. 嵌套子查询支持
脱敏函数适用于内层查询和外层查询:
sql
-- 内层查询脱敏
SELECT * FROM (
SELECT MASK_PARTIAL(phone, 3, 4, '*') AS phone
FROM users
) sub;
-- 外层查询脱敏
SELECT
MASK_PARTIAL(phone, 3, 4, '*') AS phone
FROM (
SELECT phone FROM users WHERE city = 'Beijing'
) sub;
7. 与其他函数组合
sql
-- 与字符串函数组合
SELECT
CONCAT('Phone: ', MASK_PARTIAL(phone, 3, 4, '*')) AS masked_info
FROM users;
-- 与条件函数组合
SELECT
CASE
WHEN user_level = 'VIP' THEN phone
ELSE MASK_PARTIAL(phone, 3, 4, '*')
END AS phone
FROM users;
8. 安全性考虑
- 不可逆:脱敏后的数据无法还原为原始数据
- 客户端处理:脱敏在查询结果返回时处理,原始数据仍存储在服务器
- 权限控制:建议结合 TDengine 的权限系统,限制对敏感字段的直接访问
- 审计日志:记录脱敏操作,满足合规要求
9. 性能影响
- 脱敏函数在查询时实时计算,对性能有一定影响
- 大规模数据查询时建议:
- 先进行数据过滤再脱敏
- 使用 LIMIT 限制返回行数
- 考虑在应用层缓存脱敏结果
10. 版本支持
- 脱敏函数在 TDengine 社区版和企业版 中均支持
- 注意:加密函数(如 SM4_ENCRYPT、SM4_DECRYPT)仅在企业版中提供
常见问题 FAQ
Q1: 脱敏函数是否支持超级表?
A: 是的,脱敏函数既支持普通表也支持超级表。
sql
-- 在超级表查询中使用
SELECT
tbname,
MASK_PARTIAL(device_id, 4, 4, '*') AS device_id
FROM stable_name
WHERE ts >= NOW - 1h;
Q2: 如何对多个字段批量脱敏?
A: 在 SELECT 语句中对多个字段分别应用脱敏函数:
sql
SELECT
MASK_FULL(name, '***') AS name,
MASK_PARTIAL(phone, 3, 4, '*') AS phone,
MASK_PARTIAL(id_card, 6, 4, '*') AS id_card,
MASK_PARTIAL(email, 3, 0, '*') AS email
FROM user_info;
Q3: 脱敏后的数据能否用于统计分析?
A: 脱敏会改变原始数据,因此:
- 不适合:依赖精确值的统计(如 SUM、AVG)
- 适合:计数、去重等不依赖具体值的统计
sql
-- 适合的场景
SELECT
COUNT(*) AS total_users,
COUNT(DISTINCT MASK_PARTIAL(phone, 3, 4, '*')) AS unique_phones
FROM users;
Q4: 如何在 INSERT 语句中使用脱敏函数?
A: TDengine 的脱敏函数主要用于查询场景,不建议在 INSERT 时使用,因为会永久改变存储的数据。如果需要存储脱敏数据,应在应用层处理。
Q5: 脱敏函数是否影响索引?
A: 脱敏函数在查询时执行,不影响表的索引结构和查询优化器的选择。
总结
TDengine 提供的脱敏函数是保护数据安全的重要工具:
- MASK_FULL:完全隐藏敏感信息
- MASK_PARTIAL:保留部分信息,平衡安全与可用性
- MASK_NONE:用于测试和开发
在实际应用中,应根据数据敏感级别、业务需求和法规要求,合理选择脱敏策略,确保在满足安全合规的同时,保持数据的可用性。
关于 TDengine
TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。