MySQL data lineage is the column-by-column map of how data flows through your MySQL views, INSERT ... SELECT jobs, and ETL scripts: which source columns feed each target column, and through which joins, filters, and aggregations. MySQL itself cannot show you this — information_schema describes structure, not dataflow. Flujo de SQL de Gudu builds the lineage automatically by parsing your MySQL SQL with a dedicated MySQL dialect parser, producing an interactive, drillable diagram down to individual columns.
See it on your own SQL: paste any MySQL view or INSERT ... SELECT into the Visualizador de linaje SQLFlow gratuito, pick the MySQL dialect, and get a column-level lineage diagram in seconds.
Why information_schema can’t give you MySQL data lineage
MySQL’s information_schema is a structural catalog. It will tell you that daily_revenue has five columns, what their types are, and (via KEY_COLUMN_USAGE) which foreign keys point where. What it will never tell you is that daily_revenue.net_revenue is computed from orders.amount minus orders.discount, filtered on orders.status, and grouped by customers.region.
That dataflow knowledge lives in one place only: the SQL text itself. In a typical MySQL estate that means view definitions (information_schema.VIEWS stores the text, but nothing interprets it), the INSERT ... SELECT y ON DUPLICATE KEY UPDATE statements your ETL jobs run, generated-column expressions in your DDL, and application-side query files. To turn those into lineage, something has to actually parse and semantically resolve the SQL — expanding SELECCIONAR *, tracing columns through joins, subqueries, and view stacks. That is what SQLFlow does.
A worked example: a reporting table fed by INSERT-SELECT
Here is the kind of statement that runs nightly in thousands of MySQL-backed reporting setups — an upsert that aggregates orders into a summary table:
INSERT INTO daily_revenue
(report_date, region, order_count, gross_revenue, net_revenue)
SELECT o.order_date,
c.region,
COUNT(*),
SUM(o.amount),
SUM(o.amount - o.discount)
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'completed'
GROUP BY o.order_date, c.region
ON DUPLICATE KEY UPDATE
order_count = VALUES(order_count),
gross_revenue = VALUES(gross_revenue),
net_revenue = VALUES(net_revenue);
Run this through SQLFlow and it extracts, per target column, both the columns that directly supply its value and the columns that shape the result without landing in it:
| Target column | Direct sources | Indirect (impact) influences |
|---|---|---|
daily_revenue.report_date | orders.order_date | orders.status |
daily_revenue.region | customers.region | customers.id, orders.customer_id, orders.status |
daily_revenue.gross_revenue | orders.amount via SUMA() | orders.order_date, customers.region (GROUP BY), join keys, orders.status |
daily_revenue.net_revenue | orders.amount, orders.discount via SUMA() | same as above |
The distinction in the third column matters. orders.status never appears in daily_revenue, yet changing how it is populated changes every number in the report. SQLFlow models this linaje indirecto (columns used in DÓNDE, JOIN, y AGRUPACIÓN POR) as a separate, toggleable relationship type in the diagram — most lineage tools do not make the distinction at all, and it is exactly what you need for honest impact analysis.
Lineage through MySQL views — including stacked views
Views are where table-level lineage tools quietly give up. A BI dashboard reads v_regional_kpis, which selects from v_completed_orders, which selects from orders y customers. To answer “what feeds this dashboard column?”, the lineage engine must resolve column references down through every layer of the view stack, expand any SELECCIONAR * against the underlying definitions, and carry the transformations along.
SQLFlow resolves column references through views, CTEs, subqueries, and star expansion as part of its semantic analysis. Point it at your schema over JDBC and it pulls the DDL and view definitions itself, so the lineage graph reflects the views as they actually exist in the database, not as they exist in a stale migration folder.
Generated columns: lineage inside a single table
MySQL generated columns embed dataflow directly in the DDL:
CREATE TABLE order_items (
quantity INT,
unit_price DECIMAL(10,2),
line_total DECIMAL(12,2) AS (quantity * unit_price) STORED
);
line_total is never written by any INSERT, so any approach that only watches DML misses its provenance entirely. Because SQLFlow parses the generated-column expression as SQL, line_total gets proper lineage edges from quantity y unit_price, and anything downstream that reads line_total traces all the way back to those two physical columns.
How to build MySQL lineage with SQLFlow
- Collect the SQL. Paste statements or upload files into Nube SQLFlow, or connect your MySQL instance over JDBC so SQLFlow reads the DDL and view definitions directly. dbt users can import the dbt manifest.
- Parse with the MySQL dialect. SQLFlow uses a dialect-specific MySQL parser (one of 39 dialect parsers, not a generic ANSI grammar), so MySQL-specific constructs like
ON DUPLICATE KEY UPDATE, backtick-quoted identifiers, and generated columns are analyzed correctly rather than skipped. - Explore and export. Trace any column upstream or downstream in the interactive diagram, toggle indirect lineage on and off, and export the graph as JSON, CSV, or PNG — or pull it programmatically via the REST API. Since v8.2.3 you can also ask questions in plain English (“which reports depend on
customers.region?”); every table and column the AI cites is validated against the analyzed graph before display.
The engine underneath is General SQL Parser, a commercial SQL compiler front-end developed since the mid-2000s and validated against roughly 13,600 per-dialect SQL test fixtures. Lineage quality is a parsing problem before it is anything else, and that regression corpus is what keeps real-world MySQL — with all its dialect quirks — from silently falling out of the graph.
What about open-source MySQL lineage options?
Open-source parsers like sqllineage y sqlglot handle individual MySQL SELECT and INSERT statements well, and if you need lineage for a handful of straightforward queries inside a Python pipeline, they are a reasonable place to start. Catalog platforms such as DataHub and OpenMetadata are strong at organizing and displaying lineage once it exists. The gap shows up in producing accurate lineage from hard SQL at scale: resolving columns through stacked views using live schema metadata, distinguishing direct from indirect lineage, expanding SELECCIONAR * correctly, and doing it across thousands of scripts. SQLFlow focuses on that extraction problem — and then feeds the results into the catalogs via its export adapters for DataHub, Microsoft Purview, and OpenMetadata.
When MySQL is only part of the picture
MySQL is rarely the whole estate. It is often the OLTP source that feeds a warehouse, or one of several engines an ETL layer crosses. SQLFlow parses 39 SQL dialects with the same column-level analysis, so lineage that starts in MySQL and ends in Snowflake, BigQuery, or PostgreSQL lives in one graph. Enterprise deployments batch-scan estates of 100+ databases and over a million columns, with incremental scans and a persistent lineage repository. For teams that cannot let SQL text leave their network, SQLFlow local runs on Docker or Kubernetes fully air-gapped.
To see what the output looks like across a range of real statements — multi-join inserts, view stacks, stored procedures — browse the data lineage examples.
Preguntas frecuentes
Does building MySQL lineage require access to my data?
No. SQLFlow performs static analysis of SQL code and, optionally, schema metadata such as table and view definitions. It never reads table row data. With the On-Premise edition, even the SQL text stays inside your network.
Can SQLFlow trace lineage through INSERT … SELECT … ON DUPLICATE KEY UPDATE?
Yes. The MySQL dialect parser analyzes the full statement: each target column is linked to the source columns in the SELECT, including expressions inside aggregates, and the upsert clause is handled as part of the same dataflow.
Does information_schema contain lineage information?
No. information_schema describes structure: tables, columns, types, keys, and the raw text of view definitions. It does not interpret any SQL, so it cannot tell you which source columns feed a given target column. Lineage requires parsing the view and DML SQL, which is what SQLFlow does.
How does SQLFlow handle SELECT * in MySQL views?
SQLFlow expands SELECCIONAR * against the actual schema (pulled over JDBC or supplied as DDL), so every column that flows through the star gets its own lineage edge instead of one vague table-to-table arrow.
Is there a free way to try MySQL data lineage?
Yes. SQLFlow Cloud has a free tier: paste MySQL SQL in the browser and get the column-level diagram immediately. Premium is $49.99/month; On-Premise is $500/month or $4,800 one-time per selected database type — see precios.
Can I export the MySQL lineage into my data catalog?
Yes. Export as JSON, CSV, or PNG, query the REST API, or use the built-in export adapters for DataHub, Microsoft Purview, and OpenMetadata in enterprise deployments.
Map your MySQL dataflow now
Paste a view or an INSERT-SELECT into the free visualizer, or talk to us about scanning your whole MySQL estate.