Watchlog DocsWatchlog Docs
Home
Get Started
Gen AI Monitoring
Integrations
Log Watchlist
Home
Get Started
Gen AI Monitoring
Integrations
Log Watchlist
  • All Integrations
  • NGINX

    • Nginx Integration
    • Connect NGINX to Watchlog
    • Docker
    • Windows
    • Kubernetes
    • Source Code
  • IIS

    • IIS Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • REDIS

    • Redis Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • POSTGRESQL

    • PostgreSQL Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • MONGODB

    • MongoDB Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • MYSQL

    • MySQL Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • PM2

    • PM2 Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • DOCKER

    • Docker Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code
  • GITLAB

    • Gitlab Integration
    • Ubuntu
    • Docker
    • Windows
    • Kubernetes
    • Source
  • ELASTICSEARCH

    • Elasticsearch Integration
    • Ubuntu
    • Docker Container
    • Windows
    • Kubernetes
    • Source Code

MySQL Integration

Monitor MySQL query performance, connection pressure, InnoDB internals, schema growth, index usage, lock contention and replication health from a single Watchlog agent.

Works with MySQL and MariaDB. The agent detects which one it is talking to and adapts — the two diverge on replication statements and lock tables, and version detection handles that rather than assuming.

Supported Platforms

  • Ubuntu
  • Windows
  • Source Code
  • Docker Container
  • Kubernetes

Supported Versions

VersionStatus
MySQL 8.0+Fully supported — performance_schema.data_locks gives the richest lock detail
MySQL 5.7Supported — locks come from information_schema.innodb_lock_waits instead
MariaDB 10.xSupported — never adopted data_locks or the 8.0.22 replica terminology, both handled

Version differences are detected, not assumed. Two boundaries matter:

  • MySQL 8.0 introduced performance_schema.data_locks / data_lock_waits. Below that (and on all MariaDB) the agent reads information_schema.innodb_lock_waits.
  • MySQL 8.0.22 renamed the replication statements (SHOW REPLICA STATUS). MariaDB kept the old terminology permanently.

Required Privileges

CREATE USER 'watchlog_monitor'@'%' IDENTIFIED BY 'your_password';

GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'watchlog_monitor'@'%';
GRANT SELECT ON performance_schema.* TO 'watchlog_monitor'@'%';
GRANT SELECT ON information_schema.* TO 'watchlog_monitor'@'%';

FLUSH PRIVILEGES;

No SUPER, no ALL PRIVILEGES, and no access to your application data — the agent never reads a row from a user table.

What each grant buys:

GrantEnablesWithout it
PROCESSSHOW GLOBAL STATUS, SHOW ENGINE INNODB STATUS, thread countsThe integration cannot report
SELECT on performance_schemaQuery digests, index statistics, lock waitsThose three tabs are hidden
SELECT on information_schemaSchema and table sizesNo storage detail
REPLICATION CLIENTSHOW REPLICA STATUSNo replication tab

A missing grant disables that section only. The integration stays connected.

Capability Detection

Several features depend on server configuration rather than privileges, and are probed rather than assumed:

CapabilityRequires
performanceSchemaperformance_schema = ON — off by default on some distributions
queryDigestThe statement digest consumer enabled and SELECT on performance_schema
indexStatstable_io_waits_summary_by_index_usage readable
locksMySQL 8 data_lock_waits, or 5.7/MariaDB innodb_lock_waits
binloglog_bin = ON
slowQueryLogslow_query_log = ON

When performance_schema is off, the Queries, Indexes and Locks tabs are hidden and a capability note explains why — rather than showing three empty tabs.

SHOW VARIABLES LIKE 'performance_schema';

Turning it on requires a restart and costs a few percent of memory. It is what makes query-level analysis possible.

What Watchlog Collects

Server Version and flavour, uptime, connections against max_connections, running and cached threads, aborted clients and connects, questions and slow-query counters, open tables against table_open_cache, and temporary tables created on disk.

Queries (needs performance_schema) Per normalized digest: executions, total and average latency, rows examined against rows sent, temporary tables, sorts, and full-scan counts — ranked by impact (executions × average latency), which is the database time actually consumed. That ordering surfaces a 2 ms query running 50 000 times ahead of one 4-second report; sorting by average hides it.

InnoDB Buffer pool size, usage and hit rate, dirty page percentage, log waits, row lock waits and average wait time, pending IO, and deadlock counts.

Schemas and tables Per schema: table count, data and index size. Per table: rows, data length, index length, average row length and engine. System schemas (mysql, sys, information_schema, performance_schema) are excluded everywhere — they would otherwise dominate every "largest table" list.

