vitessio/vitess · error

no read_only variable in mysql

Error message

no read_only variable in mysql

What it means

IsReadOnly runs "SHOW VARIABLES LIKE 'read_only'" via FetchSuperQuery and requires exactly one row. If no row comes back, mysqld is unreachable or the variable is missing, and this error is returned (with true as the conservative read-only answer). It signals the server state could not be determined, not that the server is genuinely read-only.

Source

Thrown at go/vt/mysqlctl/replication.go:822

	finalRes := make(map[string]string, len(qr.Rows))
	for _, row := range qr.Rows {
		if len(row) != 2 {
			return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "incorrect number of fields in the row")
		}
		finalRes[row[0].ToString()] = row[1].ToString()
	}
	return finalRes, nil
}

// IsReadOnly return true if the instance is read only
func (mysqld *Mysqld) IsReadOnly(ctx context.Context) (bool, error) {
	qr, err := mysqld.FetchSuperQuery(ctx, "SHOW VARIABLES LIKE 'read_only'")
	if err != nil {
		return true, err
	}
	if len(qr.Rows) != 1 {
		return true, errors.New("no read_only variable in mysql")
	}
	if qr.Rows[0][1].ToString() == "ON" {
		return true, nil
	}
	return false, nil
}

// IsSuperReadOnly return true if the instance is super read only
func (mysqld *Mysqld) IsSuperReadOnly(ctx context.Context) (bool, error) {
	qr, err := mysqld.FetchSuperQuery(ctx, "SELECT @@global.super_read_only")
	if err != nil {
		return false, err
	}

	if len(qr.Rows) == 1 {
		sro := qr.Rows[0][0].ToString()
		if sro == "1" || sro == "ON" {
			return true, nil

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check mysqld process status and connectivity before calling IsReadOnly.
  2. Confirm the DBA/super-user credentials used by FetchSuperQuery are valid — auth failures often surface as missing rows.
  3. Treat the returned bool=true plus this error as 'unknown', and retry or fall back to process-level checks rather than assuming read-only state.
  4. If truly running a server without read_only, upgrade to a standard MySQL build.
Defensive patterns

Strategy: retry

Try / catch

readOnly, err := mysqld.IsReadOnly(ctx)
if err != nil {
    if strings.Contains(err.Error(), "no read_only variable") {
        // server unreachable: treat as unknown, bounded retry
        return retryOrFallback(err)
    }
    return vterrors.Wrapf(err, "checking read_only")
}

Prevention

When it happens

Trigger: Calling Mysqld.IsReadOnly when SHOW VARIABLES LIKE 'read_only' returns len(qr.Rows) != 1 — usually because mysqld is down or the DBA connection cannot be established, so the expected single row is missing.

Common situations: Tablet health checks during mysqld restart/maintenance windows; super-user connection failures (FetchSuperQuery needs sufficient privileges); nonstandard MySQL builds lacking the read_only variable.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/d2af9c63e0ad54e0. Report an issue: GitHub.