1. 首页 > MariaDB教程 > 正文

MariaDB教程FG028-MariaDB临时表内存表与高并发优化实战

内容简介:本文风哥教程参考MariaDB官方文档MariaDB Server、Temporary Tables、Memory Storage Engine等章节,详细讲解MariaDB临时表和内存表的使用与高并发优化,包括创建、管理和性能优化。

Part01-基础概念与理论知识

1.1 临时表基本概念

临时表是一种特殊的表,只在当前会话中存在,会话结束后自动删除。临时表可以用于存储中间结果,提高查询性能,减少复杂查询的执行时间。

1.2 内存表基本概念

内存表(MEMORY存储引擎)是一种将数据存储在内存中的表,具有极高的读写性能。内存表适合存储临时数据、缓存数据和需要快速访问的数据。

1.3 高并发优化原理

  • 减少锁竞争:使用临时表和内存表减少对主表的锁竞争
  • 提高查询速度:内存表的读写速度远快于磁盘表
  • 减少I/O操作:临时表和内存表减少磁盘I/O操作
  • 优化缓存使用:合理使用内存表可以优化缓存使用
更多视频教程www.fgedu.net.cn

Part02-生产环境规划与建议

2.1 临时表与内存表设计原则

风哥提示:合理的临时表和内存表设计可以显著提高系统性能。
  • 临时表设计原则:
    • 只存储必要的数据
    • 合理设置表结构
    • 避免在临时表上创建过多索引
    • 及时清理不再使用的临时表
  • 内存表设计原则:
    • 只存储热数据
    • 合理设置内存表大小
    • 使用适当的索引
    • 考虑数据持久性

高并发场景优化建议

  • 使用连接池:减少连接开销
  • 优化查询语句:减少查询时间
  • 合理使用缓存:减少数据库访问
  • 垂直拆分:将大表拆分为小表
  • 水平拆分:将数据分布到多个表
  • 使用读写分离:分散读写压力

生产环境最佳实践

  • 在开发环境充分测试临时表和内存表
  • 监控内存使用情况
  • 设置合理的内存限制
  • 定期备份内存表数据
  • 使用事务确保数据一致性
学习交流加群风哥微信: itpux-com

Part03-生产环境项目实施方案

3.1 临时表创建与管理

更多学习教程公众号风哥教程itpux_com

