What MySQL actually is
MySQL is an open source relational database: it stores your data in tables and lets you query it with SQL. That's it. It doesn't give you screens, forms or reports. Those come from whatever you build on top of it.
That split is worth getting straight early. Every data-driven app has two halves:
- The front end is what people touch: a web app, a mobile app, a desktop tool. It collects input and shows results.
- The back end is where the data lives. MySQL sits here, alongside alternatives like PostgreSQL and MariaDB.
People coming from Microsoft Access sometimes expect MySQL to ship with a built-in interface. It doesn't. You install the database, then you (or your team) write the front end in PHP, Node, Python, a native mobile stack or anything else that can talk to it. In bigger companies, the front-end and back-end people can be entirely different teams, which is exactly why the two sides need to agree on how the data is laid out.
How a MySQL setup is structured
Think of MySQL as a set of nested boxes, from the hardware down to a single row of data:
- Server. A physical machine or VM with an operating system, usually Linux. For reliability you can run several MySQL servers as a cluster that replicates data, so one dead box doesn't take you offline.
- MySQL software. Installed on that OS. A data file with no MySQL running on the machine is just bytes on a disk.
- Databases. Top-level groupings. A small business might keep everything in one. A larger one might split CRM, work orders and inventory into separate databases, so a breach or corruption in one doesn't take down the rest, and so each team's app only gets access to what it needs. A single front end can still connect to several databases at once.
- Tables. Logical containers inside a database:
users,parts,vendors,invoices. They look a lot like spreadsheets. - Columns. The fields each record has, like
user_id,name,email,age. Each column has a data type. - Rows (records). The actual entries: user 1 is Bob, user 2 is Sue, and so on.
The first column is usually a primary key, typically an auto-incrementing ID. It guarantees every row is unique, even if two people share the same name and age.
All of this together, the database names, tables, columns and types, is the schema. MySQL enforces it strictly. If the front-end team decides they want to collect T-shirt sizes, nothing gets saved until someone adds a tshirt_size column. That rigidity is a feature: it keeps data predictable. Schemaless (NoSQL) databases trade it away for flexibility.
Under the hood, a storage engine does the actual reading and writing. The default is InnoDB, and unless you have a specific, well-understood reason, leave it alone.
Data types: the guardrail you'll thank later
Every column only accepts one kind of value. That sounds fussy until you picture the alternative: averaging ten thousand invoice totals where one of them is "Bob". The worst case isn't a crash. It's a number that's slightly wrong and nobody notices.
The types you'll reach for most:
| Type | Holds | Use it for |
|---|---|---|
INT (and TINYINT, SMALLINT, BIGINT) | Whole numbers | IDs, ages, quantities |
DECIMAL(p,s) | Exact numbers with fixed decimal places | Money and prices |
FLOAT / DOUBLE | Approximate decimals | Measurements, scientific values |
VARCHAR(n) / CHAR(n) | Short text with a length limit | Names, emails, codes |
TEXT | Longer text | Descriptions, notes |
DATE, DATETIME, TIMESTAMP | Dates and times | Created-at, due dates |
BLOB | Raw binary | Rarely worth it: store files elsewhere and keep a link |
Two traps catch beginners:
- Too loose. Using
FLOATfor prices gives you answers like 14.375 when a customer asks what a part costs.DECIMAL(10,2)keeps it to cents. - Too tight.
DECIMAL(5,2)tops out at 999.99. The day your totals hit four digits, inserts start failing. Size columns for where the business is going, not where it is.
Types are the last line of defence, not the only one. Validate input in the front end too (JavaScript in the form, plus a server-side check), and make sure the app tells the user when a write fails. A silent failure, where the form looks fine but nothing was saved, is the one that comes back to bite you a week later.
Stored procedures and functions
Once your queries grow past a line or two, typing them out every time gets old, and every retype is a chance to fat-finger a comma. MySQL lets you save logic on the server itself.
- A stored procedure is a saved query (or batch of statements) you run with
CALL name();. - A stored function takes inputs, does a calculation and returns one value you can use inside a
SELECT.
Say your parts table holds what you paid for each part, and you want to sell at a 25% markup. First, a function that does the math:
DELIMITER $$
CREATE FUNCTION retail_calc(part_price DECIMAL(10,2), markup DECIMAL(5,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGIN
DECLARE retail_price DECIMAL(10,2);
SET retail_price = part_price * markup;
RETURN retail_price;
END$$
DELIMITER ;
Then a procedure that wraps the query, so nobody has to type it again:
DELIMITER $$
CREATE PROCEDURE price_list()
BEGIN
SELECT *, retail_calc(part_price, 1.25) AS retail FROM parts;
END$$
DELIMITER ;
CALL price_list();
A few things worth knowing:
- The delimiter dance. The body contains semicolons, so you temporarily switch the statement terminator to
$$. Always switch it back withDELIMITER ;, or your next ordinary query will just sit there waiting. DETERMINISTIC. On servers with binary logging on (the default), MySQL refuses to create a function unless you declare whether it always returns the same output for the same input.- Calculated values aren't stored. The
retailcolumn only exists in that query's result. RunSELECT * FROM partsand it's gone. If you need to keep it, write it back with anUPDATEor a generated column. - Housekeeping:
SHOW FUNCTION STATUS WHERE Db = 'class_db';lists them,SHOW CREATE FUNCTION retail_calc;shows the code, andDROP FUNCTION retail_calc;removes it. The same commands work withPROCEDURE. - Name things clearly.
retail_calctells the next developer what it does.nastydoes not. - Check the math. A function can run perfectly and still return the wrong number. Get someone else to sanity-check any formula that touches pricing or billing.
MySQL vs PostgreSQL
PostgreSQL is the database people usually weigh MySQL against, and the short version is: MySQL is the fast, simple workhorse; PostgreSQL is the feature-rich, standards-strict one.
They have a lot in common. Both are open source relational databases, both speak SQL, both handle JSON, both replicate, and both power huge production systems. The differences are in emphasis.
| MySQL | PostgreSQL | |
|---|---|---|
| Current stable | 9.7 LTS (Apr 2026); 8.4 LTS still supported | 18.x; 19 in beta since Jun 2026 |
| Owner / governance | Oracle | Community (PostgreSQL Global Development Group) |
| Licence | GPL (plus commercial) | PostgreSQL licence (very permissive) |
| Sweet spot | Read-heavy web apps, CMSs, e-commerce | Complex queries, analytics, financial and data-heavy apps |
| Learning curve | Gentle, quick to set up | Steeper, more to configure |
| SQL standards | Looser by default | Very strict |
| Data types | The essentials | Arrays, JSONB, ranges, custom types, rich extensions (PostGIS, pgvector) |
| Concurrency | MVCC via InnoDB | MVCC built into the core |
| Hosting | Available everywhere, especially cheap shared hosting | Available on every major cloud |
Pick MySQL when you want something fast to stand up, your workload is mostly reads, or you're running software built for it, like WordPress, Magento or a lot of PHP apps. Its LTS track also shipped some former Enterprise-only features to the free Community edition in 9.7, including OpenTelemetry support and the hypergraph optimizer (source).
Pick PostgreSQL when your queries are complex, data integrity is critical, or you want advanced types and extensions. It's also the default choice for a lot of modern stacks: Supabase, most Node/TypeScript ORMs, and anything doing vector search with pgvector. Version 19 adds SQL/PGQ graph queries and up to 2x faster inserts on tables with foreign keys (source).
MySQL vs MariaDB
MariaDB is MySQL's sibling. It was forked in 2009 by MySQL's original creator, Michael "Monty" Widenius, after Oracle bought Sun (and with it, MySQL). For years it was a drop-in replacement: same commands, same client libraries, same file formats. That's still mostly true for everyday work, but the two have drifted apart.
| MySQL | MariaDB | |
|---|---|---|
| Latest LTS | 9.7 (Apr 2026) | 12.3 (May 2026) |
| Release rhythm | An LTS roughly every two years, plus innovation releases | One LTS every year, plus rolling releases |
| Governance | Oracle | MariaDB Foundation (community) + MariaDB plc (commercial) |
| Licence | GPL, with some features Enterprise-only | GPL, with more features in the free edition |
| Storage engines | InnoDB, plus a few others | InnoDB plus extras like Aria, ColumnStore, Spider |
| Vector search | Via HeatWave (Oracle cloud) | Native since 11.8 |
| Compatibility | The reference | Mostly compatible, but diverging in newer features (JSON, replication, system tables) |
On Debian, the default-mysql-server package actually installs MariaDB, and several other distributions ship it as their default "MySQL", so plenty of people use it without knowing.
Choose MariaDB if you like MySQL's model but prefer community governance, want a yearly LTS cadence, or need native vector search without a cloud service. Stick with MySQL if you're on a managed service built around it, need a feature that only exists in Oracle's version, or want the most widely supported option. Either way, test before you swap one for the other in production; "drop-in" is no longer a guarantee.
So which one should you use?
For most small and mid-sized web projects, any of the three will do the job. The deciding factor is usually what your software expects and what your team already knows.
- MySQL if you're running WordPress, Magento or classic PHP apps, want the broadest hosting support, or value simplicity over features.
- PostgreSQL if you're starting fresh on a modern stack, expect complex queries or analytics, or want extensions like PostGIS or pgvector.
- MariaDB if you want MySQL compatibility with community governance and a faster LTS cadence.
Whichever you pick, the fundamentals in this article carry over: design the schema carefully up front, choose data types that fit the data (and leave room to grow), validate in the front end, never let a write fail silently, and double-check any math you hand to the database. Get those right and the choice of engine matters a lot less than people think.