
Azure Database for MySQLAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Microsoft Azure · Databases · Managed MySQL
MySQL without the server chores. The flexible server runs community MySQL for you: you pick a version and a size, decide whether it sits inside your virtual network, and Azure looks after patching, backups and failover. Web applications built on WordPress, Laravel, Django or Java frameworks often land here. The version needs attention, because older MySQL releases go out of standard support and then cost extra.
On this page (17 sections)
Mind map: Azure Database for MySQL at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- Community MySQLIt’s MySQL, so applications, drivers and tools that speak MySQL work as they do elsewhere. That includes the frameworks and content systems that default to it.
- Current versionsMySQL 8.0 and 8.4 are the supported versions. 5.7 has reached the end of community support and can only be kept on paid extended support while you plan the upgrade.
- Three compute tiersBurstable for development and light use, General Purpose for most production applications, and Business Critical for heavier, memory-hungry workloads.
- High availabilityTurn on same-zone or zone-redundant high availability and Azure keeps a synchronised standby that takes over if the primary fails. It isn’t available on the Burstable tier, and the zone-redundant option is chosen when the server is created.
- Backups and point-in-time restoreBackups run on a schedule and are kept for up to 35 days. A restore creates a new server at the moment you choose.
- Read replicasUp to ten replicas copy the data asynchronously, in the same Region or another, to serve reads or to act as a disaster recovery copy.
- I/O you can raise separatelyYou can buy more IOPS without buying more storage, and let the server scale IOPS automatically, which helps with bursts of traffic.
- Private by designPrivate access places the server inside your virtual network. Connections use TLS 1.2 by default, and Microsoft Entra sign-in can replace stored passwords.
Basic concepts
- Flexible server
- Microsoft’s present-day packaging of the service. Single Server, its predecessor, has gone.
- Compute tier and SKU
- Burstable, General Purpose or Business Critical, plus a size such as Standard_D2ds_v4. It decides vCores, memory and the connection limit.
- Storage and IOPS
- A provisioned disk that can grow but not shrink. The server includes some IOPS with the storage, and you can add more.
- High availability
- A standby in the same zone or in another zone, kept in step with the primary. It doesn’t answer queries.
- Read replica
- An asynchronous, read-only copy that can be promoted to a stand-alone server.
- Private access
- A private address inside a subnet you set aside in your own network. Applications find it by name through a private DNS zone.
- Public access
- An internet-facing name guarded by a list of the addresses that are allowed in.
- Server parameter
- A MySQL setting, such as max_connections or require_secure_transport. Some need a restart.
- lower_case_table_names
- A setting that decides whether table names are case sensitive. It can only be chosen when the server is created.
- Extended support
- A paid arrangement that keeps an out-of-support MySQL version patched while you migrate.
- Microsoft Entra authentication
- Sign-in with an Entra identity and a short-lived token. It needs a user-assigned managed identity on the server and an Entra administrator.
- Point-in-time restore
- Builds a new server from the backups and logs at a chosen moment, leaving the original untouched.
- Maintenance window
- The monthly period you pick for patches that restart the server.
- Geo-redundant backup
- A copy of backups in the paired Region, set when the server is created.
How to create & configure it
Set up a private MySQL server through the Azure portal
- Pick the Region and the network modeDecide where the server lives and how it’s reached. Central India suits many Indian teams. Private or public access is locked in when you create the server, and private access wants a virtual network in the same Region.
- Start the wizardFind Azure Database for MySQL flexible servers in the portal and press Create. Fill in the subscription, resource group and a server name nobody else uses, and take MySQL 8.4 or 8.0 rather than 5.7.
- Choose the workload sizeUse the Development preset for a small Burstable server, or General Purpose for production. Start with two or four vCores and resize from measurements.
- Turn on high availability if it’s productionChoose zone-redundant (or same-zone if the Region has no zones). It roughly doubles compute and storage cost, and it isn’t offered on Burstable. Zone-redundant HA has to be chosen now.
- Set the storage and IOPSPick the storage size, tick autogrow, and look at the IOPS included. Raise IOPS separately later if monitoring shows I/O is the limit.
- Choose authenticationCreate the administrator account for MySQL authentication, and plan to add Microsoft Entra authentication so applications don’t use stored passwords. Entra sign-in needs a user-assigned managed identity.
- Choose private accessUnder Networking choose Private access, then point it at a virtual network, a subnet reserved for the service and a private DNS zone. Should you need public access instead, allow named addresses and nothing wider.
- Set backups and the table-name settingChoose the backup retention, geo-redundant backup if needed, and the case-sensitivity of table names, which can’t be changed afterwards.
- Connect and testConnect from inside the network over TLS, create an application user with limited privileges, load a little data and test a point-in-time restore before you rely on the backups.
Tip: the wizard is a fine way to look around. For real environments define the server as code (the Azure CLI, Bicep or Terraform, see the code references), because several settings, such as network mode, zone-redundant HA and lower_case_table_names, can’t be changed afterwards.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| ERROR 2003 or a timeout when connecting | The firewall, route or DNS doesn’t match the server’s network mode | Public servers need your address on the firewall list. Private ones can only be reached from the virtual network (or one peered with it), and the private DNS zone must be linked to that network. |
| ERROR 3159: connections using insecure transport are prohibited | TLS is required and the client didn’t use it | Connect with SSL on and the CA certificate, and leave require_secure_transport switched on. |
| Access denied for user with an Entra token | The token expired, the identity isn’t a database user, or the client doesn’t use the clear-text plugin over TLS | Fetch a fresh token just before connecting, make sure the Entra user exists on the server, and enable the mysql_clear_password plugin in the client while using TLS. |
| Too many connections | More clients than max_connections, which scales with memory | Pool connections in the application, close idle ones, look for connection leaks, and resize only if load is real. |
| ERROR 1227: you need the SUPER privilege when importing a dump | The dump contains DEFINER clauses or statements that need privileges the managed service doesn’t give | Remove or rewrite the DEFINER clauses, and set log_bin_trust_function_creators where the documentation allows it for functions and triggers. |
| Table names behave differently from your laptop | lower_case_table_names was set differently at creation | Check the setting on both sides before you migrate. It can only be changed by creating a new server. |
| The server went read-only | The disk filled while autogrow was switched off | Add storage (there’s no way back down), work out what grew, then turn autogrow on and alert on usage. |
| Slow queries after moving from another host | Different configuration, missing indexes or a smaller instance | Compare server parameters, check the slow query log and EXPLAIN output, add the indexes that are missing, and size from measurement. |
| A stopped server started again | Azure restarts a stopped server after the maximum stop period | Plan for the automatic restart, and use automation to stop dev servers again. Storage keeps billing while stopped. |
| Replica lag grows | Write bursts, or a replica sized below the primary | Match the replica’s size to the primary, look for long transactions and check the lag metric. |
| Unexpected "extended support" charges | The server runs a MySQL version that is past standard support | Upgrade in place to 8.0, then to 8.4, after testing on a restored copy. |
Use cases: when and where to use it
Good fit
- Web applications and content systems (WordPress, Laravel, Drupal, Django) that expect MySQL
- Lifting a MySQL database off your own VM with little change to the application
- Multi-tier applications that already use Azure networking and Entra ID
- Read-heavy sites that benefit from read replicas
- Non-production servers that sit stopped overnight and at weekends
- SaaS back ends that need a familiar relational engine with built-in high availability
Consider something else
- Anything written for SQL Server → Azure SQL Database, or Managed Instance when it needs server-level features
- Applications built on PostgreSQL → Azure Database for PostgreSQL
- Document, key-value or globally distributed data → Azure Cosmos DB
- Large-scale analytics on big tables → a warehouse or lakehouse, not an OLTP database
- The same job on other clouds → compare Amazon RDS for MySQL and Cloud SQL for MySQL
Pros: why consider it?
Why teams choose it
- Community MySQL, so existing applications and tools usually work unchanged
- High availability and point-in-time restore are settings rather than projects
- Read replicas, extra IOPS and autogrow give room to scale
- Private networking and Entra ID slot into an existing Azure setup
- A stopped server pays no compute, which suits part-time environments
- Free-account offers have included a small server for a year, which makes it good for learning
Trade-offs to weigh
- Network mode, zone-redundant HA and table-name case-sensitivity are fixed at creation
- No SUPER privilege, so dumps with DEFINER clauses and some admin tricks need rework
- High availability isn’t available on the Burstable tier
- Storage can’t be shrunk
- Old versions cost extra on extended support, and the upgrade path needs testing
- Entra authentication needs extra setup, including a managed identity
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| Firewall rules that let in too much | High | Open firewall ranges expose MySQL to scans and password guessing. | Prefer private access. If public is unavoidable, list specific addresses and require TLS. |
| One high-privilege login shared by every app | High | One high-privilege password in config files is hard to rotate and easy to leak. | Create least-privilege users per application, use Entra sign-in where possible, and keep remaining secrets in Key Vault. |
| Untested restore | High | Nobody knows the real recovery time, or whether the restored data is complete. | Run a restore into a scratch server every so often, check what came back and measure how long it took. |
| No high availability in production | Medium | A zone or host problem becomes an outage. | Use zone-redundant or same-zone HA on General Purpose or Business Critical, and test a failover. |
| Running an out-of-support version | Medium | MySQL 5.7 gets fixes only through paid extended support. | Plan the move to 8.0 and 8.4, and test on a restored copy first. |
| Choosing a setting you can’t change | Medium | Network mode, zone redundancy and table-name case-sensitivity are fixed once the server exists. | Decide in a design review and encode them in templates. |
| Disk full | Medium | The server turns read-only, and the disk can’t be reduced. | Turn autogrow on, alert on free space and review which tables grow fastest. |
| Over-privileged application users | Low–Med | An app user with ALL PRIVILEGES can drop tables as easily as read them. | Grant only the needed privileges on the application’s schema. |
| Forgotten replicas and test servers | Low–Med | Each one keeps charging for compute and storage until someone deletes it. | Label each with an owner and a delete-by date, and remove it when the work is done. |
Performance optimisation
- Let monitoring set the size: watch CPU, memory, IOPS and open connections, and leave Burstable once credits keep running out.
- Raise IOPS separately, or let the server scale it, when I/O is the limit, instead of buying more storage you don’t need.
- Use connection pooling in the application or framework, since max_connections depends on memory.
- Send read traffic to replicas, and watch lag, so reports don’t compete with writes.
- Use the slow query log and EXPLAIN to find missing indexes, and fix queries before scaling up.
- Keep the InnoDB buffer pool warm and large enough for the working set by choosing a tier with enough memory.
- Keep transactions short and avoid long-running idle ones that hold locks.
- Run the web tier in the same Region and zone as the database to cut round-trip time.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Azure Database for MySQL.
- Stop non-production servers overnight and at weekends. Compute charges pause, storage keeps billing, and Azure turns a stopped server back on after the maximum stop period.
- Run dev, test and small sites on Burstable, and production on General Purpose.
- Skip high availability outside production, where it would roughly double the bill.
- Consider reserved capacity for servers that are sure to run for a year or longer.
- Keep backup retention in line with recovery needs: backup space up to the size of your storage costs nothing, and anything beyond that is billed.
- Don’t over-provision IOPS. Pay for more only after metrics show I/O is the bottleneck, and consider autoscaling IOPS.
- Remove replicas and restore-test servers once the exercise is over.
- Upgrade off MySQL 5.7 before extended support fees start to matter.
- Tag servers with owner and environment, then set budgets and alerts in Cost Management.
- Check whether your free account includes a small MySQL server for your first year.
Figures and offers on this page illustrate what Microsoft's public pages say today. Tier, size, Region and time change them, so check the live figures first (see Pricing).
Security optimisation
- Choose private access, or a private endpoint, and keep any public firewall rules to specific addresses.
- Keep TLS required (require_secure_transport on, TLS 1.2 or newer) and have clients verify the server certificate.
- Turn on Microsoft Entra authentication with a user-assigned managed identity, and move applications off stored MySQL passwords.
- Create separate MySQL users per application with privileges limited to its schema, and keep the administrator account for administration only.
- Where policy demands it, hold the encryption key yourself in Key Vault, with soft delete and purge protection on the vault.
- Turn on the audit log and send diagnostic logs to Log Analytics, and alert on failed logins and changes to server parameters.
- Let Azure Policy insist on private access, TLS and tags, and read Defender for Cloud’s posture findings.
- Restrict who can change networking, parameters and deletion with Azure RBAC, and add resource locks to production servers.
- Plan upgrades off versions that are out of standard support, and test them on a restored copy.
- Review users and grants regularly, and remove accounts that no application uses.
Governance & compliance
Guardrails
- Policy that requires private access, TLS and tags (owner, environment, data class, cost centre) on every server
- A Bicep or Terraform module that bakes in HA, backups and diagnostics
- An approved list of MySQL versions and tiers, with the date each version leaves standard support
- Production servers come only from the release pipeline’s identity
Checks to run on a schedule (Azure Policy, Defender for Cloud)
- A policy that audits or denies MySQL flexible servers with public network access
- A policy that audits servers where secure transport is switched off
- An audit of servers still running versions past standard support
- A report of servers lacking geo-redundant backup where your recovery goals call for it
- A list of non-production servers that have been up beyond an agreed limit
Use the Activity log and Azure Monitor to see who changed what, Azure Policy for the rules above, Defender for Cloud for posture and the Service Trust Portal for compliance reports. Microsoft operates the platform and patches MySQL. You answer for what’s in the database, who holds which grants, how exposed the network is and whether recovery has really been tried.
Reduce carbon footprint
- Stop dev and test servers outside working hours, since a stopped server uses no compute.
- Right-size compute and storage. Spare capacity still draws power.
- Use replicas only where reads need them, and delete them afterwards.
- Add the right indexes and cache hot reads so each request does less work.
- Don’t keep backups longer than recovery requires.
- For work that isn’t tied to a location, a Region on a cleaner grid is worth considering if your data rules allow it.
- Microsoft’s Emissions Impact Dashboard breaks emissions down by subscription; find out how it counts databases before relying on a figure.
Pricing
Purchase options
Compute Per vCore-hour
Charged for every hour the server runs, by tier and size. Stopping it ends the compute charge, and HA adds the cost of a standby.
Storage and IOPS Per GB-month
You pay for the disk you provision, full or not. Some IOPS come included, and more can be bought on their own.
Backup storage Per GB-month
Backups cost nothing up to the size of your provisioned storage. Beyond that, longer retention and geo-redundant copies are billed.
Extras Varies
Replicas are billed as servers of their own. Extended support for old versions, reservations, cross-Region traffic and Log Analytics data appear as separate lines.
What you actually pay for
- Compute for every hour the server runs, by tier and size, doubled when HA is on
- The provisioned disk, plus IOPS beyond what’s included
- Backups past the free allowance, longer retention and geo-redundant copies
- Each read replica, charged like a server
- Extended support for retired versions, cross-Region traffic and Log Analytics
Rates differ by Region, tier and size, and they move over time. Azure's free account has included a small Burstable MySQL server for the first 12 months; confirm what yours gets. Use the official Azure Database for MySQL pricing page and the Azure pricing calculator for current figures, and the Azure free account page for what a new account receives.
Important code references
The orders database on Azure Database for MySQL: a private server with zone-redundant high availability, 14 days of backups and Microsoft Entra sign-in, plus a read replica and a restore test. Build it with the CLI or Terraform tab. The Python and C# tabs sign in with an Entra token over verified TLS and insert an order in a transaction. Names, the Entra administrator and the subscription are examples, and the Terraform tab keeps the administrator password as a variable you should source from a secret store. Billing for a zone-redundant server starts at creation, so remove the test server when you finish.
# Names are examples; the server name must be unique across Azure.
RG=rg-orders-mysql
LOCATION=centralindia
SERVER=orders-mysql-001
ADMIN_ID=00000000-0000-0000-0000-000000000000 # object ID of the Entra user or group that administers the server
az group create --name $RG --location $LOCATION
# Entra sign-in needs a user-assigned managed identity on the server
az identity create --resource-group $RG --name mi-orders-mysql
IDENTITY_ID=$(az identity show --resource-group $RG --name mi-orders-mysql --query id --output tsv)
# A private, zone-redundant MySQL 8.4 server. This also creates the virtual network, the delegated subnet and the private DNS zone.
# The CLI prints a generated administrator password if you don't supply one: keep it in a secret store.
az mysql flexible-server create --resource-group $RG --name $SERVER --location $LOCATION \
--version 8.4 --tier GeneralPurpose --sku-name Standard_D2ds_v4 \
--storage-size 128 --storage-auto-grow Enabled \
--high-availability ZoneRedundant --zone 1 --standby-zone 2 \
--backup-retention 14 --geo-redundant-backup Disabled \
--vnet vnet-orders --address-prefixes 10.40.0.0/16 \
--subnet snet-mysql --subnet-prefixes 10.40.1.0/24 \
--private-dns-zone orders.private.mysql.database.azure.com \
--identity $IDENTITY_ID --database-name orders \
--tags owner=orders-team --yes
# Make an Entra group the administrator
az mysql flexible-server ad-admin create --resource-group $RG --server-name $SERVER \
--display-name orders-db-admins --object-id $ADMIN_ID --identity $IDENTITY_ID
# Keep connections encrypted (this is the default; stating it makes the intent visible)
az mysql flexible-server parameter set --resource-group $RG --server-name $SERVER --name require_secure_transport --value ON
# A read replica for reporting
az mysql flexible-server replica create --resource-group $RG --replica-name orders-mysql-replica --source-server $SERVER
# Practise the restore: a new server from the backups, at a time you choose (UTC)
az mysql flexible-server restore --resource-group $RG --name orders-mysql-restore-test \
--source-server $SERVER --restore-time "2026-10-29T08:30:00Z"
# Clean up the test copy
az mysql flexible-server delete --resource-group $RG --name orders-mysql-restore-test --yes
# Assumes the azurerm provider 4.x. The administrator password is a variable: fetch it from a secret store, never commit it.
provider "azurerm" {
features {}
}
variable "admin_password" {
type = string
sensitive = true
}
variable "admin_object_id" { type = string } # object ID of the Entra administrator
data "azurerm_client_config" "current" {}
resource "azurerm_resource_group" "orders" {
name = "rg-orders-mysql"
location = "centralindia"
}
resource "azurerm_virtual_network" "orders" {
name = "vnet-orders"
location = azurerm_resource_group.orders.location
resource_group_name = azurerm_resource_group.orders.name
address_space = ["10.40.0.0/16"]
}
resource "azurerm_subnet" "mysql" {
name = "snet-mysql"
resource_group_name = azurerm_resource_group.orders.name
virtual_network_name = azurerm_virtual_network.orders.name
address_prefixes = ["10.40.1.0/24"]
delegation {
name = "mysql"
service_delegation {
name = "Microsoft.DBforMySQL/flexibleServers"
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
}
}
}
resource "azurerm_private_dns_zone" "mysql" {
name = "orders.private.mysql.database.azure.com"
resource_group_name = azurerm_resource_group.orders.name
}
resource "azurerm_private_dns_zone_virtual_network_link" "mysql" {
name = "orders-mysql-link"
resource_group_name = azurerm_resource_group.orders.name
private_dns_zone_name = azurerm_private_dns_zone.mysql.name
virtual_network_id = azurerm_virtual_network.orders.id
}
resource "azurerm_user_assigned_identity" "mysql" {
name = "mi-orders-mysql"
location = azurerm_resource_group.orders.location
resource_group_name = azurerm_resource_group.orders.name
}
resource "azurerm_mysql_flexible_server" "orders" {
name = "orders-mysql-001"
resource_group_name = azurerm_resource_group.orders.name
location = azurerm_resource_group.orders.location
version = "8.0.21"
sku_name = "GP_Standard_D2ds_v4"
zone = "1"
administrator_login = "mysqladmin"
administrator_password = var.admin_password
delegated_subnet_id = azurerm_subnet.mysql.id
private_dns_zone_id = azurerm_private_dns_zone.mysql.id
backup_retention_days = 14
geo_redundant_backup_enabled = false
storage {
size_gb = 128
auto_grow_enabled = true
}
high_availability {
mode = "ZoneRedundant"
standby_availability_zone = "2"
}
identity {
type = "UserAssigned"
identity_ids = [azurerm_user_assigned_identity.mysql.id]
}
tags = { team = "orders" }
depends_on = [azurerm_private_dns_zone_virtual_network_link.mysql]
}
resource "azurerm_mysql_flexible_database" "orders" {
name = "orders"
resource_group_name = azurerm_resource_group.orders.name
server_name = azurerm_mysql_flexible_server.orders.name
charset = "utf8mb4"
collation = "utf8mb4_0900_ai_ci"
}
resource "azurerm_mysql_flexible_server_active_directory_administrator" "admin" {
server_id = azurerm_mysql_flexible_server.orders.id
identity_id = azurerm_user_assigned_identity.mysql.id
login = "orders-db-admins"
object_id = var.admin_object_id
tenant_id = data.azurerm_client_config.current.tenant_id
}
resource "azurerm_mysql_flexible_server_configuration" "secure_transport" {
name = "require_secure_transport"
resource_group_name = azurerm_resource_group.orders.name
server_name = azurerm_mysql_flexible_server.orders.name
value = "ON"
}
# pip install mysql-connector-python azure-identity
# One-off, as the Entra administrator: CREATE AADUSER 'orders-app' IDENTIFIED BY 'orders-app-client-id';
# GRANT SELECT, INSERT ON orders.* TO 'orders-app'@'%';
import time
import mysql.connector
from azure.identity import DefaultAzureCredential
HOST = "orders-mysql-001.mysql.database.azure.com" # with private access this name resolves to a private address
DB_NAME = "orders"
DB_USER = "orders-app" # the Entra principal's name in MySQL
CA_FILE = "DigiCertGlobalRootG2.crt.pem" # the root certificate named in the Azure MySQL documentation
credential = DefaultAzureCredential()
def connect():
"""Open a verified TLS connection. The Entra access token is the password, sent with the clear-text plugin over TLS."""
token = credential.get_token("https://ossrdbms-aad.database.windows.net/.default").token
return mysql.connector.connect(
host=HOST, port=3306, database=DB_NAME, user=DB_USER, password=token,
auth_plugin="mysql_clear_password", ssl_ca=CA_FILE, ssl_verify_cert=True,
connection_timeout=5)
def place_order(conn, customer_id, total_cents):
"""Add an order inside a transaction and hand back the generated id."""
cursor = conn.cursor()
try:
cursor.execute(
"INSERT INTO orders (customer_id, total_cents) VALUES (%s, %s)",
(customer_id, total_cents))
conn.commit()
return cursor.lastrowid
except mysql.connector.Error:
conn.rollback()
raise
finally:
cursor.close()
def with_retry(action, tries=3):
"""A failover or a maintenance restart drops connections. Reconnect and try again, backing off each time."""
wait = 2
while True:
tries -= 1
conn = None
try:
conn = connect()
return action(conn)
except (mysql.connector.InterfaceError, mysql.connector.OperationalError):
if tries == 0:
raise
time.sleep(wait)
wait *= 2
finally:
if conn is not None and conn.is_connected():
conn.close()
if __name__ == "__main__":
print("New order id:", with_retry(lambda c: place_order(c, 42, 129900)))
// Program.cs: Entra sign-in, then one order inserted inside a transaction
// NuGet packages: MySqlConnector, Azure.Identity
using Azure.Core;
using Azure.Identity;
using MySqlConnector;
// Entra access tokens expire after roughly an hour, so request one for every new connection
AccessToken token = await new DefaultAzureCredential().GetTokenAsync(
new TokenRequestContext(new[] { "https://ossrdbms-aad.database.windows.net/.default" }));
var builder = new MySqlConnectionStringBuilder
{
Server = "orders-mysql-001.mysql.database.azure.com",
Port = 3306,
Database = "orders",
UserID = "orders-app",
Password = token.Token,
SslMode = MySqlSslMode.VerifyFull,
SslCa = "DigiCertGlobalRootG2.crt.pem", // the root certificate named in the Azure MySQL documentation
ConnectionTimeout = 5
};
await using var connection = new MySqlConnection(builder.ConnectionString);
await connection.OpenAsync();
await using var txn = await connection.BeginTransactionAsync();
await using var insert = new MySqlCommand(
"INSERT INTO orders (customer_id, total_cents) VALUES (@customerId, @totalCents)", connection, txn);
insert.Parameters.AddWithValue("@customerId", 42L);
insert.Parameters.AddWithValue("@totalCents", 129900);
await insert.ExecuteNonQueryAsync();
var orderId = insert.LastInsertedId;
await txn.CommitAsync();
Console.WriteLine($"New order id: {orderId}");
Best videos to explore
Short walkthrough videos for this service are being prepared. They will appear here and load only when you press play. Until then, follow CloudBrum on YouTube for new videos.
Interview questions
BasicWhat is Azure Database for MySQL?
It’s Microsoft’s managed MySQL service. Picking the flexible server option means choosing a MySQL version, a size, some storage and how the server is reached. Azure then runs the host, applies patches, takes the backups and carries out failover, leaving the schema, queries, users and tuning to you.
BasicWhich MySQL versions are available?
MySQL 8.0 and 8.4 are the supported versions. MySQL 5.7 has reached the end of community support and can only be kept on paid extended support while you upgrade. The upgrade path goes from 5.7 to 8.0 first, and then from 8.0 to 8.4, so test each step on a restored copy.
BasicWhat is the difference between private and public access?
With private access the server gets a private address on a delegated subnet in your virtual network, and clients resolve it through a private DNS zone, with no public endpoint. With public access it has a public name and a firewall that lists the allowed addresses. The choice is made when the server is created.
IntermediateHow does high availability work, and what are its limits?
Azure keeps a standby that is synchronised with the primary, in the same zone or in another zone, and fails over to it automatically. Reads can’t be sent to the standby, so scaling reads needs replicas. It isn’t available on the Burstable tier, and zone-redundant HA has to be chosen when the server is created.
IntermediateA dump from your old server fails with a SUPER privilege error. What do you do?
Managed MySQL doesn’t give out SUPER. The usual cause is DEFINER clauses on views, triggers and routines that name a user that doesn’t exist or needs more privilege. Strip or rewrite them in the dump, and for functions and triggers check whether log_bin_trust_function_creators needs to be set. Then import again.
IntermediateHow do applications sign in without a stored password?
Turn on Microsoft Entra authentication, which needs a user-assigned managed identity on the server and an Entra administrator. Create a database user for the application’s identity, and have the application request a token for the Azure open-source database resource and send it as the password, with TLS on and the clear-text plugin enabled in the client. Tokens are short-lived, so request a new one for each connection.
AdvancedYou are upgrading from MySQL 5.7 with almost no downtime. How?
Create a read replica or a restored copy on 8.0 and test the application against it, including character sets, SQL modes, deprecated syntax and query plans. Plan the upgrade in place from 5.7 to 8.0, then to 8.4, on a quiet window with a fresh backup, or build a new server and cut over using replication. Keep the old server for a while as a way back.
AdvancedWhat do you do when replica lag keeps growing?
Check whether the primary has a burst of large writes or long transactions, whether the replica has the same size and IOPS as the source, and whether single-threaded apply is the limit. Look at slow queries on the replica, raise the replica’s resources, and move heavy reporting queries elsewhere. If it’s the workload’s nature, consider batching writes.
AdvancedPlan a disaster recovery design that survives a Regional outage.
Use a cross-Region read replica that you can promote, or geo-redundant backup chosen at creation, and keep infrastructure code that rebuilds the network, DNS and permissions in the paired Region. Write down the RPO and RTO, remembering replication is asynchronous, practise a promotion, and make the application’s connection settings changeable without a rebuild.
AdvancedA WordPress site on the server is slow. Where do you look first?
Start with the database: the slow query log, missing indexes on large post-meta tables, the buffer pool size against the working set, and the connection count. Check IOPS and CPU in metrics, add object caching so fewer queries run at all, and only then resize the server. Make sure the web tier and the database are in the same Region and zone.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | Amazon RDS for MySQL | Azure Database for MySQL (flexible server) | Cloud SQL for MySQL |
| Versions on offer | Several MySQL majors, with paid Extended Support for old ones | 8.0 and 8.4, with 5.7 on paid extended support | Several MySQL majors, by edition |
| A standby for failover | Multi-AZ instance, or a Multi-AZ DB cluster | Same-zone or zone-redundant HA (not on Burstable) | Regional high availability |
| Read scaling | Read replicas, in-Region or cross-Region | Up to ten read replicas | Read replicas, including cross-Region |
| How long backups last | Automated backups kept 1 to 35 days, snapshots on top | Retention up to 35 days, plus point-in-time restore | A retained backup count plus a log window |
| Passwordless sign-in | IAM database authentication | Microsoft Entra authentication | IAM database authentication |
| Raising I/O | Provisioned IOPS and gp3 throughput | IOPS bought separately, with autoscale option | SSD size and Enterprise Plus data cache |
| Private networking | Private subnets and security groups | VNet integration or private endpoint | Private IP, reached through private services access |
The same family has other members: Azure SQL Database for SQL Server applications and Azure Database for PostgreSQL for PostgreSQL ones. Web tiers that use MySQL commonly run on Azure Virtual Machines or Azure Functions.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- What is Azure Database for MySQL - Flexible Server?Microsoft
- Supported versions for Azure Database for MySQLMicrosoft
- High availability in Azure Database for MySQLMicrosoft
- Backup and restore in Azure Database for MySQLMicrosoft
- Connectivity and networking conceptsMicrosoft
- Microsoft Entra authentication for Azure Database for MySQLMicrosoft
- Use an Azure free account to try Azure Database for MySQLMicrosoft
- Azure Database for MySQL pricingMicrosoft
- Terraform azurerm: mysql_flexible_serverHashiCorp
