Airflow 系列4:Airflow 元数据库表结构介绍


前面已经将 Airflow 2.3.4 的元数据库从默认 SQLite 修改为了 MySQL,并将执行器修改为了 LocalExecutor

元数据库配置完成之后,Airflow 的很多运行状态都会写入 MySQL 中。

例如:

  • DAG 是否暂停
  • DAG 最近一次解析时间
  • DAG Run 的运行状态
  • Task Instance 的运行状态
  • 任务失败记录
  • 任务重试记录
  • XCom 数据
  • Connection 配置
  • Variable 配置
  • Web UI 用户、角色和权限

所以,想要真正排查 Airflow 调度问题,除了会看 Web UI,还需要理解元数据库中几张核心表的作用。

本文基于 Apache Airflow 2.3.4 初始化后的 MySQL 元数据库 airflow_db 进行整理。

一、Airflow 元数据库整体结构

下面这张图是通过 DBeaver 查看 airflow_db 得到的元数据库 ER 图。

Airflow 元数据库 ER 图

从图中可以看到,Airflow 元数据库中的表并不是完全围绕一条主线展开的,而是可以大致分成几类:

分类 主要表 作用
DAG 定义相关 dagserialized_dagdag_codedag_pickledag_tagimport_error 保存 DAG 基础信息、序列化信息、源码和解析错误
调度运行核心 dag_runtask_instance 保存 DAG 运行记录和任务实例运行记录
任务运行辅助 task_failtask_rescheduletask_maprendered_task_instance_fieldsxcom 保存失败、重调度、动态任务、模板渲染和任务间传值
调度器与日志 jobloglog_templatecallback_requestsla_misssensor_instancetrigger 保存调度器心跳、操作日志、日志模板、SLA 和 Trigger 信息
配置与资源 connectionvariableslot_pool 保存连接信息、变量和资源池
Web 权限 ab_userab_roleab_permissionab_view_menu 保存 Airflow Web UI 的用户、角色和权限
数据库版本 alembic_version 保存元数据库迁移版本

在实际排查问题时,不需要一开始就记住所有表。

最常用、最应该先理解的是:

dag
dag_run
task_instance
job
log
connection
variable

其中 dag_runtask_instance 是调度状态排查的核心。

二、当前元数据库表清单

当前 Airflow 2.3.4 初始化后,airflow_db 中一共有 33 张表。

可以通过下面的 SQL 查看:

SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = 'airflow_db'
ORDER BY table_name;

当前环境中的表如下:

表名 当前行数 说明
ab_permission 11 Web 权限动作
ab_permission_view 89 权限和菜单视图的关联
ab_permission_view_role 207 角色和权限视图的关联
ab_register_user 0 注册用户信息
ab_role 5 Web 角色
ab_user 0 Web 用户
ab_user_role 0 用户和角色关联
ab_view_menu 48 Web 菜单视图
alembic_version 1 数据库迁移版本
callback_request 0 回调请求
connection 52 Airflow Connection 配置
dag 0 DAG 基础状态
dag_code 0 DAG 源码
dag_pickle 0 Pickle 格式 DAG
dag_run 0 DAG 运行记录
dag_tag 0 DAG 标签
import_error 0 DAG 导入错误
job 1 Scheduler 等 Job 运行记录
log 7 操作日志
log_template 2 任务日志路径模板
rendered_task_instance_fields 0 渲染后的任务字段
sensor_instance 0 Sensor 实例
serialized_dag 0 序列化 DAG
session 5 Web Session
sla_miss 0 SLA Miss 记录
slot_pool 0 Pool 资源池
task_fail 0 任务失败记录
task_instance 0 任务实例记录
task_map 0 动态任务映射
task_reschedule 0 任务重新调度记录
trigger 0 Trigger 记录
variable 0 Airflow Variable
xcom 0 任务间通信数据

可以看到,在刚初始化完成、还没有运行 DAG 的情况下,大量调度相关表都是空的。

这也比较正常。