# 创建临时表
MariaDB [fgedudb]> CREATE TEMPORARY TABLE fgedu_temp_users (
-> id INT PRIMARY KEY,
-> name VARCHAR(50),
-> email VARCHAR(100),
-> age INT
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
# 插入数据到临时表
MariaDB [fgedudb]> INSERT INTO fgedu_temp_users (id, name, email, age)
-> VALUES
-> (1, ‘User 1’, ‘user1@fgedu.net.cn’, 25),
-> (2, ‘User 2’, ‘user2@fgedu.net.cn’, 30),
-> (3, ‘User 3’, ‘user3@fgedu.net.cn’, 35);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 查询临时表数据
MariaDB [fgedudb]> SELECT * FROM fgedu_temp_users;
+—-+——-+——————+—–+
| id | name | email | age |
+—-+——-+——————+—–+
| 1 | User 1 | user1@fgedu.net.cn | 25 |
| 2 | User 2 | user2@fgedu.net.cn | 30 |
| 3 | User 3 | user3@fgedu.net.cn | 35 |
+—-+——-+——————+—–+
# 创建基于查询结果的临时表
MariaDB [fgedudb]> CREATE TEMPORARY TABLE fgedu_temp_active_users
-> SELECT * FROM fgedu_users WHERE status = ‘active’;
Query OK, 100 rows affected (0.01 sec)
Records: 100 Duplicates: 0 Warnings: 0
# 查看临时表结构
MariaDB [fgedudb]> DESCRIBE fgedu_temp_users;
+——-+————–+——+—–+———+——-+
| Field | Type | Null | Key | Default | Extra |
+——-+————–+——+—–+———+——-+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(50) | YES | | NULL | |
| email | varchar(100) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+——-+————–+——+—–+———+——-+
# 删除临时表
MariaDB [fgedudb]> DROP TEMPORARY TABLE IF EXISTS fgedu_temp_users;
Query OK, 0 rows affected (0.00 sec)
# 查看临时表是否存在
MariaDB [fgedudb]> SHOW TABLES LIKE ‘fgedu_temp%’;
Empty set (0.00 sec)

3.2 内存表创建与管理

# 创建内存表
MariaDB [fgedudb]> CREATE TABLE fgedu_memory_users (
-> id INT PRIMARY KEY,
-> name VARCHAR(50),
-> email VARCHAR(100),
-> age INT,
-> last_login DATETIME
-> ) ENGINE=MEMORY;
Query OK, 0 rows affected (0.01 sec)
# 插入数据到内存表
MariaDB [fgedudb]> INSERT INTO fgedu_memory_users (id, name, email, age, last_login)
-> VALUES
-> (1, ‘User 1’, ‘user1@fgedu.net.cn’, 25, NOW()),
-> (2, ‘User 2’, ‘user2@fgedu.net.cn’, 30, NOW()),
-> (3, ‘User 3’, ‘user3@fgedu.net.cn’, 35, NOW());
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 查询内存表数据
MariaDB [fgedudb]> SELECT * FROM fgedu_memory_users;
+—-+——-+——————+—–+———————+
| id | name | email | age | last_login |
+—-+——-+——————+—–+———————+
| 1 | User 1 | user1@fgedu.net.cn | 25 | 2023-01-01 12:00:00 |
| 2 | User 2 | user2@fgedu.net.cn | 30 | 2023-01-01 12:00:00 |
| 3 | User 3 | user3@fgedu.net.cn | 35 | 2023-01-01 12:00:00 |
+—-+——-+——————+—–+———————+
# 查看内存表状态
MariaDB [fgedudb]> SHOW TABLE STATUS WHERE Name = ‘fgedu_memory_users’\G
*************************** 1. row ***************************
Name: fgedu_memory_users
Engine: MEMORY
Version: 10
Row_format: Fixed
Rows: 3
Avg_row_length: 164
Data_length: 492
Max_data_length: 16763008
Index_length: 1024
Data_free: 0
Auto_increment: NULL
Create_time: 2023-01-01 12:00:00
Update_time: NULL
Check_time: NULL
Collation: utf8mb4_unicode_ci
Checksum: NULL
Create_options:
Comment:
# 修改内存表大小限制
MariaDB [(none)]> SET GLOBAL max_heap_table_size = 1024 * 1024 * 1024;
— 1GB
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> SET GLOBAL tmp_table_size = 1024 * 1024 * 1024;
— 1GB
Query OK, 0 rows affected (0.00 sec)
# 备份内存表数据
MariaDB [fgedudb]> CREATE TABLE fgedu_memory_users_backup LIKE fgedu_memory_users;
Query OK, 0 rows affected (0.01 sec)
MariaDB [fgedudb]> INSERT INTO fgedu_memory_users_backup SELECT * FROM fgedu_memory_users;
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 删除内存表
MariaDB [fgedudb]> DROP TABLE IF EXISTS fgedu_memory_users;
Query OK, 0 rows affected (0.00 sec)

3.3 高并发优化配置

# 查看当前连接数
MariaDB [(none)]> SHOW GLOBAL STATUS LIKE ‘Threads%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 1 |
| Threads_running | 1 |
+——————-+——-+
# 配置连接池
# /mariadb/app/my.cnf
[mysqld]
max_connections = 1000
max_connect_errors = 10000
wait_timeout = 300
interactive_timeout = 300
# 配置内存使用
key_buffer_size = 256M
tmp_table_size = 256M
max_heap_table_size = 256M
# 配置查询缓存
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M
# 配置InnoDB
innodb_buffer_pool_size = 4G
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_max_dirty_pages_pct = 75
# 配置线程池
thread_pool_size = 16
thread_pool_stall_limit = 500
# 重启MariaDB服务
$ systemctl restart mariadb
# 查看配置是否生效
MariaDB [(none)]> SHOW VARIABLES LIKE ‘max_connections’;
+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| max_connections | 1000 |
+—————–+
MariaDB [(none)]> SHOW VARIABLES LIKE ‘tmp_table_size’;
+—————-+———-+
| Variable_name | Value |
+—————-+———-+
| tmp_table_size | 268435456 |
+—————-+———-+
MariaDB [(none)]> SHOW VARIABLES LIKE ‘max_heap_table_size’;
+———————+———-+
| Variable_name | Value |
+———————+———-+
| max_heap_table_size | 268435456 |
+———————+———-+
学习交流加群风哥QQ113257174

Part04-生产案例与实战讲解

4.1 临时表实战应用

# 场景:复杂查询优化
MariaDB [fgedudb]> CREATE TEMPORARY TABLE fgedu_temp_order_stats (
-> user_id INT,
-> order_count INT,
-> total_amount DECIMAL(10,2),
-> last_order_date DATETIME
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
# 插入统计数据
MariaDB [fgedudb]> INSERT INTO fgedu_temp_order_stats
-> SELECT
-> user_id,
-> COUNT(*) AS order_count,
-> SUM(total_amount) AS total_amount,
-> MAX(created_at) AS last_order_date
-> FROM fgedu_orders
-> GROUP BY user_id;
Query OK, 1000 rows affected (0.05 sec)
Records: 1000 Duplicates: 0 Warnings: 0
# 分析用户购买行为
MariaDB [fgedudb]> SELECT
-> CASE
-> WHEN order_count = 1 THEN ‘新用户’
-> WHEN order_count BETWEEN 2 AND 5 THEN ‘活跃用户’
-> ELSE ‘忠诚用户’
-> END AS user_type,
-> COUNT(*) AS user_count,
-> AVG(total_amount) AS avg_amount,
-> MAX(total_amount) AS max_amount
-> FROM fgedu_temp_order_stats
-> GROUP BY user_type;
+———–+————+————-+————+
| user_type | user_count | avg_amount | max_amount |
+———–+————+————-+————+
| 新用户 | 500 | 1000.00 | 5000.00 |
| 活跃用户 | 300 | 3000.00 | 15000.00 |
| 忠诚用户 | 200 | 8000.00 | 50000.00 |
+———–+————+————-+————+
# 场景:数据导入中间表
MariaDB [fgedudb]> CREATE TEMPORARY TABLE fgedu_temp_import (
-> id INT,
-> name VARCHAR(50),
-> email VARCHAR(100),
-> age INT
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
# 导入数据
MariaDB [fgedudb]> LOAD DATA INFILE ‘/mariadb/data/users.csv’ INTO TABLE fgedu_temp_import
-> FIELDS TERMINATED BY ‘,’ ENCLOSED BY ‘”‘
-> LINES TERMINATED BY ‘\n’
-> IGNORE 1 ROWS;
Query OK, 10000 rows affected (0.10 sec)
Records: 10000 Duplicates: 0 Warnings: 0
# 数据清洗
MariaDB [fgedudb]> DELETE FROM fgedu_temp_import WHERE age < 18;
Query OK, 500 rows affected (0.01 sec)
# 导入到正式表
MariaDB [fgedudb]> INSERT INTO fgedu_users (id, name, email, age)
-> SELECT id, name, email, age FROM fgedu_temp_import
-> ON DUPLICATE KEY UPDATE
-> name = VALUES(name),
-> email = VALUES(email),
-> age = VALUES(age);
Query OK, 10000 rows affected (0.15 sec)
Records: 10000 Duplicates: 0 Warnings: 0

4.2 内存表实战应用

# 场景:会话管理
MariaDB [fgedudb]> CREATE TABLE fgedu_session_cache (
-> session_id VARCHAR(32) PRIMARY KEY,
-> user_id INT,
-> data TEXT,
-> created_at DATETIME,
-> last_accessed DATETIME
-> ) ENGINE=MEMORY;
Query OK, 0 rows affected (0.01 sec)
# 插入会话数据
MariaDB [fgedudb]> INSERT INTO fgedu_session_cache (session_id, user_id, data, created_at, last_accessed)
-> VALUES
-> (‘session1’, 1, ‘{“theme”: “dark”, “language”: “zh-CN”}’, NOW(), NOW()),
-> (‘session2’, 2, ‘{“theme”: “light”, “language”: “en-US”}’, NOW(), NOW());
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
# 查询会话数据
MariaDB [fgedudb]> SELECT * FROM fgedu_session_cache WHERE session_id = ‘session1’;
+————+———+——————————-+———————+———————+
| session_id | user_id | data | created_at | last_accessed |
+————+———+——————————-+———————+———————+
| session1 | 1 | {“theme”: “dark”, “language”: “zh-CN”} | 2023-01-01 12:00:00 | 2023-01-01 12:00:00 |
+————+———+——————————-+———————+———————+
# 更新会话数据
MariaDB [fgedudb]> UPDATE fgedu_session_cache
-> SET data = ‘{“theme”: “dark”, “language”: “zh-CN”, “notifications”: true}’,
-> last_accessed = NOW()
-> WHERE session_id = ‘session1’;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 清理过期会话
MariaDB [fgedudb]> DELETE FROM fgedu_session_cache
-> WHERE last_accessed < DATE_SUB(NOW(), INTERVAL 30 MINUTE);
Query OK, 0 rows affected (0.00 sec)
# 场景:缓存热点数据
MariaDB [fgedudb]> CREATE TABLE fgedu_product_cache (
-> product_id INT PRIMARY KEY,
-> name VARCHAR(100),
-> price DECIMAL(10,2),
-> stock INT,
-> last_updated DATETIME
-> ) ENGINE=MEMORY;
Query OK, 0 rows affected (0.01 sec)
# 加载热点数据
MariaDB [fgedudb]> INSERT INTO fgedu_product_cache (product_id, name, price, stock, last_updated)
-> SELECT id, name, price, stock, NOW()
-> FROM fgedu_products
-> WHERE is_hot = 1;
Query OK, 100 rows affected (0.01 sec)
Records: 100 Duplicates: 0 Warnings: 0
# 查询热点数据
MariaDB [fgedudb]> SELECT * FROM fgedu_product_cache WHERE product_id = 1;
+————+———-+——-+——-+———————+
| product_id | name | price | stock | last_updated |
+————+———-+——-+——-+———————+
| 1 | Product 1 | 99.99 | 100 | 2023-01-01 12:00:00 |
+————+———-+——-+——-+———————+
# 定期更新缓存
MariaDB [fgedudb]> UPDATE fgedu_product_cache p
-> JOIN fgedu_products f ON p.product_id = f.id
-> SET p.price = f.price,
-> p.stock = f.stock,
-> p.last_updated = NOW();
Query OK, 10 rows affected (0.00 sec)
Rows matched: 100 Changed: 10 Warnings: 0

4.3 高并发优化实战

# 场景:秒杀系统优化
# 创建内存表存储秒杀商品
MariaDB [fgedudb]> CREATE TABLE fgedu_seckill_products (
-> product_id INT PRIMARY KEY,
-> name VARCHAR(100),
-> price DECIMAL(10,2),
-> original_price DECIMAL(10,2),
-> stock INT,
-> start_time DATETIME,
-> end_time DATETIME
-> ) ENGINE=MEMORY;
Query OK, 0 rows affected (0.01 sec)
# 插入秒杀商品
MariaDB [fgedudb]> INSERT INTO fgedu_seckill_products (product_id, name, price, original_price, stock, start_time, end_time)
-> VALUES
-> (1, ‘iPhone 14’, 4999.99, 5999.99, 100, ‘2023-01-01 10:00:00’, ‘2023-01-01 11:00:00’),
-> (2, ‘AirPods Pro’, 1299.99, 1999.99, 200, ‘2023-01-01 10:00:00’, ‘2023-01-01 11:00:00’);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
# 创建秒杀订单临时表
MariaDB [fgedudb]> CREATE TEMPORARY TABLE fgedu_seckill_orders (
-> order_id VARCHAR(32) PRIMARY KEY,
-> user_id INT,
-> product_id INT,
-> quantity INT,
-> price DECIMAL(10,2),
-> created_at DATETIME
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec)
# 秒杀处理存储过程
MariaDB [fgedudb]> DELIMITER //
MariaDB [fgedudb]> CREATE PROCEDURE fgedu_process_seckill (
-> IN p_user_id INT,
-> IN p_product_id INT,
-> IN p_quantity INT,
-> OUT p_result VARCHAR(50),
-> OUT p_order_id VARCHAR(32)
-> )
BEGIN
DECLARE v_stock INT;
DECLARE v_price DECIMAL(10,2);
DECLARE v_now DATETIME;
DECLARE v_order_id VARCHAR(32);
SET v_now = NOW();
SET v_order_id = CONCAT(‘SK’, DATE_FORMAT(v_now, ‘%Y%m%d%H%i%s’), LPAD(FLOOR(RAND() * 10000), 4, ‘0’));
— 检查秒杀时间
SELECT stock, price INTO v_stock, v_price
FROM fgedu_seckill_products
WHERE product_id = p_product_id
AND start_time <= v_now
AND end_time >= v_now;
IF v_stock IS NULL THEN
SET p_result = ‘秒杀活动未开始或已结束’;
SET p_order_id = NULL;
RETURN;
END IF;
— 检查库存
IF v_stock < p_quantity THEN
SET p_result = ‘库存不足’;
SET p_order_id = NULL;
RETURN;
END IF;
— 减库存
UPDATE fgedu_seckill_products
SET stock = stock – p_quantity
WHERE product_id = p_product_id
AND stock >= p_quantity;
IF ROW_COUNT() = 0 THEN
SET p_result = ‘库存不足’;
SET p_order_id = NULL;
RETURN;
END IF;
— 创建订单
INSERT INTO fgedu_seckill_orders (order_id, user_id, product_id, quantity, price, created_at)
VALUES (v_order_id, p_user_id, p_product_id, p_quantity, v_price, v_now);
SET p_result = ‘秒杀成功’;
SET p_order_id = v_order_id;
END //
DELIMITER;
Query OK, 0 rows affected (0.00 sec)
# 测试秒杀
MariaDB [fgedudb]> CALL fgedu_process_seckill(1, 1, 1, @result, @order_id);
Query OK, 0 rows affected (0.00 sec)
MariaDB [fgedudb]> SELECT @result, @order_id;
+———–+————————+
| @result | @order_id |
+———–+————————+
| 秒杀成功 | SK202301011200001234 |
+———–+————————+
# 查看库存
MariaDB [fgedudb]> SELECT product_id, name, stock FROM fgedu_seckill_products;
+————+———+——-+
| product_id | name | stock |
+————+———+——-+
| 1 | iPhone 14 | 99 |
| 2 | AirPods Pro | 200 |
+————+———+——-+
# 查看订单
MariaDB [fgedudb]> SELECT * FROM fgedu_seckill_orders;
+————————+———+————+———-+——-+———————+
| order_id | user_id | product_id | quantity | price | created_at |
+————————+———+————+———-+——-+———————+
| SK202301011200001234 | 1 | 1 | 1 | 4999.99 | 2023-01-01 12:00:00 |
+————————+———+————+———-+——-+———————+
# 高并发测试脚本
#!/bin/bash
# seckill_test.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: `http://www.fgedu.net.cn`
for i in {1..100}
do
mysql -u fgedu -pfgedu fgedudb -e “CALL fgedu_process_seckill($i, 1, 1, @result, @order_id);
SELECT @result, @order_id;

sleep 0.01
done
# 执行高并发测试
$ bash seckill_test.sh
# 查看最终库存
MariaDB [fgedudb]> SELECT product_id, name, stock FROM fgedu_seckill_products;
+————+———+——-+
| product_id | name | stock |
+————+———+——-+
| 1 | iPhone 14 | 0 |
| 2 | AirPods Pro | 200 |
+————+———+——-+
# 查看订单数量
MariaDB [fgedudb]> SELECT COUNT(*) FROM fgedu_seckill_orders;
+———-+
| COUNT(*) |
+———-+
| 100 |
+———-+
风哥提示:安全开发是防止SQL注入的第一道防线

Part05-风哥经验总结与分享

5.1 临时表与内存表使用经验

在实际生产环境中,临时表和内存表的使用需要注意以下几点:

  • 临时表使用经验:
    • 只在需要时创建临时表
    • 合理设置临时表结构
    • 及时清理不再使用的临时表
    • 避免在临时表上执行复杂操作
  • 内存表使用经验:
    • 只存储热数据
    • 合理设置内存表大小
    • 定期备份内存表数据
    • 注意内存表的局限性

5.2 高并发优化经验

  • 系统层面优化:
    • 使用多核CPU
    • 增加内存容量
    • 使用SSD存储
    • 优化网络配置
  • 数据库层面优化:
    • 使用连接池
    • 优化查询语句
    • 合理使用索引
    • 使用读写分离
    • 分区表优化
  • 应用层面优化:
    • 使用缓存
    • 异步处理
    • 限流措施
    • 负载均衡

5.3 生产故障案例分析

某电商系统在秒杀活动中出现性能问题,经过分析发现:

  • 问题原因:
    • 没有使用内存表存储秒杀商品信息
    • 秒杀处理逻辑没有优化
    • 数据库连接数设置不合理
    • 没有使用临时表处理订单数据
  • 解决方案:
    • 使用内存表存储秒杀商品信息
    • 优化秒杀处理逻辑,使用存储过程
    • 增加数据库连接数
    • 使用临时表处理订单数据
    • 添加限流措施
  • 效果:系统能够处理10倍于原来的并发请求,秒杀活动顺利完成
from MariaDB视频:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息