How to Install MySQL on Linux (Ubuntu)

How to Install MySQL on Linux (Ubuntu)

When I first started managing databases professionally, MySQL was the very first server I ever set up on a Linux box, and to this day it’s still the database I reach for when I need something reliable, well-documented, and battle-tested in production. In this guide, I’m going to walk you through everything I know about installing MySQL on Ubuntu — from the absolute basics all the way to the internal architecture that makes MySQL tick, so you’re not just copy-pasting commands but actually understanding what’s happening under the hood.

Why I Still Choose MySQL in 2026

Before I get into the installation steps, I want to explain why MySQL remains relevant. I’ve worked with PostgreSQL, MariaDB, and a handful of NoSQL engines, but MySQL keeps earning its place because of its predictable performance, mature replication ecosystem, and the sheer size of its community. Whether I’m spinning up a WordPress backend, a Laravel application, or a data warehouse staging layer, MySQL almost always fits the bill.

Understanding MySQL Architecture Before You Install

I always tell people new to databases: don’t just install software blindly — understand what you’re installing. MySQL follows a client-server architecture with a layered design:

  • Connection Layer – handles authentication, thread pooling, and SSL negotiation for every client that connects to my server.
  • SQL Layer – this is where the parser, optimizer, and query cache (deprecated since MySQL 8.0) live. It’s responsible for turning my SQL text into an execution plan.
  • Storage Engine Layer – the pluggable part of MySQL. InnoDB is the default engine I use for almost everything because it supports transactions, row-level locking, and crash recovery.
graph TD
    A[Client Application] --> B[Connection Layer]
    B --> C[SQL Layer: Parser & Optimizer]
    C --> D[Storage Engine Layer]
    D --> E[(InnoDB)]
    D --> F[(MyISAM)]
    D --> G[(Memory)]
    E --> H[Disk Storage / Tablespaces]

Knowing this layered structure has saved me countless hours of troubleshooting because I know exactly which layer to check when something misbehaves — is it a connection issue, a query planning issue, or a storage engine issue?

System Requirements I Check Before Installing

Before I install MySQL on any Ubuntu machine, I verify:

RequirementMinimumWhat I Recommend
RAM1 GB4 GB+ for production
Disk5 GB freeSSD with 50 GB+ for real workloads
OSUbuntu 20.04+Ubuntu 22.04 LTS or 24.04 LTS
CPU1 core2+ cores
User privilegessudo accesssudo access

Step 1: Update My Package Index

The first thing I always do on a fresh Ubuntu server is update the package index so I’m not installing stale packages.

sudo apt update
sudo apt upgrade -y

Step 2: Installing MySQL Server

I install MySQL directly from Ubuntu’s official APT repository because it’s the most reliable path for most of my use cases.

sudo apt install mysql-server -y

This single command pulls in mysql-server, mysql-client, and the common libraries MySQL depends on. Once it finishes, I confirm the service is running:

sudo systemctl status mysql

Expected output looks something like this:

● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled)
     Active: active (running) since Thu 2026-07-30 10:12:03 UTC

If I ever want the absolute latest MySQL version (Ubuntu’s default repo often lags a version or two behind), I add Oracle’s official APT repository instead:

wget https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.29-1_all.deb
sudo apt update
sudo apt install mysql-server -y

During the dpkg -i step, a text-based configuration screen appears where I select the MySQL version and product line I want (usually “MySQL Server & Cluster” followed by the latest GA release).

Step 3: Securing My Installation

This is a step I never skip, even on a throwaway development VM, because bad habits on dev machines eventually leak into production. MySQL ships with an interactive script that hardens the default configuration.

sudo mysql_secure_installation

It walks me through a series of prompts:

  1. Validate Password Component – I usually enable this and choose a medium or strong policy.
  2. Set root password – I always use a long, random password here, generated with a password manager.
  3. Remove anonymous users – Yes, always.
  4. Disallow root login remotely – Yes, unless I have a very specific reason not to.
  5. Remove test database – Yes, I never need the sample test database in production.
  6. Reload privilege tables – Yes, so all changes take effect immediately.

Step 4: Logging In and Verifying My Installation

sudo mysql -u root -p

Once inside the MySQL shell, I like to run a few sanity checks:

SELECT VERSION();
STATUS;
SHOW DATABASES;

Sample output:

+-----------+
| VERSION() |
+-----------+
| 8.0.40    |
+-----------+

Step 5: Creating a Dedicated Admin User

I never keep using the root account for daily work. Instead, I create a dedicated administrative user with a strong password and scoped privileges:

CREATE USER 'ahmad_admin'@'localhost' IDENTIFIED BY 'Str0ngP@ssw0rd!';
GRANT ALL PRIVILEGES ON *.* WITH GRANT OPTION;
FLUSH PRIVILEGES;

Step 6: Configuring MySQL to Start on Boot

sudo systemctl enable mysql

This ensures that after a server reboot — which inevitably happens during patching windows — my database comes back online without manual intervention.

Understanding the Configuration File

On Ubuntu, MySQL’s main configuration file lives at /etc/mysql/mysql.conf.d/mysqld.cnf. I always review a handful of settings right after installation:

[mysqld]
bind-address = 127.0.0.1
port = 3306
datadir = /var/lib/mysql
innodb_buffer_pool_size = 1G
max_connections = 151
  • bind-address controls which network interface MySQL listens on. I leave this as 127.0.0.1 unless I explicitly need remote access.
  • innodb_buffer_pool_size is the single most important tuning parameter for InnoDB performance — I usually set it to 60–70% of available RAM on a dedicated database server.

Storage Engines: What I Choose and Why

Storage EngineTransactionsRow-Level LockingBest Use Case
InnoDBYesYesDefault choice for almost everything
MyISAMNoTable-level onlyLegacy read-heavy, non-transactional workloads
MemoryNoTable-levelTemporary, in-RAM lookup tables
ArchiveNoN/AHistorical, append-only log data

I default to InnoDB unless I have a very specific reason to use something else, because ACID compliance and crash recovery matter more to me than the marginal speed gains of MyISAM.

A Real-World Scenario: Setting Up a Fresh App Server

When I provisioned a new Ubuntu 22.04 server for a client’s e-commerce backend, my exact workflow was:

  1. Update packages and install MySQL Server.
  2. Run mysql_secure_installation.
  3. Create an application-specific database and a least-privilege user scoped to that database only.
  4. Restrict bind-address to the private network interface.
  5. Enable the UFW firewall and only allow port 3306 from the application server’s IP.
sudo ufw allow from 10.0.0.5 to any port 3306

This kind of least-privilege setup is something I insist on for every client project, because an exposed MySQL port on the public internet is one of the most common breach vectors I’ve seen.

Security Best Practices I Always Follow

  • I never expose port 3306 to the public internet without a VPN or SSH tunnel.
  • I always enforce SSL/TLS for remote connections.
  • I create per-application database users instead of sharing root credentials.
  • I rotate passwords regularly and store them in a secrets manager, never in plaintext config files.
  • I enable the general_log only temporarily for debugging, since it has a real performance cost.

Troubleshooting Common Installation Issues

Issue: MySQL service fails to start

sudo journalctl -u mysql.service -n 50

I check this log first — it almost always tells me whether it’s a permissions issue on /var/lib/mysql or a corrupted configuration file.

Issue: “Access denied for user ‘root’@’localhost'”

This usually means the auth_socket plugin is active. I switch the authentication method with:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'NewPassword123!';
FLUSH PRIVILEGES;

Issue: Port 3306 already in use

sudo lsof -i :3306

I use this to identify and stop whatever process is conflicting, often a leftover MariaDB instance.

Performance Considerations Right After Installation

Even before I load any real data, I set a baseline by checking key InnoDB status variables:

SHOW ENGINE INNODB STATUS\G
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

I also make sure the data directory sits on fast storage (SSD/NVMe), since disk I/O is almost always the first bottleneck I encounter in production MySQL deployments.

Frequently Asked Questions

Q: Can I install multiple versions of MySQL on the same Ubuntu server? A: Technically yes, using different data directories and ports, but I avoid this in production. I prefer Docker containers when I need multiple isolated MySQL versions.

Q: Do I need to install MySQL Workbench separately? A: Yes, mysql-server only installs the database engine. I install MySQL Workbench separately, or I use the command-line client and tools like DBeaver.

Q: What’s the difference between MySQL and MariaDB on Ubuntu? A: MariaDB is a community fork of MySQL. I choose based on project requirements — MySQL for Oracle-backed enterprise features, MariaDB when I want a fully open-source stack.

Q: How do I completely uninstall MySQL if something goes wrong? A:

sudo apt purge mysql-server mysql-client mysql-common -y
sudo rm -rf /etc/mysql /var/lib/mysql
sudo apt autoremove -y

Interview Questions I’ve Been Asked (and Asked Others)

  1. What are the main storage engines in MySQL, and how do they differ?
  2. Explain the difference between mysql_secure_installation steps and why each matters.
  3. How does MySQL’s connection layer handle authentication?
  4. What is innodb_buffer_pool_size, and how would you tune it on a server with 16 GB of RAM?
  5. How would you troubleshoot MySQL failing to start after a server reboot?
  6. What’s the difference between binding MySQL to 127.0.0.1 versus 0.0.0.0?

Summary and Key Takeaways

Installing MySQL on Ubuntu is straightforward on the surface, but I’ve learned that the real value comes from understanding the architecture underneath — the connection layer, SQL layer, and storage engines — and from following disciplined security practices from day one. I always secure the installation immediately, create scoped users instead of relying on root, and tune innodb_buffer_pool_size before putting any real workload on the server.

Key takeaways:

  • Use apt install mysql-server for the standard installation path, or Oracle’s APT repo for the latest version.
  • Always run mysql_secure_installation immediately after installing.
  • Understand the layered architecture (connection, SQL, storage engine) to troubleshoot effectively.
  • InnoDB is my default storage engine for transactional integrity.
  • Secure the network layer with firewalls and SSL/TLS before going to production.

References

  • MySQL Official Documentation: https://dev.mysql.com/doc/
  • MySQL 8.0 Reference Manual, Installation Chapter: https://dev.mysql.com/doc/refman/8.0/en/installing.html
  • Ubuntu Server Documentation: https://ubuntu.com/server/docs
Total
2
Shares

Leave a Reply

Previous Post
How to Install MySQL on Windows

How to Install MySQL on Windows

Next Post
How to Create a MySQL Database

How to Create a MySQL Database

Related Posts