因为 dag_runtask_instancetask_failxcom 等表,只有在 DAG 被解析、触发、运行之后才会逐渐产生数据。

三、DAG 定义相关表

3.1 dag

dag 表保存 DAG 的基础状态信息。

这个表不是保存完整 DAG 代码的地方,而是保存 Airflow 识别到的 DAG 状态。

主要字段如下:

字段 说明
dag_id DAG 的唯一标识
is_paused DAG 是否暂停
is_subdag 是否为 SubDAG
is_active DAG 是否仍然活跃
last_parsed_time 最近一次被解析的时间
fileloc DAG 文件路径
owners DAG 所属用户
description DAG 描述
schedule_interval 调度周期
next_dagrun 下一次 DAG Run 时间
next_dagrun_create_after 下一次允许创建 DAG Run 的时间
max_active_tasks 当前 DAG 最大并发任务数
max_active_runs 当前 DAG 最大并发运行数
has_import_errors 是否存在导入错误
timetable_description 调度时间表描述

如果某个 DAG 在页面上看不到,或者页面上显示有导入错误,可以先查看 dagimport_error

常用 SQL:

SELECT dag_id,
       is_paused,
       is_active,
       last_parsed_time,
       fileloc,
       next_dagrun,
       has_import_errors
FROM dag
ORDER BY last_parsed_time DESC;

3.2 serialized_dag

serialized_dag 表保存序列化后的 DAG 信息。

主要字段如下:

字段 说明
dag_id DAG ID
fileloc DAG 文件路径
fileloc_hash 文件路径 Hash
data 序列化后的 DAG JSON
last_updated 最近更新时间
dag_hash DAG 内容 Hash
data_compressed 压缩后的 DAG 数据

在 Airflow 2.x 中,Webserver 不一定直接解析所有 DAG 文件,而是可以读取序列化后的 DAG 数据进行展示。

所以 serialized_dag 对 Web UI 展示很重要。

3.3 dag_code

dag_code 表保存 DAG 文件的源码。

主要字段如下:

字段 说明
fileloc_hash DAG 文件路径 Hash,主键
fileloc DAG 文件路径
source_code DAG 源码内容
last_updated 最近更新时间

如果在 Web UI 中查看 DAG Code,背后就可能会用到这类数据。

3.4 dag_tag

dag_tag 表保存 DAG 标签。

主要字段如下:

字段 说明
name 标签名称
dag_id DAG ID

主键是:

name + dag_id

一个 DAG 可以有多个标签,一个标签也可以被多个 DAG 使用。

3.5 import_error

import_error 表保存 DAG 文件导入失败记录。

主要字段如下:

字段 说明
id 主键
timestamp 错误发生时间
filename 发生错误的 DAG 文件
stacktrace 错误堆栈

如果页面上显示 DAG Import Errors,可以直接查这张表:

SELECT timestamp, filename, stacktrace
FROM import_error
ORDER BY timestamp DESC;

这张表对排查 DAG 语法错误、依赖缺失、模块导入失败很有用。

四、调度运行核心表

4.1 dag_run

dag_run 表表示一次 DAG 运行。

一个 DAG 每被调度一次,或者被手动触发一次,都会产生一条 DAG Run 记录。

主要字段如下:

字段 说明
id 自增主键
dag_id DAG ID
execution_date 逻辑执行时间
state DAG Run 状态
run_id 运行 ID
external_trigger 是否外部触发
conf 手动触发时传入的配置
start_date 实际开始时间
end_date 实际结束时间
run_type 运行类型,例如 scheduled、manual
last_scheduling_decision 最近一次调度决策时间
creating_job_id 创建该 DAG Run 的 Job ID
queued_at 入队时间
data_interval_start 数据区间开始时间
data_interval_end 数据区间结束时间
log_template_id 日志模板 ID

这里要注意 execution_date

在 Airflow 2.x 中,它更接近“逻辑日期”,不一定等于任务真实开始执行的时间。

