Using MySQL Shell for Efficient Cluster Administration

How to Use MySQL Shell to Script Cluster Administration

MySQL Shell (mysqlsh) is more than an interactive client. It provides scripting APIs for managing InnoDB clusters, allowing you to automate deployment, maintenance and troubleshooting with repeatable scripts instead of ad‑hoc commands.

This article walks through practical ways to use MySQL Shell for cluster administration, focusing on InnoDB Cluster / Group Replication environments.

1. Why script cluster administration?

Manual cluster management does not scale. Scripting with MySQL Shell helps you:

  • Standardise cluster creation and reconfiguration.
  • Reduce human error during failovers and maintenance.
  • Embed safety checks before running disruptive operations.
  • Integrate MySQL operations into CI/CD and infrastructure-as-code workflows.

At a high level, you move from:

┌─────────────────────────────────────┐
│ Manual steps (docs / runbooks)     │
└─────────────────────────────────────┘
                ↓
┌─────────────────────────────────────┐
│ Reviewed, version-controlled scripts│
└─────────────────────────────────────┘

2. MySQL Shell basics for scripting

2.1 Installing MySQL Shell on RHEL/Rocky Linux

On RHEL/Rocky Linux, install mysql-shell from the MySQL Yum repository or your distribution if available. Example with an enabled MySQL repo:

sudo dnf install -y mysql-shell

Verify:

mysqlsh --version

2.2 Choosing a language: JavaScript vs Python

MySQL Shell supports JavaScript (default) and Python. The cluster APIs are functionally equivalent in both. Choose based on team preference:

  • JavaScript mode: mysqlsh --js
  • Python mode: mysqlsh --py

Switch inside the shell:

\\js
\\py

This article uses JavaScript examples; Python is similar with minor syntax differences.

2.3 Running scripts non-interactively

To execute a script file:

mysqlsh --js -f /opt/mysql/scripts/create_cluster.js

Or pass commands via -e:

mysqlsh --js -e "shell.connect('root@db1:3306'); ..."

For production automation, prefer script files under version control rather than long inline commands.

3. Connecting and working with sessions

3.1 Safe connection patterns

A typical pattern:

shell.connect('admin@db1:3306')
var dba = require('dba')

Avoid embedding passwords in scripts. Use:

  • Interactive password prompts.
  • Option files (e.g. ~/.my.cnf) with restricted permissions.
  • Environment variables or secret managers, then read them inside the script.

3.2 Checking instance state before acting

Always verify that an instance is suitable for cluster operations. Example:

var dba = require('dba')

var info = dba.checkInstanceConfiguration('admin@db1:3306')
print(info.exitState)  // should be 'ok'

Use these checks in scripts to fail fast when prerequisites are not met.

4. Scripting cluster creation

Assume three instances:

db1:3306  (planned primary)
db2:3306
db3:3306

Minimal JavaScript script to create and populate an InnoDB cluster:

// file: create_cluster.js

var dba = require('dba')

// 1. Connect to the first instance
shell.connect('admin@db1:3306')

// 2. Validate configuration
var check = dba.checkInstanceConfiguration('admin@db1:3306')
if (check.exitState != 'ok') {
  print('Instance db1 is not correctly configured: ' + check.exitState)
  shell.exit(1)
}

// 3. Create the cluster
var cluster = dba.createCluster('prod_cluster')

// 4. Add additional instances
var instances = ['admin@db2:3306', 'admin@db3:3306']

instances.forEach(function (uri) {
  var r = dba.checkInstanceConfiguration(uri)
  if (r.exitState != 'ok') {
    print('Skipping ' + uri + ' due to configuration issues')
  } else {
    cluster.addInstance(uri)
  }
})

// 5. Show status
cluster.status()

Run:

mysqlsh --js -f create_cluster.js

Best practices:

  • Use dba.checkInstanceConfiguration() before createCluster() or addInstance().
  • Fail with a clear message if checks are not ok.
  • Keep cluster name and instance list configurable (e.g. via environment variables or a JSON config file).

5. Automating common administration tasks

5.1 Checking cluster health

A small script to print concise health information:

// file: cluster_health.js

var dba = require('dba')

shell.connect('admin@db1:3306')
var cluster = dba.getCluster('prod_cluster')

var status = cluster.status({extended: 0})

print('Cluster name: ' + status['clusterName'])
print('Default primary: ' + status['defaultReplicaSet']['primary'])

status['defaultReplicaSet']['topology'].forEach(function (instance) {
  print(instance['address'] + ' - ' + instance['status'] +
        ' - ' + instance['mode'])
})

This can be run by monitoring systems or cron to expose simple health information.

