### 6.5.3 使用 MySQL 企业数据屏蔽和去标识化

在使用 MySQL Enterprise Data Masking and De-Identification 之前，请按照提供的说明进行安装[第 6.5.2 节，“安装或卸载 MySQL Enterprise Data Masking 和 De-Identification”](data-masking-installation.html).

要在应用程序中使用 MySQL Enterprise Data Masking 和 De-Identification，请调用适合您希望执行的操作的函数。详细功能说明见[第 6.5.5 节，“MySQL 企业数据屏蔽和去标识化功能描述”](data-masking-functions.html).本节演示如何使用这些函数来执行一些具有代表性的任务。它首先概述了可用的功能，然后是一些如何在实际环境中使用这些功能的示例：

-   [屏蔽数据以删除识别特征](data-masking-usage.html#data-masking-usage-masking-functions)

-   [生成具有特定特征的随机数据](data-masking-usage.html#data-masking-usage-generation-functions)

-   [使用字典生成随机数据](data-masking-usage.html#data-masking-usage-dictionary-functions)

-   [使用屏蔽数据进行客户识别](data-masking-usage.html#data-masking-usage-customer-identification)

-   [创建显示屏蔽数据的视图](data-masking-usage.html#data-masking-usage-views)

#### 屏蔽数据以删除识别特征

MySQL 提供了屏蔽任意字符串的通用屏蔽函数和屏蔽特定类型值的专用屏蔽函数。

##### 通用屏蔽函数

[`mask_inner()`](data-masking-functions.html#function_mask-inner)和[`mask_outer()`](data-masking-functions.html#function_mask-outer)是根据字符串中的位置屏蔽任意字符串部分的通用函数：

-   [`mask_inner()`](data-masking-functions.html#function_mask-inner)掩盖其字符串参数的内部，使末端不被掩盖。其他参数指定未屏蔽末端的大小。

    ```
    mysql> SELECT mask_inner('This is a string', 5, 1);
    +--------------------------------------+
    | mask_inner('This is a string', 5, 1) |
    +--------------------------------------+
    | This XXXXXXXXXXg                     |
    +--------------------------------------+
    mysql> SELECT mask_inner('This is a string', 1, 5);
    +--------------------------------------+
    | mask_inner('This is a string', 1, 5) |
    +--------------------------------------+
    | TXXXXXXXXXXtring                     |
    +--------------------------------------+
    ```

-   [`mask_outer()`](data-masking-functions.html#function_mask-outer)做相反的事情，掩盖其字符串参数的末端，使内部不被掩盖。其他参数指定掩蔽端的大小。

    ```
    mysql> SELECT mask_outer('This is a string', 5, 1);
    +--------------------------------------+
    | mask_outer('This is a string', 5, 1) |
    +--------------------------------------+
    | XXXXXis a strinX                     |
    +--------------------------------------+
    mysql> SELECT mask_outer('This is a string', 1, 5);
    +--------------------------------------+
    | mask_outer('This is a string', 1, 5) |
    +--------------------------------------+
    | Xhis is a sXXXXX                     |
    +--------------------------------------+
    ```

    默认，[`mask_inner()`](data-masking-functions.html#function_mask-inner)和[`mask_outer()`](data-masking-functions.html#function_mask-outer)采用`'X'`作为掩码字符，但允许可选的掩码字符参数：


```
mysql> SELECT mask_inner('This is a string', 5, 1, '*');
+-------------------------------------------+
| mask_inner('This is a string', 5, 1, '*') |
+-------------------------------------------+
| This **********g                          |
+-------------------------------------------+
mysql> SELECT mask_outer('This is a string', 5, 1, '#');
+-------------------------------------------+
| mask_outer('This is a string', 5, 1, '#') |
+-------------------------------------------+
| #####is a strin#                          |
+-------------------------------------------+
```

##### 专用屏蔽功能

其他屏蔽函数需要一个表示特定类型值的字符串参数并将其屏蔽以删除识别特征。

笔记

此处的示例使用返回适当类型值的随机值生成函数提供函数参数。有关生成函数的更多信息，请参阅[生成具有特定特征的随机数据](data-masking-usage.html#data-masking-usage-generation-functions).

**支付卡主帐号掩码。**屏蔽功能提供对主帐号的严格和宽松的屏蔽。

-   [`掩码盘（）`](data-masking-functions.html#function_mask-pan)屏蔽除数字的最后四位以外的所有数字：

    ```
    mysql> SELECT mask_pan(gen_rnd_pan());
    +-------------------------+
    | mask_pan(gen_rnd_pan()) |
    +-------------------------+
    | XXXXXXXXXXXX2461        |
    +-------------------------+
    ```

-   [`mask_pan_relaxed()`](data-masking-functions.html#function_mask-pan-relaxed)类似，但不掩盖表明支付卡发卡机构未掩盖的前六位数字：

    ```
    mysql> SELECT mask_pan_relaxed(gen_rnd_pan());
    +---------------------------------+
    | mask_pan_relaxed(gen_rnd_pan()) |
    +---------------------------------+
    | 770630XXXXXX0807                |
    +---------------------------------+
    ```

**美国社会安全号码掩蔽。**  [`mask_ssn()`](data-masking-functions.html#function_mask-ssn)屏蔽除数字的最后四位以外的所有数字：

```
mysql> SELECT mask_ssn(gen_rnd_ssn());
+-------------------------+
| mask_ssn(gen_rnd_ssn()) |
+-------------------------+
| XXX-XX-1723             |
+-------------------------+
```

#### 生成具有特定特征的随机数据

几个函数生成随机值。这些值可用于测试、模拟等。

[`gen_range()`](data-masking-functions.html#function_gen-range)返回从给定范围中选择的随机整数：

```
mysql> SELECT gen_range(1, 10);
+------------------+
| gen_range(1, 10) |
+------------------+
|                6 |
+------------------+
```

[`gen_rnd_email()`](data-masking-functions.html#function_gen-rnd-email)返回一个随机的电子邮件地址`例子.com`领域：

```
mysql> SELECT gen_rnd_email();
+---------------------------+
| gen_rnd_email()           |
+---------------------------+
| ayxnq.xmkpvvy@example.com |
+---------------------------+
```

[`gen_rnd_pan()`](data-masking-functions.html#function_gen-rnd-pan)返回一个随机支付卡主帐号：

```
mysql> SELECT gen_rnd_pan();
```

（这[`gen_rnd_pan()`](data-masking-functions.html#function_gen-rnd-pan)未显示函数结果，因为它的返回值应仅用于测试目的，而不是用于发布。不能保证该号码未分配给合法的支付账户。）

[`gen_rnd_ssn()`](data-masking-functions.html#function_gen-rnd-ssn)返回一个随机的美国社会安全号码，第一部分和第二部分均选自一个不用于合法号码的范围：

```
mysql> SELECT gen_rnd_ssn();
+---------------+
| gen_rnd_ssn() |
+---------------+
| 912-45-1615   |
+---------------+
```

[`gen_rnd_us_phone()`](data-masking-functions.html#function_gen-rnd-us-phone)返回一个 555 区号的随机美国电话号码，不用于合法号码：

```
mysql> SELECT gen_rnd_us_phone();
+--------------------+
| gen_rnd_us_phone() |
+--------------------+
| 1-555-747-5627     |
+--------------------+
```

#### 使用字典生成随机数据

MySQL Enterprise Data Masking and De-Identification 使字典可以用作随机值的来源。要使用字典，必须首先从文件中加载它并为其命名。每个加载的字典都成为字典注册表的一部分。然后可以从注册的字典中选择项目并用作随机值或替换其他值。

有效的字典文件具有以下特征：

-   文件内容是纯文本，每行一个词。

-   空行被忽略。

-   该文件必须至少包含一个术语。

    假设一个名为`de_cities.txt`包含德国的这些城市名称：


```
Berlin
Munich
Bremen
```

还假设一个名为`us_cities.txt`包含美国的这些城市名称：

```
Chicago
Houston
Phoenix
El Paso
Detroit
```

假设[`secure_file_priv`](server-system-variables.html#sysvar_secure_file_priv)系统变量设置为`/usr/local/mysql/mysql-文件`.在这种情况下，将字典文件复制到该目录，以便 MySQL 服务器可以访问它们。然后使用[`gen_dictionary_load()`](data-masking-functions.html#function_gen-dictionary-load)将字典加载到字典注册表中并为其分配名称：

```
mysql> SELECT gen_dictionary_load('/usr/local/mysql/mysql-files/de_cities.txt', 'DE_Cities');
+--------------------------------------------------------------------------------+
| gen_dictionary_load('/usr/local/mysql/mysql-files/de_cities.txt', 'DE_Cities') |
+--------------------------------------------------------------------------------+
| Dictionary load success                                                        |
+--------------------------------------------------------------------------------+
mysql> SELECT gen_dictionary_load('/usr/local/mysql/mysql-files/us_cities.txt', 'US_Cities');
+--------------------------------------------------------------------------------+
| gen_dictionary_load('/usr/local/mysql/mysql-files/us_cities.txt', 'US_Cities') |
+--------------------------------------------------------------------------------+
| Dictionary load success                                                        |
+--------------------------------------------------------------------------------+
```

要从字典中选择一个随机术语，请使用[`gen_dictionary()`](data-masking-functions.html#function_gen-dictionary)：

```
mysql> SELECT gen_dictionary('DE_Cities');
+-----------------------------+
| gen_dictionary('DE_Cities') |
+-----------------------------+
| Berlin                      |
+-----------------------------+
mysql> SELECT gen_dictionary('US_Cities');
+-----------------------------+
| gen_dictionary('US_Cities') |
+-----------------------------+
| Phoenix                     |
+-----------------------------+
```

要从多个词典中选择一个随机词，请随机选择其中一个词典，然后从中选择一个词：

```
mysql> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+---------------------------------------------------------------+
| gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities')) |
+---------------------------------------------------------------+
| Detroit                                                       |
+---------------------------------------------------------------+
mysql> SELECT gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities'));
+---------------------------------------------------------------+
| gen_dictionary(ELT(gen_range(1,2), 'DE_Cities', 'US_Cities')) |
+---------------------------------------------------------------+
| Bremen                                                        |
+---------------------------------------------------------------+
```

这[`gen_blocklist()`](data-masking-functions.html#function_gen-blocklist)函数可以将一个字典中的术语替换为另一个字典中的术语，这会通过替换实现掩蔽。它的参数是要替换的术语、出现该术语的字典以及从中选择替换的字典。例如，要将美国城市替换为德国城市，反之亦然，请使用[`gen_blocklist()`](data-masking-functions.html#function_gen-blocklist)像这样：

```
mysql> SELECT gen_blocklist('Munich', 'DE_Cities', 'US_Cities');
+---------------------------------------------------+
| gen_blocklist('Munich', 'DE_Cities', 'US_Cities') |
+---------------------------------------------------+
| Houston                                           |
+---------------------------------------------------+
mysql> SELECT gen_blocklist('El Paso', 'US_Cities', 'DE_Cities');
+----------------------------------------------------+
| gen_blocklist('El Paso', 'US_Cities', 'DE_Cities') |
+----------------------------------------------------+
| Bremen                                             |
+----------------------------------------------------+
```

如果要替换的词不在第一本词典中，[`gen_blocklist()`](data-masking-functions.html#function_gen-blocklist)原样返回：

```
mysql> SELECT gen_blocklist('Moscow', 'DE_Cities', 'US_Cities');
+---------------------------------------------------+
| gen_blocklist('Moscow', 'DE_Cities', 'US_Cities') |
+---------------------------------------------------+
| Moscow                                            |
+---------------------------------------------------+
```

#### 使用屏蔽数据进行客户识别

在客户服务呼叫中心，一种常见的身份验证技术是要求客户提供他们的最后四个社会安全号码 (SSN) 数字。例如，客户可能会说她的名字是 Joanna Bond，而她的 SSN 后四位数字是`0007`.

假设一个`顾客`包含客户记录的表具有以下列：

-   `id`: 客户 ID 号。

-   `名`: 客户的名字。

-   `姓`: 客户姓氏。

-   `ssn`：客户社会安全号码。

    例如，该表可能定义如下：


```
CREATE TABLE customer
(
  id         BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  first_name VARCHAR(40),
  last_name  VARCHAR(40),
  ssn        VARCHAR(11)
);
```

客户服务代表用于检查客户SSN的应用程序可能会执行以下查询：

```
mysql> SELECT id, ssn
mysql> FROM customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id  | ssn         |
+-----+-------------+
| 786 | 906-39-0007 |
+-----+-------------+
```

但是，这会将SSN暴露给客户服务代表，客户服务代表只需要看到最后四位数字。相反，应用程序可以使用此查询仅显示屏蔽的SSN：

```
mysql> SELECT id, mask_ssn(CONVERT(ssn USING binary)) AS masked_ssn
mysql> FROM customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id  | masked_ssn  |
+-----+-------------+
| 786 | XXX-XX-0007 |
+-----+-------------+
```

现在，代表只看到必要的东西，客户隐私得到了保护。

为什么[`CONVERT（）`](cast-functions.html#function_convert)用于参数的函数[`面具_ssn（）`](data-masking-functions.html#function_mask-ssn)? 因为[`面具_ssn（）`](data-masking-functions.html#function_mask-ssn)需要长度为11的参数。因此，即使`ssn`定义为`瓦查尔（11）`，如果`ssn`列有一个多字节字符集，当传递给可加载函数时，它的长度可能超过11字节，并且会发生错误。将值转换为二进制字符串可确保函数看到长度为11的参数。

当字符串参数没有单字节字符集时，其他数据屏蔽函数可能需要类似的技术。

#### 创建显示屏蔽数据的视图

如果表中的屏蔽数据用于多个查询，则可以方便地定义生成屏蔽数据的视图。这样，应用程序就可以从视图中进行选择，而无需在单个查询中执行屏蔽。

例如，屏幕上的遮罩视图`顾客`上一节中的表可以这样定义：

```
CREATE VIEW masked_customer AS
SELECT id, first_name, last_name,
mask_ssn(CONVERT(ssn USING binary)) AS masked_ssn
FROM customer;
```

然后，查找客户的查询变得更简单，但仍会返回隐藏的数据：

```
mysql> SELECT id, masked_ssn
mysql> FROM masked_customer
mysql> WHERE first_name = 'Joanna' AND last_name = 'Bond';
+-----+-------------+
| id  | masked_ssn  |
+-----+-------------+
| 786 | XXX-XX-0007 |
+-----+-------------+
```
