文档
1. 什么是 MariaDB?
MariaDB 是 MySQL 的完全兼容替代品,由 MySQL 之父 Monty Widenius 在 Oracle 收购 Sun/MySQL 后创建(2009 年),以保障 MySQL 生态的开源自由。
MySQL vs MariaDB
| 维度 | MySQL 8.0 | MariaDB 11.x |
|---|---|---|
| JSON 支持 | JSON 类型 + 函数 | 相同,还增加了 JSON 校验约束 |
| 存储引擎 | 以 InnoDB 为主 | 多了 Aria、ColumnStore、MyRocks |
| 窗口函数 | 支持 | 支持(10.2+) |
| CTE/递归 | 支持 | 支持 |
| RETURNING 子句 | ❌ | ✅ (10.5+)(省去额外查询) |
| 序列(Sequence) | ❌ | ✅ (10.3+) |
| 系统版本表 | ❌ | ✅ (10.3+)(自动保留历史) |
| 许可 | GPL | GPL + LGPL(客户端库更宽松) |
2. MariaDB 独有特性详解
RETURNING 子句
-- 插入同时返回数据,无需 SELECT
INSERT INTO users (name, email) VALUES ('张三', 'zs@test.com')
RETURNING id, name, created_at;
序列(Sequence)
CREATE SEQUENCE order_seq START WITH 1000 INCREMENT BY 1;
SELECT NEXTVAL(order_seq); -- 1000
CREATE TABLE orders (
order_no BIGINT DEFAULT NEXTVAL(order_seq),
user_id INT,
amount DECIMAL(10,2)
);
系统版本表(自动记录历史)
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
price DECIMAL(8,2)
) WITH SYSTEM VERSIONING;
-- 更新后查询历史
SELECT * FROM products FOR SYSTEM_TIME ALL
WHERE id = 1 AND price < 200;
3. 实战:图书管理系统
CREATE DATABASE library CHARACTER SET utf8mb4;
USE library;
-- 读者表
CREATE TABLE readers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
card_no VARCHAR(20) UNIQUE NOT NULL,
phone VARCHAR(20),
registered_at DATE DEFAULT (CURRENT_DATE)
);
-- 图书表(含系统版本追踪)
CREATE TABLE books (
id INT AUTO_INCREMENT PRIMARY KEY,
isbn VARCHAR(20) UNIQUE NOT NULL,
title VARCHAR(200) NOT NULL,
author VARCHAR(100),
price DECIMAL(8,2),
stock INT DEFAULT 0 CHECK(stock >= 0)
) WITH SYSTEM VERSIONING;
-- 借阅记录
CREATE TABLE borrows (
id INT AUTO_INCREMENT PRIMARY KEY,
reader_id INT NOT NULL,
book_id INT NOT NULL,
borrow_date DATE DEFAULT (CURRENT_DATE),
return_date DATE,
FOREIGN KEY (reader_id) REFERENCES readers(id),
FOREIGN KEY (book_id) REFERENCES books(id)
);
-- 借书(事务)
DELIMITER $$
CREATE PROCEDURE borrow_book(
IN p_reader_id INT,
IN p_book_id INT
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
START TRANSACTION;
-- 检查库存
IF (SELECT stock FROM books WHERE id = p_book_id) <= 0 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '库存不足';
END IF;
-- 扣减库存
UPDATE books SET stock = stock - 1 WHERE id = p_book_id;
-- 创建借阅记录
INSERT INTO borrows (reader_id, book_id) VALUES (p_reader_id, p_book_id);
COMMIT;
END$$
DELIMITER ;
-- 调用
INSERT INTO readers (name, card_no) VALUES ('张三', 'R2024001');
INSERT INTO books (isbn, title, author, price, stock) VALUES
('978-7-111', '数据库系统概念', 'Silberschatz', 99.00, 3);
CALL borrow_book(1, 1);
4. ColumnStore 列式引擎(分析场景)
-- MariaDB 10.5+ 内置 ColumnStore
CREATE TABLE sales_log (
id INT AUTO_INCREMENT,
product_id INT,
amount DECIMAL(10,2),
sale_date DATE,
region VARCHAR(50)
) ENGINE=ColumnStore;
-- 列式存储对聚合查询极快
SELECT region, SUM(amount) AS total
FROM sales_log
WHERE sale_date BETWEEN '2024-01-01' AND '2024-12-31'
GROUP BY region;
5. 优化技巧
-- 慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
-- 查看执行计划
EXPLAIN FORMAT=JSON
SELECT * FROM borrows WHERE reader_id = 1;
-- 使用 ANALYZE + FORMAT=JSON(MariaDB 独有)
ANALYZE FORMAT=JSON
SELECT b.title, r.name
FROM borrows br
JOIN books b ON br.book_id = b.id
JOIN readers r ON br.reader_id = r.id;
思考题
- 系统版本表(SYSTEM VERSIONING)和外键约束能共存吗?为什么?
- 什么场景下 ColumnStore 比 InnoDB 更快?反过来呢?
- MariaDB 的
RETURNING子句相比 MySQL 的LAST_INSERT_ID()的SELECT,有什么优势?
推荐工具
- HeidiSQL(Windows GUI)- 对 MariaDB 完美支持
- Beekeeper Studio(跨平台)
- mycli(命令行智能补全):
pip install mycli