任务真实开始执行的时间要看 start_date

常用查询:

SELECT dag_id,
       run_id,
       run_type,
       state,
       execution_date,
       start_date,
       end_date,
       data_interval_start,
       data_interval_end
FROM dag_run
ORDER BY execution_date DESC;

如果一个 DAG 没有按预期触发,可以先查 dag_run

SELECT *
FROM dag_run
WHERE dag_id = 'your_dag_id'
ORDER BY execution_date DESC;

4.2 task_instance

task_instance 表表示一次任务实例运行记录。

这是 Airflow 元数据库中排查任务问题最重要的一张表。

一个 DAG 中有多个 Task,一次 DAG Run 下每个 Task 都会对应一条 Task Instance 记录。

主要字段如下:

字段 说明
dag_id DAG ID
task_id Task ID
run_id 所属 DAG Run ID
map_index 动态任务映射下标,普通任务一般为 -1
state Task Instance 状态
try_number 当前尝试次数
start_date 开始执行时间
end_date 结束执行时间
duration 执行耗时
hostname 执行任务的主机
unixname 执行用户
job_id 关联的 Job ID
pool 使用的 Pool
queue 队列名称
priority_weight 优先级权重
operator Operator 类型
queued_dttm 入队时间
pid 执行进程 PID
max_tries 最大重试次数
executor_config Executor 配置
pool_slots 占用 Pool Slot 数量
trigger_id 关联 Trigger ID
trigger_timeout Trigger 超时时间
next_method Deferrable Operator 恢复时调用的方法
next_kwargs 恢复方法参数

task_instance 的主键是:

dag_id + task_id + run_id + map_index

也就是说,同一个 dag_idtask_id 可能会出现很多条记录,因为它们属于不同的 run_id

常用查询:

SELECT dag_id,
       task_id,
       run_id,
       state,
       try_number,
       start_date,
       end_date,
       duration,
       operator,
       hostname
FROM task_instance
ORDER BY start_date DESC;

查看失败任务:

SELECT dag_id,
       task_id,
       run_id,
       state,
       try_number,
       start_date,
       end_date
FROM task_instance
WHERE state = 'failed'
ORDER BY end_date DESC;

查看排队中的任务:

SELECT dag_id,
       task_id,
       run_id,
       state,
       queued_dttm,
       pool,
       queue,
       priority_weight
FROM task_instance
WHERE state = 'queued'
ORDER BY queued_dttm;

4.3 dag_runtask_instance 的关系

dag_runtask_instance 是一对多关系。

可以简单理解为:

一次 DAG Run
  |
  +-- 多个 Task Instance

在当前 Airflow 2.3.4 的元数据库中,task_instance 通过下面的外键关联到 dag_run

task_instance(dag_id, run_id) -> dag_run(dag_id, run_id)

排查任务时,经常会把这两张表关联查询。

例如查看某个 DAG 最近一次运行下所有任务状态:

SELECT dr.dag_id,
       dr.run_id,
       dr.state AS dag_state,
       ti.task_id,
       ti.state AS task_state,
       ti.try_number,
       ti.start_date,
       ti.end_date
FROM dag_run dr
JOIN task_instance ti
  ON dr.dag_id = ti.dag_id
 AND dr.run_id = ti.run_id
WHERE dr.dag_id = 'your_dag_id'
ORDER BY dr.execution_date DESC, ti.task_id;
DAG Run 与 Task Instance 关系图

从这张图中可以看到,排查调度状态时,dag_run 表示一次工作流运行,task_instance 表示这次运行中的具体任务状态。失败、重调度、XCom 和模板渲染结果,都是围绕具体的 Task Instance 展开的。

五、任务运行辅助表

5.1 task_fail

task_fail 表保存任务失败记录。

主要字段如下:

字段 说明
id 主键
task_id Task ID
dag_id DAG ID
start_date 失败这次尝试的开始时间
end_date 失败这次尝试的结束时间
duration 失败这次尝试的耗时
map_index 动态任务映射下标
run_id DAG Run ID