5.2 Adding a new instance

Adding instances is a common task that benefits from scripting. Example:

// file: add_instance.js

if (shell.argv.length < 1) {
  print('Usage: mysqlsh --js add_instance.js <user@host:port>')
  shell.exit(1)
}

var dba = require('dba')
var newInstance = shell.argv[0]

shell.connect('admin@db1:3306')
var cluster = dba.getCluster('prod_cluster')

var check = dba.checkInstanceConfiguration(newInstance)
if (check.exitState != 'ok') {
  print('Instance not suitable: ' + check.exitState)
  shell.exit(1)
}

cluster.addInstance(newInstance, {recoveryMethod: 'clone'})
cluster.status()

Notes:

  • Use recoveryMethod: 'clone' when you want automatic provisioning of data.
  • Ensure network and disk capacity are sufficient for a clone operation.

5.3 Planned switchover of primary

For maintenance on the current primary, script a controlled switchover:

// file: switchover.js

if (shell.argv.length < 1) {
  print('Usage: mysqlsh --js switchover.js <targetPrimary>')
  shell.exit(1)
}

var target = shell.argv[0]  // e.g. 'db2:3306'

var dba = require('dba')

shell.connect('admin@db1:3306')
var cluster = dba.getCluster('prod_cluster')

var status = cluster.status({extended: 0})
var currentPrimary = status['defaultReplicaSet']['primary']

if (currentPrimary == target) {
  print('Target is already primary: ' + target)
  shell.exit(0)
}

print('Current primary: ' + currentPrimary)
print('Requested primary: ' + target)

cluster.setPrimaryInstance(target)
cluster.status()

Before running this in production, ensure your application can handle a brief primary switch and that your connection layer (e.g. routers, proxies) will follow the new primary.

6. Recovery and troubleshooting scripting

6.1 Rejoining an instance

When a node falls out of the cluster, you can script rejoin attempts:

// file: rejoin_instance.js

if (shell.argv.length < 1) {
  print('Usage: mysqlsh --js rejoin_instance.js <host:port>')
  shell.exit(1)
}

var target = shell.argv[0]
var dba = require('dba')

shell.connect('admin@db1:3306')
var cluster = dba.getCluster('prod_cluster')

try {
  cluster.rejoinInstance(target)
  print('Rejoin requested for ' + target)
} catch (e) {
  print('Failed to rejoin ' + target + ': ' + e)
  shell.exit(1)
}

cluster.status()

Use this as part of a runbook, not as an automatic endless loop; a repeatedly failing rejoin indicates underlying issues that need investigation.

6.2 Detecting quorum and topology issues

A script can quickly show you where problems are:

// file: cluster_quorum.js

var dba = require('dba')

shell.connect('admin@db1:3306')
var cluster = dba.getCluster('prod_cluster')
var status = cluster.status({extended: 0})

var rs = status['defaultReplicaSet']

print('Primary: ' + rs['primary'])
print('Number of instances: ' + rs['topology'].length)

rs['topology'].forEach(function (inst) {
  print(inst['address'] + ' | status=' + inst['status'] +
        ' | mode=' + inst['mode'])
})

Integrate this with your logging or alerting pipeline to capture snapshots during incidents.

7. Structuring scripts and configuration

To keep scripts maintainable:

  • Store scripts in a dedicated repository, e.g. infra/mysql-shell-scripts/.
  • Use one script per operation (create, add, remove, switchover, health check).
  • Externalise cluster names, instance URIs and credentials into config files or environment variables.
  • Log key actions and decisions to stdout so automation tools can parse them.

Example directory layout:

infra/mysql-shell-scripts/
  config/
    prod.json
    staging.json
  scripts/
    create_cluster.js
    add_instance.js
    switchover.js
    cluster_health.js

8. Operational best practices

  • Always run scripts against a staging cluster first.
  • Prefer idempotent scripts (safe to re-run) where possible.
  • Add explicit confirmation steps for disruptive actions when running interactively.
  • Document each script: purpose, expected inputs, preconditions, and rollback steps.
  • Combine MySQL Shell scripts with configuration management tools (Ansible, etc.) for full-stack automation.

9. Conclusion

MySQL Shell turns InnoDB cluster administration into a scriptable, testable workflow instead of a manual art. By using the built-in dba APIs, validating instance state before changes, and structuring your scripts with clear inputs and safety checks, you can standardise cluster creation, maintenance and recovery. Start by scripting read-only operations like health checks, then gradually automate more complex tasks such as adding instances and planned switchovers.

This article offers general technical guidance. Validate all configurations in a safe environment before applying them to production.

Smart reads for curious minds

We don’t spam! Read more in our privacy policy