Indexes (needs performance_schema) Per index: reads, writes and usage, with unused candidates flagged. An unused index is reads = 0 — not reads = 0 && writes = 0, which would exclude every index on a write-heavy table. UNIQUE and PRIMARY indexes are never proposed for removal; they enforce correctness regardless of scan count.

Locks Blocking and waiting transactions with the statements involved, plus deadlock counts.

Replication Role, IO and SQL thread state, seconds behind source, relay log position, and the last error.

Health Score and Insights

A 0–100 score computed server-side, with a written reason on every deduction:

SignalJudged on
Connection pressureThreads connected against max_connections
Running threadsConcurrency actually executing, not merely connected
Query latencyWorst per-interval average across tracked digests
Buffer poolHit rate, judged only once enough reads happened to be meaningful
Dirty pagesShare of the buffer pool awaiting flush
InnoDB log waitsWrites that stalled waiting for log space
Table cacheTable open rate against table_open_cache
Disk temp tablesTemporary tables that spilled to disk
Lock waits, deadlocksActive waits and deadlock events
ReplicationStopped threads, last error, and seconds behind

A number is not a verdict. A low buffer pool hit rate over 200 reads means nothing; the score requires volume before it judges.

Slow Queries

Watchlog does not read the MySQL slow query log file. It uses performance_schema.events_statements_summary_by_digest, which gives the same information without the file, without a threshold to configure, and without the write cost.

slowQuery.thresholdMs (default 100) only decides what the dashboard calls slow. The agent, the API and the UI all use that one number so they cannot disagree.

Query text is normalized by MySQL itself before Watchlog ever sees it — the digest text has literals replaced with ?. Parameter values never leave your host.

Tips

performance_schema timings are picoseconds. Watchlog converts them; if you compare raw values with what the dashboard shows, divide by 1e9 for milliseconds.

Collection Intervals

SectionInterval
Status, connections, InnoDB, queries, locks, replicationevery collection cycle (60s)
Schema and table sizes300s
Index statistics300s

Safety

Watchlog is read-only. It never runs any of the following:

ANALYZE TABLE · OPTIMIZE TABLE · ALTER TABLE · KILL · FLUSH TABLES · SET GLOBAL · DROP of anything · any write to any table

There are no full table scans for monitoring, and every monitoring statement carries a timeout so it can never be the thing that hangs a busy server.

Advanced Options

{
  "service": "mysql",
  "monitor": true,
  "host": "localhost",
  "port": "3306",
  "username": "watchlog_monitor",
  "password": "your_password",
  "database": [],
  "ssl": false,

  "advanced": {
    "enabled": true,
    "queries": true,
    "schema": true,
    "indexes": true,
    "locks": true,
    "replication": true,
    "maxDigests": 200,
    "maxTables": 300,
    "maxIndexes": 500,
    "maxLockWaits": 50,
    "schemaIntervalSeconds": 300,
    "indexIntervalSeconds": 300
  },

  "slowQuery": {
    "thresholdMs": 100
  }
}
FieldDefaultPurpose
database[]Only the legacy collector needs this. The advanced collector discovers schemas itself.
sslfalseTLS to the server
advanced.maxDigests200Query shapes tracked per scrape, ranked by impact
advanced.maxTables300Tables per scrape, largest first
advanced.maxLockWaits50Lock-wait pairs captured
slowQuery.thresholdMs100What counts as slow, consistently across agent, API and UI

Multiple Instances

Add one entry per instance. Each is identified by its host:port:

[
  {
    "service": "mysql",
    "monitor": true,
    "host": "127.0.0.1",
    "port": "3306",
    "username": "watchlog_monitor",
    "password": "your_password"
  },
  {
    "service": "mysql",
    "monitor": true,
    "host": "127.0.0.1",
    "port": "3307",
    "username": "watchlog_monitor",
    "password": "your_password"
  }
]

Troubleshooting

SymptomCause
Queries, Indexes and Locks tabs missingperformance_schema is off, or the user lacks SELECT on it
Queries tab empty but the others workThe statement digest consumer is disabled
Replication tab missingNo REPLICATION CLIENT grant, or the server is not a replica
Access denied on connectThe user's host pattern does not match where the agent connects from — 'watchlog_monitor'@'%' vs @'localhost'
Table sizes look staleThey refresh every 300s by design
Deadlock count always zeroMySQL exposes cumulative deadlocks only via SHOW ENGINE INNODB STATUS; MariaDB has an Innodb_deadlocks status variable. Both are handled, but the value differs in meaning.
Last Updated:: 8/13/26, 12:54 AM
Contributors: mohammad
Next
Ubuntu