这张表适合统计任务失败次数。

例如:

SELECT dag_id,
       task_id,
       COUNT(*) AS fail_count
FROM task_fail
GROUP BY dag_id, task_id
ORDER BY fail_count DESC;

5.2 task_reschedule

task_reschedule 表保存任务重新调度记录。

它常见于 Sensor 任务,特别是 mode='reschedule' 的场景。

主要字段如下:

字段 说明
id 主键
task_id Task ID
dag_id DAG ID
try_number 尝试次数
start_date 本次检查开始时间
end_date 本次检查结束时间
duration 本次检查耗时
reschedule_date 下一次重新调度时间
run_id DAG Run ID
map_index 动态任务映射下标

如果一个 Sensor 一直没有成功,可以查这张表看它是否在反复 reschedule。

5.3 rendered_task_instance_fields

rendered_task_instance_fields 表保存模板渲染后的任务字段。

例如 BashOperator 中写了模板变量:

bash_command='echo {{ ds }}'

Airflow 在具体运行时会将模板变量渲染成实际值,渲染结果就可能保存到这张表中。

主要字段如下:

字段 说明
dag_id DAG ID
task_id Task ID
run_id DAG Run ID
map_index 动态任务映射下标
rendered_fields 渲染后的字段
k8s_pod_yaml Kubernetes Pod YAML

5.4 xcom

xcom 表保存任务之间传递的小数据。

XCom 的全称是 Cross Communication。

它适合在 Task 之间传递少量元信息,例如上游任务生成的文件路径、运行结果标记、某个小的 JSON 对象。

主要字段如下:

字段 说明
dag_run_id DAG Run 主键 ID
task_id Task ID
key XCom Key
value XCom Value,二进制保存
timestamp 写入时间
dag_id DAG ID
run_id DAG Run ID
map_index 动态任务映射下标

注意,XCom 不适合传递大量数据。

如果需要在任务之间传递大文件或大数据集,更合理的方式是把数据写到 HDFS、对象存储、MySQL、Hive 等外部系统中,然后在 XCom 中只传路径或标识。

5.5 task_map

task_map 表和动态任务映射有关。

主要字段如下:

字段 说明
dag_id DAG ID
task_id Task ID
run_id DAG Run ID
map_index 映射下标
length 映射长度
keys 映射 Key

如果不使用 Dynamic Task Mapping,这张表通常不会有数据。

六、调度器和日志相关表

6.1 job

job 表保存 Airflow 内部 Job 的运行记录,例如 SchedulerJob。

主要字段如下:

字段 说明
id 主键
dag_id DAG ID,有些 Job 不绑定具体 DAG
state Job 状态
job_type Job 类型
start_date 开始时间
end_date 结束时间
latest_heartbeat 最近心跳时间
executor_class 使用的 Executor
hostname 主机名
unixname 系统用户

当前环境中已经有一条 Scheduler 记录:

job_type: SchedulerJob
state: running
executor_class: LocalExecutor
hostname: ubuntu-linux-2404

如果怀疑 Scheduler 没有正常工作,可以看 job 表中的心跳时间:

SELECT id,
       state,
       job_type,
       start_date,
       latest_heartbeat,
       executor_class,
       hostname
FROM job
ORDER BY latest_heartbeat DESC;

6.2 log

log 表保存 Airflow 操作日志。

注意,这里不是每个任务的完整运行日志。

任务运行日志通常保存在本地日志目录、远程日志系统或对象存储中,而 log 表保存的是 Airflow 的事件记录。

主要字段如下:

字段 说明
id 主键
dttm 事件时间
dag_id DAG ID
task_id Task ID
event 事件名称
execution_date 执行时间
owner 操作用户
extra 额外信息
map_index 动态任务映射下标

当前环境中已经记录了几条 CLI 操作:

cli_users_create
cli_check
cli_webserver
cli_scheduler

常用查询:

SELECT dttm,
       dag_id,
       task_id,
       event,
       owner
FROM log
ORDER BY dttm DESC;

6.3 log_template

log_template 表保存任务日志路径模板。

当前环境中有两条默认模板。

主要字段如下:

字段 说明
id 主键
filename 日志文件路径模板
elasticsearch_id Elasticsearch 日志 ID 模板
created_at 创建时间

例如其中一条模板类似:

dag_id={{ ti.dag_id }}/run_id={{ ti.run_id }}/task_id={{ ti.task_id }}/attempt={{ try_number }}.log

这说明 Airflow 会根据 DAG ID、Run ID、Task ID、尝试次数组织任务日志路径。

6.4 sensor_instancetriggercallback_requestsla_miss

这几张表属于更细的调度能力。

表名 作用
sensor_instance 保存 Sensor 实例状态
trigger 保存 Trigger 信息,主要和 Deferrable Operator 相关
callback_request 保存回调请求
sla_miss 保存 SLA 未满足记录

初学阶段不需要优先记住这些表。

当遇到 Sensor、SLA、Deferrable Operator 相关问题时,再重点查看。

七、配置和资源相关表

7.1 connection

connection 表保存 Airflow 中配置的连接信息。

在 Web UI 中进入:

Admin -> Connections

看到的连接信息就来自这张表。

主要字段如下:

字段 说明
id 主键
conn_id 连接 ID
conn_type 连接类型
host 主机地址
schema 数据库或 Schema
login 用户名
password 密码
port 端口
extra 额外配置
is_encrypted 密码是否加密
is_extra_encrypted extra 是否加密
description 描述

当前环境初始化后,connection 表中有 52 条默认连接。

例如:

airflow_db
aws_default
azure_default
cassandra_default
databricks_default

查询示例:

SELECT conn_id,
       conn_type,
       host,
       `schema`,
       login,
       port
FROM connection
ORDER BY conn_id;

注意,connection 表中可能保存密码,不建议在博客或截图中直接暴露完整内容。

7.2 variable

variable 表保存 Airflow Variables。

在 Web UI 中进入:

Admin -> Variables

看到的变量信息就来自这张表。

主要字段如下:

字段 说明
id 主键
key 变量名
val 变量值
is_encrypted 是否加密
description 描述

Variables 适合保存一些运行参数,例如环境标识、路径、开关配置等。

不要把大块业务数据放到 Variables 中。

7.3 slot_pool

slot_pool 表保存 Airflow Pool 配置。

Pool 用来限制某类任务的并发数。

主要字段如下:

字段 说明
id 主键
pool Pool 名称
slots Slot 数量
description 描述

例如某个外部接口最多只能同时被 3 个任务调用,就可以为这类任务配置一个 Pool,并设置 slots = 3

任务实例表 task_instance 中也有 poolpool_slots 字段,用来记录任务使用哪个 Pool、占用多少 Slot。

八、Web 用户和权限相关表

Airflow Web UI 使用 Flask AppBuilder 做权限管理,所以会有一组 ab_ 开头的表。

主要表如下:

表名 说明
ab_user Web 用户
ab_role 角色
ab_user_role 用户和角色关联
ab_permission 权限动作
ab_view_menu 菜单或视图
ab_permission_view 权限动作和菜单视图关联
ab_permission_view_role 角色和权限视图关联
ab_register_user 注册用户
session Web Session

这组表主要服务于 Web UI 登录和权限控制。

例如创建管理员用户:

airflow users create \
  --username admin \
  --firstname Admin \
  --lastname User \
  --role Admin \
  --email admin@example.com \
  --password admin

执行后,相关用户和角色信息会写入 ab_userab_roleab_user_role 等表。

一般情况下,不建议直接手动修改这组权限表。

更推荐使用 Airflow CLI 或 Web UI 进行管理。

九、数据库迁移版本表

9.1 alembic_version

alembic_version 表用于记录 Airflow 元数据库迁移版本。

当前环境中的版本号是:

f5fcbda3e651

查看 SQL:

SELECT *
FROM alembic_version;

Airflow 使用 Alembic 管理数据库结构变更。

执行下面这些命令时,都可能会读取或更新这张表:

airflow db init
airflow db upgrade
airflow db check

如果升级 Airflow 版本后元数据库结构不一致,通常就需要关注这张表和 Airflow 的数据库迁移日志。

十、核心外键关系

从当前数据库中可以看到几个比较重要的外键关系。

10.1 DAG 标签关系

dag_tag(dag_id) -> dag(dag_id)

表示标签属于某个 DAG。

10.2 DAG Run 与 Task Instance

task_instance(dag_id, run_id) -> dag_run(dag_id, run_id)

这是调度运行中最核心的关系。

10.3 Task Instance 与失败、重试、XCom

task_fail(dag_id, task_id, run_id, map_index) -> task_instance(...)
task_reschedule(dag_id, task_id, run_id, map_index) -> task_instance(...)
xcom(dag_id, task_id, run_id, map_index) -> task_instance(...)
rendered_task_instance_fields(...) -> task_instance(...)

这些表都围绕具体任务实例展开。

也就是说,先找到 task_instance,再继续查失败、重试、XCom、模板渲染结果,排查思路会更清楚。

10.4 权限关系

ab_user_role(user_id) -> ab_user(id)
ab_user_role(role_id) -> ab_role(id)
ab_permission_view_role(role_id) -> ab_role(id)
ab_permission_view_role(permission_view_id) -> ab_permission_view(id)

这部分主要用于 Web UI 权限。

十一、常用排查 SQL

11.1 查看 DAG 状态

SELECT dag_id,
       is_paused,
       is_active,
       last_parsed_time,
       next_dagrun,
       has_import_errors
FROM dag
ORDER BY last_parsed_time DESC;

11.2 查看最近 DAG Run

SELECT dag_id,
       run_id,
       run_type,
       state,
       execution_date,
       start_date,
       end_date
FROM dag_run
ORDER BY execution_date DESC
LIMIT 20;

11.3 查看失败任务

SELECT dag_id,
       task_id,
       run_id,
       state,
       try_number,
       start_date,
       end_date
FROM task_instance
WHERE state = 'failed'
ORDER BY end_date DESC;

11.4 查看排队任务

SELECT dag_id,
       task_id,
       run_id,
       state,
       queued_dttm,
       pool,
       queue
FROM task_instance
WHERE state = 'queued'
ORDER BY queued_dttm;

11.5 查看 Scheduler 心跳

SELECT id,
       state,
       job_type,
       latest_heartbeat,
       executor_class,
       hostname
FROM job
ORDER BY latest_heartbeat DESC;

11.6 查看 DAG 导入错误

SELECT timestamp,
       filename,
       stacktrace
FROM import_error
ORDER BY timestamp DESC;

11.7 查看 Connection 配置

SELECT conn_id,
       conn_type,
       host,
       `schema`,
       login,
       port
FROM connection
ORDER BY conn_id;

十二、总结

Airflow 元数据库中的表很多,但是排查问题时并不需要平均用力。

可以先按下面的顺序理解:

  1. dag:Airflow 是否识别到 DAG。
  2. dag_run:DAG 有没有被调度或触发。
  3. task_instance:具体 Task 当前是什么状态。
  4. task_failtask_reschedulexcom:任务失败、重新调度和任务间通信。
  5. job:Scheduler 等内部进程是否还在正常心跳。
  6. logimport_error:操作记录和 DAG 导入错误。
  7. connectionvariableslot_pool:Airflow 配置和资源限制。

简单来说:

dag_run 看工作流运行,task_instance 看任务运行,job 看调度器心跳,import_error 看 DAG 是否解析失败。

理解这几张表之后,再看 Airflow Web UI 中的状态,就不会只是停留在页面展示,而是能进一步从数据库层面确认调度链路到底卡在哪里。


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录