

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 连接到 MySQL 数据来源
<a name="using-mysql-in-AMG"></a>

 添加 MySQL 数据来源，以便从 MySQL 兼容的数据库中查询数据并将其可视化。

**重要**  
Grafana 版本 8.0 更改了 MySQL、Postgres 和 Microsoft SQL Server 数据来源数据帧的底层数据结构。因此，时间序列查询结果将以宽格式返回。有关更多信息，请参阅 Grafana 数据帧文档中的[宽格式](https://grafana.com/developers/plugin-tools/introduction/data-frames#wide-format)。  
要使可视化效果和以前一样，您可能需要进行一些手动迁移。Github 上记录了一个解决方案，网址为 [Postgres/MySQL/MSSQL：v8.0 中与时间序列查询和数据列排序相关的重大更改](https://github.com/grafana/grafana/issues/35534)。

## 添加数据来源
<a name="mysql-adding-the-data-source"></a>

1.  选择顶部标题中的 Grafana 图标，打开侧边菜单。

1.  在侧边菜单的**控制面板**链接下，您应该可以找到名为**数据来源**的链接。

1.  选择顶部标题中的 **\$1 添加数据来源**按钮。

1.  从**类型**下拉列表中选择 **MySQL**。

### 数据来源选项
<a name="mysql-data-source-options"></a>


|  Name  |  说明  | 
| --- | --- | 
|  Name  |  数据来源名称。您将在面板和查询中通过其名称查看数据来源。 | 
|  Default  |  默认数据来源意味着将为新面板预先选择该数据来源。 | 
|  Host  |  您的 MySQL 实例的 IP address/hostname 和可选端口。 | 
|  Database  |  MySQL 数据库的名称。 | 
|  User  |  数据库用户的登录名/用户名。 | 
|  Password  |  数据库用户密码。 | 
|  Max open  |  数据库的最大打开连接数，默认为 unlimited（Grafana v5.4\$1）。 | 
|  Max idle  |  空闲连接池中的最大连接数，默认为 2（Grafana v5.4\$1）。 | 
|  Max lifetime  |  连接可重复使用的最长时间（秒），默认为 14400/4 小时。此值应始终低于 MySQL（Grafana v5.4\$1）中配置的 [wait\$1timeout](https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_wait_timeout)。 | 

### 最小时间间隔
<a name="mysql-min-time-interval"></a>

 `$_interval` `$_interval_ms` 变量的下限。建议设置以写入频率，例如，如果您的数据每分钟写入一次，则为 `1m`。此选项也可以在 overridden/configured 仪表板面板的数据源选项下方。此值的格式**必须**为数字，后跟有效的时间标识符；例如，`1m`（1 分钟）或 `30s`（30 秒）。支持以下时间标识符。


|  标识符  |  说明  | 
| --- | --- | 
|  y  |  Year  | 
|  M  |  Month  | 
|  w  |  周  | 
|  d  |  天  | 
|  h  |  小时  | 
|  m  |  分钟  | 
|  s  |  秒  | 
|  ms  |  毫秒  | 

### 数据库用户权限
<a name="database-user-permissions-important"></a>

**重要**  
 添加数据来源时指定的数据库用户只能获得对要查询的指定数据库和表的 SELECT 权限。Grafana 不会验证查询是否安全。查询可以包含任何 SQL 语句。例如，可以运行 `USE otherdb;` 和 `DROP TABLE user;` 之类的语句。为了防止这种情况，强烈建议您创建具有受限权限的特定 MySQL 用户。

 以下代码示例显示了如何创建具有受限权限的特定 MySQL 用户。

```
 CREATE USER 'grafanaReader' IDENTIFIED BY 'password';
 GRANT SELECT ON mydatabase.mytable TO 'grafanaReader';
```

 要授予对更多数据库和表的访问权限，可以根据需要使用通配符（`*`）代替数据库或表。

## 查询编辑器
<a name="mysql-query-editor"></a>

 在面板的编辑模式下，您可以在“指标”选项卡中找到 MySQL 查询编辑器。要进入编辑模式，请选择面板标题，然后选择**编辑**。

 在面板编辑模式下，查询编辑器有一个**生成式 SQL** 链接，并在查询运行后显示。选择之后，将会展开并显示运行的原始插值 SQL 字符串。

### 选择表、时间列和指标列（FROM）
<a name="select-table-time-column-and-metric-column-from"></a>

 当您首次进入编辑模式或添加新查询时，Grafana 将尝试在查询生成器中预填充第一个包含时间戳列和数字列的表。

 在 FROM 字段中，Grafana 建议使用配置数据库中的表。要在数据库用户有权访问的其他数据库中选择表或视图，您可以手动输入完全限定名称（database.table），例如 `otherDb.metrics`。

 “时间”列字段引用保存时间值的列的名称。为指标列字段选择值是可选项。如果选择一个值，则“指标”列字段将用作序列名称。

 指标列建议仅包含文本数据类型（text、tinytext、mediumtext、longtext、varchar、char）的列。如果要将具有不同数据类型的列作为指标列，则可以通过强制转换 `CAST(numericColumn as CHAR)` 输入列名称。您也可以在指标列字段中输入任意 SQL 表达式，这些表达式的计算结果为文本数据类型，例如 `CONCAT(column1, " ", CAST(numericColumn as CHAR))`。

### 列和聚合函数（SELECT）
<a name="columns-and-aggregation-functions-select"></a>

 在 `SELECT` 行中，您可以指定要使用的列和函数。在列字段中，您可以编写任意表达式来代替列名称，例如 `column1 * column2 / column3`。

 如果使用聚合函数，则必须对结果集分组。如果添加聚合函数，编辑器将自动添加 `GROUP BY time`。

 选择加号按钮并从菜单中选择 `Column`，即可添加更多值列。多个值列将在图形面板中绘制为单独的序列。

### 筛选数据（WHERE）
<a name="mysql-filter-data-where"></a>

 要添加筛选条件，请选择 `WHERE` 条件右侧的加号图标。您可以选择筛选条件，然后选择 `Remove` 来移除筛选条件。当前所选时间范围的筛选条件会自动添加到新查询中。

### 分组依据
<a name="mysql-group-by"></a>

 要按时间或任何其他列分组，请选择 GROUP BY 行末尾的加号图标。建议下拉列表将仅显示当前所选表的文本列，但可以手动输入任何列。您可以在项目上进行选择，然后选择 `Remove` 来移除组。

 如果添加任何分组，则所有选定的列都必须应用聚合函数。添加分组时，查询生成器会自动向所有没有聚合函数的列添加聚合函数。

#### 填充缺失值
<a name="mysql-gap-filling"></a>

 按时间分组时，Grafana 可以填充缺失值。time 函数接受两个参数。第一个参数是要作为分组依据的时间窗口，第二个参数是您希望 Grafana 填充缺失项目的值。

### 文本编辑器模式（原始）
<a name="mysql-text-editor-mode-raw"></a>

 选择汉堡包图标并选择**切换编辑器模式**或在查询下方选择**编辑 SQL**，即可切换到原始查询编辑器模式。

**注意**  
 如果使用原始查询编辑器，请确保您的查询至少具有 `ORDER BY time` 和返回时间范围的筛选条件。

## 宏
<a name="mysql-macros"></a>

 为了简化语法并允许动态部分（如日期范围筛选器），查询可包含宏。


|  宏示例  |  说明  | 
| --- | --- | 
|  \$1\$1\$1time(dateColumn)  |  将替换为一个表达式，以转换为 UNIX 时间戳，并将列重命名为 time\$1sec；例如，UNIX\$1TIMESTAMP(dateColumn) as time\$1sec。 | 
|  \$1\$1\$1timeEpoch(dateColumn)  |  将替换为一个表达式，以转换为 UNIX 时间戳，并将列重命名为 time\$1sec；例如，UNIX\$1TIMESTAMP(dateColumn) as time\$1sec。 | 
|  \$1\$1\$1timeFilter(dateColumn)  |  将替换为使用指定列名的时间范围筛选条件。例如，dateColumn BETWEEN FROM\$1UNIXTIME(1494410783) AND FROM\$1UNIXTIME(1494410983)。 | 
|  \$1\$1\$1timeFrom()  |  将替换为当前活动时间选择的开始时间。例如，FROM\$1UNIXTIME(1494410783)。 | 
|  \$1\$1\$1timeTo()  |  将替换为当前活动时间选择的结束时间。例如，FROM\$1UNIXTIME(1494410983)。 | 
|  \$1\$1\$1timeGroup(dateColumn,'5m')  |  将替换为 GROUP BY 子句中可用的表达式。例如，cast(cast(UNIX\$1TIMESTAMP(dateColumn)/(300) as signed)300 as signed),\$1  | 
|  \$1\$1\$1timeGroup(dateColumn,'5m', 0)  |  与前一行相同，但带有填充参数，序列中缺失的点将由 Grafana 添加，0 将用作值。 | 
|  \$1\$1\$1timeGroup(dateColumn,'5m', NULL)  |  与上面相同，但 NULL 将用作缺失点的值。 | 
|  \$1\$1\$1timeGroup(dateColumn,'5m', previous)  |  与上面相同，但如果未看到任何值，则该序列中的前一个值将用作填充值，但使用 NULL（仅适用于 Grafana 5.3\$1）。 | 
|  \$1\$1\$1timeGroupAlias(dateColumn,'5m')  |  将替换为与 \$1\$1\$1timeGroup 相同的内容，但增加了列别名（仅在 Grafana 5.3\$1 中可用）。 | 
| \$1\$1\$1unixEpochFilter(dateColumn) | 将使用指定列名替换为时间范围筛选条件，其中时间表示为 Unix 时间戳 例如 dateColumn > 1494410783 AND dateColumn < 1494497183。 | 
| \$1\$1\$1unixEpochFrom() | 将替换为当前活动时间选择的开始时间，作为 Unix 时间戳。例如 1494410783。 | 
| \$1\$1\$1unixEpochTo() | 将替换为当前活动时间选择的结束时间，作为 Unix 时间戳。例如 1494497183。 | 
| \$1\$1\$1unixEpochNanoFilter(dateColumn) | 将使用指定列名替换为时间范围筛选条件，其中时间表示为纳秒时间戳。例如 dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872。 | 
| \$1\$1\$1unixEpochNanoFrom() | 将替换为当前活动时间选择的开始时间，作为纳秒时间戳。例如 1494410783152415214。 | 
| \$1\$1\$1unixEpochNanoTo() | 将替换为当前活动时间选择的结束时间，作为纳秒时间戳。例如 1494497183142514872。 | 
| \$1\$1\$1unixEpochGroup(dateColumn,"5m", [fillmode]) | 与 \$1\$1\$1timeGroup 相同，但时间存储为 Unix 时间戳（仅在 Grafana 5.3\$1 中可用）。 | 
| \$1\$1\$1unixEpochGroupAlias(dateColumn,"5m", [fillmode])` | 与上面相同，但也增加了列别名（仅在 Grafana 5.3\$1 中可用）。 | 

 在面板编辑模式下，查询编辑器有一个**生成式 SQL** 链接，并在查询运行后显示。选择之后，将会展开并显示运行的原始插值 SQL 字符串。

## 表查询
<a name="mysql-table-queries"></a>

 如果**格式化为**查询选项设置为**表**，则基本上可以执行任何类型的 SQL 查询。表面板将自动显示查询返回的任何列和行的结果。

 以下代码显示了一个示例查询。

```
SELECT
  title as 'Title',
  user.login as 'Created By' ,
  dashboard.created as 'Created On'
 FROM dashboard
INNER JOIN user on user.id = dashboard.created_by
WHERE $__timeFilter(dashboard.created)
```

 您可以使用常规 `as` SQL 列选择语法来控制表面板列的名称。

## 时间序列查询
<a name="mysql-time-series-queries"></a>

 如果将**格式化为**设置为**时间序列**，例如在图形面板中使用，查询必须有一个名为 `time` 的列，该列返回 SQL 日期时间或任何表示 Unix 纪元的数字数据类型。除 `time` 和 `metric` 之外的任何列都被视为值列。您可以返回一个名为 `metric` 的列，该列用作值列的指标名称。如果返回多个值列和一个名为的 `metric` 列，则此列将用作序列名称的前缀（仅在 Grafana 5.3\$1 中可用）。

 时间序列查询的结果集必须按时间排序。

 以下代码示例显示了多个 `metric` 列。

```
SELECT
  $__timeGroup(time_date_time,'5m'),
  min(value_double),
  'min' as metric
FROM test_data
WHERE $__timeFilter(time_date_time)
GROUP BY time
ORDER BY time
```

 以下代码示例显示了如何使用 \$1\$1\$1timeGroup 宏中的填充参数将空值转换为零。

```
SELECT
  $__timeGroup(createdAt,'5m',0),
  sum(value_double) as value,
  measurement
FROM test_data
WHERE
  $__timeFilter(createdAt)
GROUP BY time, measurement
ORDER BY time
```

 以下代码示例显示了多个列。

```
SELECT
  $__timeGroup(time_date_time,'5m'),
  min(value_double) as min_value,
  max(value_double) as max_value
FROM test_data
WHERE $__timeFilter(time_date_time)
GROUP BY time
ORDER BY time
```

不支持基于时间范围和面板宽度按时间进行动态分组。

## 模板化
<a name="mysql-templating"></a>

 您可以在指标查询中使用变量来代替服务器、应用程序和传感器名称等硬编码。变量显示为控制面板顶部的下拉选择框。您可以使用这些下拉框来更改控制面板中显示的数据。

 有关模板化和模板变量的更多信息，请参阅 [模板](templates-and-variables.md#templates)。

### 查询变量
<a name="mysql-query-variable"></a>

 如果添加 `Query` 类型的模板变量，则可以编写一个 MySQL 查询，该查询可以返回测量名称、键名或键值等显示为下拉选择框的内容。

 例如，如果在模板变量 *Query* 设置中指定了这样的查询，则会有一个变量，其中包含表中 `hostname` 列的所有值的。

```
SELECT hostname FROM my_host
```

 查询可以返回多列，Grafana 会自动根据这些列创建一个列表。例如，以下查询将返回一个列表，其中包含来自 `hostname` 和 `hostname2` 的值。

```
SELECT my_host.hostname, my_other_host.hostname2 FROM my_host JOIN my_other_host ON my_host.city = my_other_host.city
```

 要在查询中使用依赖于时间范围的宏（如 `$__timeFilter(column)`），必须将模板变量的刷新模式设置为*时间范围更改时*。

```
SELECT event_name FROM event_log WHERE $__timeFilter(time_column)
```

 另一种选择是可以创建 key/value 变量的查询。该查询应返回名为 `__text` 和 `__value` 的两列。`__text` 列值应该是唯一的（如果不是唯一的，则使用第一个值）。下拉列表中的选项将具有文本和值，因此您可以将友好名称作为文本，将 ID 作为值。

以下代码示例显示了一个以 `hostname` 作为文本，以 `id` 作为值的查询。

```
SELECT hostname AS __text, id AS __value FROM my_host
```

 您还可以创建嵌套变量。例如，您还有一个名为 `region` 的变量。然后，您可以让主机变量仅显示来自当前所选区域的主机，并使用以下查询（如果 `region` 是多值变量，则使用 `IN` 比较运算符而不是 `=` 与多个值匹配）。

```
SELECT hostname FROM my_host  WHERE region IN($region)
```

#### 使用 `__searchFilter` 筛选查询变量结果
<a name="using-__searchfilter-to-filter-results-in-query-variable"></a>

 在查询字段中使用 `__searchFilter`，根据用户在下拉选择框中输入的内容筛选查询结果。当用户未输入任何内容时，`__searchFilter` 的默认值为 `%`。

**注意**  
 请务必用引号将 `__searchFilter` 表达式括起来，因为 Grafana 不会为您执行此操作。

 以下示例显示了当用户在下拉选择框中键入时，如何使用 `__searchFilter` 作为查询字段的一部分来启用 `hostname` 搜索。

```
SELECT hostname FROM my_host  WHERE hostname LIKE '$__searchFilter'
```

### 在查询中使用变量
<a name="using-variables-in-queries-2"></a>

 从 Grafana 4.3.0 到 4.6.0，模板变量总是自动引用，因此如果是字符串值，请不要在 where 子句中用引号将其括起来。

 从 Grafana 4.7.0 开始，只有当模板变量为 `multi-value` 时，才会引用模板变量值。

 如果该变量是多值变量，则使用 `IN` 比较运算符而不是 `=` 与多个值匹配。

 共有两种语法：

 `$<varname>` 名为 `hostname` 的模板变量的示例：

```
SELECT
  UNIX_TIMESTAMP(atimestamp) as time,
  aint as value,
  avarchar as metric
FROM my_table
WHERE $__timeFilter(atimestamp) and hostname in($hostname)
ORDER BY atimestamp ASC
```

 `[[varname]]` 名为 `hostname` 的模板变量的示例：

```
SELECT
  UNIX_TIMESTAMP(atimestamp) as time,
  aint as value,
  avarchar as metric
FROM my_table
WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
ORDER BY atimestamp ASC
```

#### 关闭多值变量的引用
<a name="disabling-quoting-for-multi-value-variables"></a>

 Grafana 会自动为多值变量创建带引号、以逗号分隔的字符串。例如，如果选择 `server01` 和 `server02`，则其格式为：`'server01', 'server02'`。要关闭引用，请对变量使用 csv 格式选项。

 `${servers:csv}` 

 有关变量格式选项的更多信息，请参阅 [高级变量格式选项](templates-and-variables.md#advanced-variable-format-options)。

## Annotations
<a name="mysql-annotations"></a>

 您可以使用注释在图形上叠加丰富的事件信息。您可以通过控制面板菜单/注释视图添加注释查询。有关更多信息，请参阅 。

 以下示例代码演示了一个查询，该查询使用具有纪元值的 time 列。

```
SELECT
  epoch_time as time,
  metric1 as text,
  CONCAT(tag1, ',', tag2) as tags
FROM
  public.test_data
WHERE
  $__unixEpochFilter(epoch_time)
```

以下示例代码演示了一个区域查询，该查询使用具有纪元值的 time 和 timeend 列。

**注意**  
 仅在 Grafana v6.6\$1 中可用。

```
SELECT
  epoch_time as time,
  epoch_timeend as timeend,
  metric1 as text,
  CONCAT(tag1, ',', tag2) as tags
FROM
  public.test_data
WHERE
  $__unixEpochFilter(epoch_time)
```

 以下示例代码显示了使用原生 SQL date/time 数据类型的时间列的查询。

```
SELECT
  native_date_time as time,
  metric1 as text,
  CONCAT(tag1, ',', tag2) as tags
FROM
  public.test_data
WHERE
  $__timeFilter(native_date_time)
```


|  Name  |  说明  | 
| --- | --- | 
|  time  |  date/time 字段的名称。可以是具有本机 SQL date/time 数据类型或纪元值的列。 | 
|  timeend  |  结束 date/time 字段的可选名称。可以是具有本机 SQL date/time 数据类型或纪元值的列。 | 
|  text  |  事件描述字段。 | 
|  tags  |  用于事件标签的可选字段名称，显示为以逗号分隔的字符串。 | 

## 警报
<a name="mysql-alerting"></a>

 时间序列查询应在警报条件下工作。警报规则条件尚不支持表格式查询。