How Grafana connects to MySQL and SQL Server dashboards
Operational or business data often sits in MySQL or Microsoft SQL Server, and the people who need it want dashboards and alerts without waiting for a report. The supported method is Grafana's core SQL data sources for each database. Grafana queries the database directly at the moment a panel refreshes or an alert rule evaluates, and it does not copy the data into its own store by default. That means dashboards are only as current as the query and the database allow, and every panel refresh or alert evaluation adds load to the database server. The integration does not replace the database's own reporting, does not model or clean the data for you, and does not decide which tables are safe to expose. Those decisions belong to the data owners and the team that runs the database.
The work DeployOpen performs happens inside your infrastructure: your Grafana instance, your network paths to the MySQL or SQL Server hosts, and your database accounts. In practice this means installing and configuring the data source against a database you already run, creating read-only database users with access limited to the schemas and views the dashboards need, and checking that Grafana's outbound connections are allowed through your firewalls and segmentation. Confirm early which MySQL version or SQL Server edition your database runs, which TLS settings your security team requires, and whether a read replica or reporting copy is available for queries. Those answers determine how the data source is configured and how much load your dashboards can place on production.
Before building panels, agree on the boundary of the integration with the database owners. Grafana can run raw SQL or use its query editor, and both send statements to the server, so the account Grafana uses determines what it can read and what it could change if misconfigured. Plan for a dedicated account with SELECT permissions only, and record which database, schema and views it can reach. Also decide who may edit queries in a shared instance, because a query written in the editor is code that runs against your production database on every refresh.
What you need before connecting Grafana to MySQL or SQL Server
Connecting Grafana to a relational database touches four parts of your estate: the Grafana instance and its configuration database, the database engine you query, the network and certificates between them, and the people accountable for the read access. Confirm each one before any dashboard work starts, because a gap in any card tends to surface later as a failed connection or an exposed production database.
Self-hosted Grafana version and configuration database
Confirm which Grafana release you run and where it keeps its own configuration. Grafana stores configuration in SQLite 3 by default, but the installation docs say SQLite does not scale for production, so a production or high availability deployment needs MySQL 8.0 or later or PostgreSQL 12 or later. Check this before adding data sources, because data source definitions and dashboards live in that database. Confirm your release is in an active support window using the upgrade guidance.
Target database engine and version
Confirm the exact MySQL or Microsoft SQL Server versions you will query, and whether each is on a supported track with the vendor. MySQL offers an LTS track and an Innovation track, and Innovation releases are supported only until the next Innovation release. Ask your DBA which version is in production and which migration or patch window is planned, because Grafana queries must be tested against the same version that production uses.
Network paths and firewall rules
Map the route from each Grafana server to the database listener, including load balancers, database proxies and any firewall between subnets or data centers. Grafana nodes in a high availability pair should all reach the same database endpoint. Record the port and the source addresses to allow, and confirm that query traffic from Grafana does not cross a segment that production applications are not permitted to use.
TLS certificates and encryption in transit
Decide whether connections between Grafana and the database use TLS, and which certificate authority signs the database server certificate. Grafana must trust that CA, and the certificate name must match the host name Grafana connects to. Check certificate expiry dates and the renewal owner in advance, since an expired certificate will break dashboards and alert rules at the same time.
Read-only database account and named owner
Create a dedicated database user for Grafana with SELECT rights only on the schemas and views it needs, and no write or administrative privileges. Name one owner who approves the account, tracks its password rotation and reviews which tables it can read. Without a named owner, the account tends to be shared between dashboards, alerting and ad hoc tools, which makes access reviews and incident response harder.
Query load and production impact
Agree with the database owner how much query load Grafana may place on production, including refresh intervals, the number of panels per dashboard and whether alert rules run against the primary or a replica. Dashboards that refresh frequently against large tables can consume more capacity than expected, so ask whether a read replica is available for reporting and alerting workloads.
Configuring the MySQL or SQL Server data source in Grafana
This sequence takes a self-hosted Grafana instance from a locked-down database account to a first working panel built on time series macros. Each step closes with a check so the team knows the connection is sound before dashboards depend on it.
Create a dedicated read-only database user
The database administrator creates a separate login for Grafana, grants it SELECT on only the schemas, tables or views the dashboards need, and avoids write, DDL and administrative privileges. Use one account per database engine and per environment so access can be reviewed and revoked independently. Ask the database team to confirm the grants with a test query that attempts an INSERT and is refused. The step is done when the account can read the intended views and nothing else.
Open the network path from Grafana to the database
The network or platform team allows connections from the Grafana server or container to the database listener, typically on the engine's default port unless your environment uses another. Restrict the source to the Grafana hosts only and confirm any firewall, security group or proxy rules on both sides. Check the path from the Grafana host with a basic client connection before touching Grafana, because a failed data source test later is hard to diagnose. The step is done when a client on the Grafana host connects and authenticates with the new account.
Add the data source in Grafana
An administrator opens Connections, adds the MySQL or Microsoft SQL Server data source, and enters the host, database name and the read-only credentials. Store the password in Grafana's secure fields rather than in plain configuration. Alternatively, define the same settings in a provisioning file so the data source is loaded at startup and reviewed in version control. The step is done when the data source is saved and appears in the list with the correct name and type.
Set connection and TLS options
Set the connection timeout, the maximum open connections and the default database, then configure TLS to match your policy. Confirm with the database team whether the server certificate must be validated against a trusted certificate authority and whether the Grafana host must trust that authority. Avoid disabling certificate verification to make a test pass, since that hides the wrong host or a spoofed endpoint. The step is done when the TLS mode you chose is documented and the connection negotiates encryption as expected.
Run the data source test and a sample query
Select Save and test to confirm Grafana can authenticate and reach the database. Then run a simple query against a known view in Explore, such as a count of rows or the most recent records, and compare the result with the same query run in the database client. Errors about authentication, timeouts or missing privileges point back to the earlier steps. The step is done when the test reports success and the sample query returns the rows you expect.
Build the first time series panel with macros
Create a dashboard panel, switch to the code editor, and write a query that selects a timestamp column and a value. Use the time series macros the data source provides, such as the time filter macro, so the query follows the dashboard time range. Confirm the panel plots points across the selected range and that changing the range changes the returned data. The step is done when the panel renders a time series that matches the database view for the same window.
Review query load on the production database
Ask the database team to watch active sessions and query duration while the panel refreshes at its default interval. Confirm that queries use indexed time columns, that refresh intervals are not shorter than the data needs, and that heavy dashboards point at reporting replicas or summary views where the database offers them. Agree on who can change refresh rates and query limits. The step is done when the database team accepts the observed load for the planned number of panels and users.
Time series macros and visual builder versus raw SQL
The visual query builder lets an editor pick a table, a time column, an aggregation and filters from menus, and Grafana generates the SQL. It suits simple time series panels and gives application owners a path to dashboards without writing SQL. The trade-off is that the builder covers a subset of what SQL can express, so joins, subqueries and database-specific functions usually require the code editor.
- Fast first panels: Pick a table, a value column and an aggregation to chart one metric over time.
- Limited expressiveness: Complex joins, nested logic and vendor-specific functions fall outside what the builder generates.
- Predictable queries: The generated query follows a fixed shape, which makes simple panels easier to review.
- Mode switching: Confirm whether a builder query converts to raw SQL cleanly and whether edits made in code flow back to the builder in your Grafana version.
Before publishing a builder panel to a wide audience, open the query inspector and check the generated SQL against the indexes your database team has defined on the time column.
Raw SQL gives full control over MySQL and Microsoft SQL Server syntax, including common table expressions, window functions and dialect-specific features. It is the usual choice for business dashboards that combine several tables. The cost is that correctness rests on the author: Grafana runs whatever query is written, so time filters, grouping and null handling must be written by hand.
- Full dialect access: Use T-SQL on Microsoft SQL Server and MySQL syntax on MySQL, including features the builder does not generate.
- Author responsibility: A missing time filter returns the full history of a table, which slows the panel and adds load to the source database.
- Version-dependent features: Confirm which functions and syntax your MySQL or SQL Server version supports, especially on the release track you plan to standardize on.
- Reviewable definitions: Keep queries in version-controlled provisioning or dashboard JSON so changes pass through review like other configuration.
Before a raw query goes live, confirm that it returns a bounded result for the widest time range the dashboard allows and that the execution plan uses an index on the time column.
Grafana's SQL data sources expand time macros such as $__timeFilter and $__timeGroup before the query runs, so one panel follows the dashboard time picker. Those macros are only as correct as the time column they reference. The column must hold a date or datetime value that Grafana can compare with the selected range, and the time zone in the database session must match what your users expect. Check macro names and exact behavior in the Grafana data sources documentation for your version.
- `$__timeFilter`: Restricts rows to the dashboard range on the named column, which every time series query needs as its first filter.
- `$__timeGroup`: Buckets rows into intervals for charts, with the bucket size set by the panel width and the query configuration.
- Column type: Integer epoch columns and text timestamps need explicit conversion, and a type mismatch can return empty panels without an error.
- Time zones: Compare the database session time zone with the Grafana server and user settings, since a mismatch moves counts across day boundaries.
Test each panel with a narrow and a wide time range, then compare the totals with a direct query your database team runs against the same range.
Operational dashboards, such as order queue depth or batch job status, usually refresh often over short windows, so they need indexed time filters and small result sets. Business dashboards, such as revenue by region or monthly customer counts, often aggregate large tables and tolerate slower refresh, so they fit summary tables or a read replica better. The query approach should follow that split, and the source database should be chosen with the same logic.
- Refresh frequency: Set short intervals only on panels that hit indexed ranges, and move heavy aggregations to a slower schedule.
- Source choice: Consider a read replica or reporting table for expensive business queries. Your database team must provision and keep these in sync.
- Builder for simple operational panels: Counts and gauges suit the builder, which keeps their queries predictable under frequent refresh.
- Raw SQL for business reporting: Multi-table reports with joins and calculated measures usually need raw SQL and a reviewed metric definition.
Ask your database team which tables have indexes on the time column and whether a replica exists before you set any refresh interval.
Protecting production databases from dashboard query load
Dashboard load on a production database comes from four sources that multiply each other: refresh intervals, panel count, time range and alert evaluation. A dashboard that refreshes often and has many panels sends one query per panel on every refresh, for every open browser tab. Grafana runs panel queries as the data source user, so each viewer's refresh reaches the database. Unbounded time ranges are the worst case, because a $__timeFilter macro with no effective window lets the query scan the full table history. Alert rules add load on their own schedule, since each rule group runs at its evaluation interval whether or not anyone is viewing a dashboard.
Set limits in Grafana first, then confirm them in the database. The min_refresh_interval key in the [dashboards] section of grafana.ini sets the fastest refresh any dashboard can request, so confirm its value and default in your Grafana version before relying on it. In each SQL data source, the query timeout and the connection pool settings (maximum open connections, maximum idle connections and connection lifetime) cap how many concurrent queries one data source can open. Make default time ranges bounded, and review panels to confirm they use $__timeFilter and $__timeGroup. Before go-live, use MySQL Performance Schema or the SQL Server dynamic management views to record the most expensive queries, so you can compare them against the dashboards that issue them.
Test against a read replica or reporting copy wherever one exists. Point a second data source at it, load the dashboards with the intended refresh rate and expected number of viewers, and compare query cost and duration with the primary. Replication lag means replica results can be a little behind, so confirm with the business owners that the dashboards tolerate that delay. If no replica exists, run the same test on a restored copy and agree the change window and monitoring with your database administrators before any production run. Schedule a review after the first month of real use, because dashboards tend to multiply once other teams see them.
Mapping database objects to dashboard panels and alert rules
This table maps the database objects you expose to Grafana (tables, views, timestamp columns, dimensions and business keys) to the panels, variables and alert queries they feed. Read each row as a rule you agree with the database owner before building, and treat the check column as the test that must pass before a dashboard goes to users. Most broken dashboards trace back to a timestamp or key column with the wrong type or no index.
| Source object | Grafana element | Required data type | Check that confirms the mapping |
|---|---|---|---|
| Reporting view over a fact table | Time series panel query, selected as the single source for a dashboard | Read-only view with a stable name and column list | Query returns the expected row count for a known date range, compared with a direct query run by the database owner |
| DATETIME or TIMESTAMP column in MySQL | Time column for $__timeFilter and time series macros | DATETIME or TIMESTAMP, stored in a time zone your team has confirmed | Panel values match a manual aggregation for one hour, with the Grafana time zone and session time zone set the same way |
| DATETIME2 or DATETIME column in SQL Server | Time column for $__timeFilter and $__timeGroup macros | datetime, datetime2 or smalldatetime, with an agreed UTC or local convention | Bucketed totals match a GROUP BY in SQL Server Management Studio for the same window and bucket size |
| Dimension column such as region, product or queue | Series name, group-by value or dashboard variable (query type) | Low-cardinality text or integer with a bounded list of distinct values | Variable dropdown lists the expected values, and the distinct count stays within what the panel can display without clutter |
| Business key such as order ID or account number | Table panel column, drill-down link or alert label | Stable identifier, not free text, that does not change after insert | Sample keys return one row each in the panel, and duplicates are reported by a separate data quality query |
| Status or numeric measure, such as backlog count or error rate | Stat, gauge or threshold input in an alert rule | Integer or decimal, with NULL handling agreed in the query | Alert condition fires on a seeded test value and stays silent on the normal baseline |
| Staging or wide table without an index on the time column | Any panel using the table directly | Index on the time column and any filter columns, or a pre-aggregated view | Query plan or execution time is checked on production-sized data before the panel is shared with users |
Securing the SQL data source connection
The Grafana data source is a direct route from dashboards into a production database, so its account, its secrets and the people allowed to change it deserve the same review as the database itself. The cards below cover the decisions that shape that connection, from the database grants to the query audit trail.
Read-only database account
Create a dedicated account for Grafana that can only read. Grant SELECT on the specific views, reporting schemas or tables the dashboards use, rather than on whole databases. Where possible, expose curated views so that dashboard authors never need to know the underlying table layout. Ask the database team to confirm that the account cannot write, call stored procedures that modify data, or read schemas unrelated to the dashboards.
Credential storage and rotation
Store the database password in Grafana's data source configuration with secrets encryption, not in a dashboard JSON export or a shared document. Provision the data source from files only where the secret comes from a secrets manager or environment variable. Agree a rotation schedule with the database team and confirm that a rotation can be applied without editing every dashboard.
TLS on the database connection
Require encrypted connections between Grafana and the database server. Confirm with the DBA whether the server presents a certificate signed by an internal CA, and whether Grafana must trust that CA and verify the host name. Avoid options that skip certificate verification in production. Test the connection from the Grafana host with the same settings the data source uses, so that a failed handshake is not mistaken for a network fault.
Who can edit data sources and run raw SQL
Changing a data source's host, user or TLS settings changes where Grafana sends queries, so limit that right to a small administrator group. Separately, decide which editors may write raw SQL. Raw SQL can reach any table the account can read, while the visual query builder keeps authors inside a chosen table. Use Grafana's role model and folder permissions to match those decisions, and confirm which of them your edition enforces.
Auditing query access
Grafana records who changed configuration, but the query text and the user who ran a dashboard panel are not always visible on the database side. Enable the database's general or audit logging for the Grafana account where your policy allows it, and use a distinct account name so that Grafana traffic can be filtered. Confirm the retention period and storage location of those logs with your security team before relying on them as evidence.
Hardening the Grafana instance
The database grants protect data, but the Grafana instance decides who reaches the data source screens in the first place. Apply the controls in Grafana's security hardening guidance, including secure cookies and authenticated access to the metrics endpoint, so that a compromised browser session cannot be used to read the data source configuration. Review the result on each Grafana upgrade.
Common MySQL and SQL Server connection and query failures
This table lists the failures teams most often hit when Grafana reads MySQL or Microsoft SQL Server, with the likely cause and the fix for each. Use it as a first-pass checklist before changing database settings or dashboard queries. Most failures trace back to credentials and TLS settings, time zone handling, or query design, so check those first.
| Failure | Likely cause | Fix |
|---|---|---|
| Authentication or login failure | Wrong user, password or host in the data source, or a database user without login rights on the target database | Test the data source in Grafana, then confirm the read-only user can log in from the Grafana server address with a client tool. Check the database name and that the user has been granted access to it. |
| TLS or certificate error | Server requires encrypted connections but the data source has TLS disabled, or the certificate authority or host name does not match | Enable TLS in the data source and install the database CA on the Grafana host. Confirm the host name in the connection matches the certificate subject. Ask your DBA which TLS version the server enforces. |
| Timeouts on large time ranges | Dashboards query full history on unindexed time columns, so a wide range scans millions of rows | Filter on an indexed datetime column using the time macros, narrow the default dashboard range, and ask the DBA to confirm indexes exist on the columns used in WHERE clauses. |
| Time zone mismatch | Database stores UTC or server-local time, while Grafana converts using the browser or server zone, shifting points by hours | Agree one storage time zone with the database owner. Convert in the query when the stored value is not UTC, and set the dashboard time zone explicitly so panels and alerts line up. |
| Datetime type handling | Columns stored as text, epoch integers or mixed types are not recognized as time, so panels show no time axis or empty results | Cast the column to the datetime type the time series format expects, or convert epoch values with the database function for your engine. Test each panel in table format before switching to time series. |
| Missing grants on views | The read-only user can see tables but not the views or underlying schemas that dashboards depend on, returning permission errors only for some panels | Grant SELECT on each view and confirm the user can read the underlying tables if the engine requires it. Re-test every panel after a grant change, since errors often appear only on specific queries. |
| Duplicate alert notifications in high availability | Two or more Grafana servers evaluate the same SQL alert rule and each sends a notification | Follow the alerting high availability configuration in the Grafana docs so only the intended instance sends notifications, and test with a non-critical contact point before relying on it. |
| Slow dashboards and database load | Many panels refresh at short intervals, each running heavy queries against a production primary | Point dashboards at a read replica where available, raise refresh intervals, cache or summarize data in a reporting table, and set query timeouts. Ask the DBA to review the top queries in the database monitoring tools. |
Questions teams ask before connecting Grafana to SQL databases
What drives the cost of connecting Grafana to MySQL or SQL Server?
The cost depends mostly on how many databases, schemas and dashboards are in scope, how clean the existing tables are, and how much of the query logic has to be written from scratch. Most of the work is one-time: installing and hardening Grafana, creating read-only database accounts, writing and reviewing queries, building dashboards and testing alert rules. Recurring costs are the infrastructure that runs Grafana and the database, plus upgrades and any ongoing support. Grafana itself is open source, so the main cost is labor and infrastructure. Ask for a quote that lists each data source, each dashboard group, the alerting scope and who performs the database-side review. DeployOpen provides quotes that follow from a written scope.
How long does a Grafana SQL dashboard project take?
Duration rises with the number of data sources and dashboards, and with how many teams must review the queries. A single database with a few well-understood reporting views is a much smaller job than several MySQL and SQL Server instances feeding operational and finance dashboards with alerts. No researched timeline applies to this topic, so the honest answer is to ask for a schedule tied to the written scope. Ask the provider to break the schedule into access setup, a test environment, query and dashboard build, alert testing and handover. Timelines that do not name these phases are hard to check.
What do we need to provide before the work starts?
Plan to provide four things before work starts: read access to the target databases through dedicated accounts, a named owner for each database and each dashboard group, a test environment that mirrors the production schema, and a decision on where Grafana will run. Read-only database users are the baseline, so the database team must be willing to create them and approve the grants. Owners answer questions about business meaning, such as which status values count as closed. A test environment lets queries be tuned without loading production. Ask the provider to list these inputs in the scope document so gaps surface early.
Can our internal team connect Grafana to SQL databases without a partner?
Yes, a capable internal team can do this, especially if it already runs Grafana or a database platform. The work involves skills in three areas: Grafana administration and provisioning, SQL and database security, and dashboard design for operational audiences. The main risks for an internal-only effort are unreviewed queries that load production, over-privileged database accounts and alert rules that fire on data nobody owns. Teams that choose to do it alone should set a test environment, use read-only accounts and document each query. A partner is most useful when the team lacks one of these skills or wants a fixed scope delivered on a known schedule.
Can Grafana alert on the results of SQL queries?
Yes. Grafana's core SQL data sources, including Microsoft SQL Server and MySQL, are documented in the Grafana data sources guide as supporting queries that can drive alerting, so an alert rule can evaluate a query result and notify a team when a threshold is crossed. Before relying on it, confirm the data source version and the alerting behavior in your Grafana release, and test each rule against known data. Keep alert queries light, because they run on a schedule against the database. Also plan for notification routing, silences and high availability. Grafana documents extra configuration for high availability alerting so that notifications are not duplicated.
How do we keep SQL queries from overloading production databases?
Limit what Grafana can run and how often. Create a dedicated read-only account for each data source, grant access only to the views or tables the dashboards need, and avoid giving Grafana rights to write or call administrative procedures. Use time range filters and aggregation in the query rather than pulling raw rows. Set dashboard refresh intervals with care, because each open panel can trigger a query. Point heavy reports at a read replica or reporting copy when the database team allows it. Test each query in a non-production environment and review the execution plan before it goes live.
Does the security model for SQL access need review?
Yes. Database credentials stored in Grafana are sensitive, so review how they are stored and who can edit data sources. Grafana users with edit rights to a data source may be able to change its connection details, so limit that role. Use least-privilege database accounts, encrypted connections where the database supports them, and a documented process for rotating passwords. Consider which dashboards show personal or regulated data and restrict them accordingly. Access control features differ between open source and Enterprise editions, so confirm which controls your deployment needs before the build starts.
How DeployOpen scopes and delivers this integration
Every engagement starts with a written scope that names the data sources, databases and dashboards in play before any work begins. For a MySQL or Microsoft SQL Server integration, that scope lists each database instance, the schemas and tables or views each dashboard reads, the Grafana version and editions in use, the read-only database accounts to be created, the target hosts for the Grafana server and its network paths to the databases, and the alert rules that will run against SQL results. Most engagements are fixed-scope, so deliverables and timelines are agreed in writing first. Ask for the scope to state which items are out of scope, such as building dashboards for business questions you have not yet defined, changes to the database schema, or tuning of the database server itself.
The deliverables usually include the data source definitions, the provisioning files or as-code configuration that recreate them, the dashboards and their query reviews, the alert rules with their notification routing, and a short record of the database accounts and their granted permissions. Confirm with DeployOpen which of these will be stored in your Git repository and which will live only in the Grafana instance, because provisioning files are what let you rebuild the setup after an upgrade or a restore. Documentation and handover should cover where each credential is stored, how the query load was measured against production, and how to add a new dashboard without granting broader database rights.
Ongoing work after handover is optional and can be covered by a retainer. A retainer can include Grafana patching, checks on database driver and engine version compatibility, review of new queries before they reach production, and rotation of the database passwords used by Grafana. Ask for the retainer terms in writing, including response expectations, what is covered for Grafana upgrades, and what is billed as separate project work. DeployOpen does not publish a price list, so the quote follows from the written scope, and you should compare any retainer against your own team's capacity to keep these queries and accounts current.

