Python九阳神功之陆:数据库持久化与缓存·乾坤大挪移

Python九阳神功之陆:数据库持久化与缓存·乾坤大挪移

前言

上一篇我们掌握了数据生产与流转 的内功心法,本篇进入数据存储与访问的实战领域。持久化是系统的根基,缓存是性能的灵魂。本文将带领你从 SQL 到 NoSQL,从 MySQL 到 Redis,打通数据存储的任督二脉。


一、数据库概论

1.1 什么是数据库

数据库(Database)是存储和管理数据的系统,数据按特定格式组织,支持增、删、改、查等操作。

1.2 数据库分类

类型 存储形式 代表产品 特点
关系型数据库(SQL) 行列表格 MySQL、Oracle、SQL Server 结构化、支持SQL查询、事务ACID
非关系型数据库(NoSQL) 键值对/文档/列/图 Redis、MongoDB、HBase 松散结构、高性能、API调用

二、SQL 基础

2.1 SQL 分类

分类 全称 关键字 作用
DDL 数据定义语言 CREATEDROPALTER 定义数据库/表结构
DML 数据操作语言 INSERTUPDATEDELETE 操作表记录
DQL 数据查询语言 SELECTFROMWHERE 查询数据(重点)
DCL 数据控制语言 GRANTREVOKE 权限管理

2.2 通用语法

  • 以分号 ; 结尾
  • 不区分大小写(关键字建议大写)
  • 支持注释:/* */--#
  • 支持缩进增强可读性

三、DDL --- 数据定义语言

3.1 数据库操作

sql 复制代码
-- 创建数据库(存在则忽略)
CREATE DATABASE IF NOT EXISTS hm_db CHARSET utf8;

-- 查看所有数据库
SHOW DATABASES;

-- 使用数据库
USE hm_db;

-- 删除数据库(慎用!)
DROP DATABASE IF EXISTS hm_db;

3.2 表操作

sql 复制代码
-- 创建表
CREATE TABLE IF NOT EXISTS user_info (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_name VARCHAR(32) NOT NULL,
    phone CHAR(11),
    id_card CHAR(18) UNIQUE,
    city VARCHAR(255) DEFAULT '北京'
);

-- 查看所有表
SHOW TABLES;

-- 查看表结构
DESC user_info;

-- 删除表
DROP TABLE IF EXISTS user_info;

3.3 常用数据类型

类型 说明
INT 整数(默认长度11)
VARCHAR(n) 变长字符串
CHAR(n) 定长字符串
DECIMAL(m,n) 精确小数
DATE 日期(YYYY-MM-DD)
DATETIME 日期时间

3.4 约束速查

约束 关键字 作用
主键 PRIMARY KEY 非空唯一
自增 AUTO_INCREMENT 自动递增
非空 NOT NULL 不能为空
唯一 UNIQUE 不能重复
默认 DEFAULT 预设默认值
外键 FOREIGN KEY 关联另一张表

四、DML --- 数据操作语言

4.1 插入(INSERT)

sql 复制代码
-- 指定字段插入(推荐)
INSERT INTO user_info (user_name, phone, id_card)
VALUES ('张三', '13888888888', '11010519900325002X');

-- 插入多条
INSERT INTO user_info (user_name, phone, id_card)
VALUES 
    ('张三', '13888888888', '11010519900325002X'),
    ('李四', '13999999999', '11010519900325002Y');

-- 不指定字段(必须按顺序填所有列)
INSERT INTO user_info VALUES (NULL, '王五', '13777777777', '11010519900325002Z', '上海');

4.2 更新(UPDATE)

sql 复制代码
-- ⚠️ 必须带条件,否则全表更新!
UPDATE user_info SET phone = '13666666666' WHERE user_name = '张三';

4.3 删除(DELETE)

sql 复制代码
-- ⚠️ 必须带条件!
DELETE FROM user_info WHERE id = 1;

-- 清空表(两种方式)
DELETE FROM user_info;          -- 自增保留
TRUNCATE TABLE user_info;       -- 自重重置

五、DQL --- 数据查询语言(核心)

5.1 基础查询

sql 复制代码
-- 查询所有列
SELECT * FROM products;

-- 查询指定列
SELECT name, price FROM products;

-- 去重
SELECT DISTINCT is_self FROM products;

-- 别名
SELECT name AS 商品名称, price 价格 FROM products;

5.2 条件查询(WHERE)

运算符 说明
=!=<>><>=<= 比较
ANDORNOT 逻辑
BETWEEN x AND y 连续范围
IN (x, y, z) 枚举范围
LIKE + %(任意)_(单字符) 模糊匹配
IS NULL / IS NOT NULL 空值判断
sql 复制代码
-- 价格大于3000且自营
SELECT * FROM products WHERE price > 3000 AND is_self = '自营';

-- 价格在 2199~4499 之间
SELECT * FROM products WHERE price BETWEEN 2199 AND 4499;

-- 品牌包含'华为'
SELECT * FROM products WHERE name LIKE '%华为%';

-- 分类为空
SELECT * FROM products WHERE category_id IS NULL;

5.3 排序(ORDER BY)

sql 复制代码
-- 默认升序(ASC),降序(DESC)
SELECT * FROM products ORDER BY price DESC;

-- 多字段排序:先按价格降序,同价按评分升序
SELECT * FROM products ORDER BY price DESC, score ASC;

5.4 聚合函数

函数 作用
COUNT(*) 统计行数(不忽略 NULL)
SUM(列) 求和
AVG(列) 平均值
MAX(列) 最大值
MIN(列) 最小值
sql 复制代码
SELECT 
    COUNT(*) AS 总商品数,
    ROUND(AVG(price), 2) AS 均价,
    MAX(price) AS 最高价,
    MIN(price) AS 最低价
FROM products;

5.5 分组(GROUP BY)

sql 复制代码
-- 按分类统计
SELECT 
    category_id,
    COUNT(*) AS 商品数,
    AVG(price) AS 均价
FROM products
GROUP BY category_id;

-- 加过滤条件(WHERE 分组前,HAVING 分组后)
SELECT 
    category_id,
    AVG(price) AS 均价
FROM products
WHERE is_self = '自营'
GROUP BY category_id
HAVING 均价 > 2000;

5.6 分页(LIMIT)

sql 复制代码
-- 第1页(每页4条)
SELECT * FROM products ORDER BY price DESC LIMIT 0, 4;

-- 第2页:LIMIT 偏移量, 条数
SELECT * FROM products ORDER BY price DESC LIMIT 4, 4;

-- 可读性写法
SELECT * FROM products ORDER BY price DESC LIMIT 4 OFFSET 4;

5.7 SQL 执行顺序(重要!)

复制代码
书写顺序:SELECT → DISTINCT → 聚合函数 → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT
执行顺序:FROM → WHERE → GROUP BY → 聚合函数 → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT

六、多表查询

6.1 表关系

关系 场景
1对多 商品 → 分类
多对多 员工 ↔ 角色 ↔ 权限
1对1 QQ号 → 用户详情

6.2 外键(Foreign Key)

概念:从表某列引用主表主键,保证数据完整性。

注意 :实际开发中更常用逻辑外键(由程序保证一致性),物理外键会降低开发灵活性。

6.3 连接查询

sql 复制代码
-- ① 交叉连接(笛卡尔积)------ 无意义,了解即可
SELECT * FROM category, products;

-- ② 内连接(取交集)
SELECT c.name, p.name 
FROM category c 
INNER JOIN products p ON c.id = p.category_id;

-- ③ 左外连接(左表全保留)
SELECT c.name, p.name 
FROM category c 
LEFT JOIN products p ON c.id = p.category_id;

-- ④ 右外连接(右表全保留)
SELECT c.name, p.name 
FROM products p 
RIGHT JOIN category c ON p.category_id = c.id;

-- ⑤ 全外连接(MySQL 用 UNION 模拟)
SELECT * FROM category LEFT JOIN products ON category.id = products.category_id
UNION
SELECT * FROM category RIGHT JOIN products ON category.id = products.category_id;

6.4 自连接

sql 复制代码
-- 查询河北省所有城市
SELECT city.title 
FROM areas AS province 
JOIN areas AS city ON province.id = city.pid 
WHERE province.title = '河北省';

6.5 子查询

sql 复制代码
-- 查询河北省所有市(单值子查询)
SELECT * FROM areas WHERE pid = (SELECT id FROM areas WHERE title = '河北省');

-- 查询河北/江苏所有市(多值子查询)
SELECT * FROM areas WHERE pid IN (SELECT id FROM areas WHERE title IN ('河北省', '江苏省'));

七、PyMySQL --- Python 操作 MySQL

7.1 安装与连接

bash 复制代码
pip install pymysql
python 复制代码
import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='root',
    database='jing_dong'
)
cur = conn.cursor()

7.2 查询操作

python 复制代码
# 执行查询
cur.execute("SELECT * FROM goods")
data = cur.fetchall()      # 取所有
one = cur.fetchone()       # 取一条

cur.close()
conn.close()

7.3 增删改(需提交事务)

python 复制代码
try:
    cur.execute("INSERT INTO goods(name) VALUES ('魅族手机')")
    conn.commit()           # 提交事务
except Exception:
    conn.rollback()         # 回滚
finally:
    cur.close()
    conn.close()

7.4 SQL 注入与防范

错误写法(拼接字符串):

python 复制代码
# 危险!输入 `' OR '1'='1` 可绕过验证
sql = f"SELECT * FROM user WHERE user='{account}' AND pwd='{pwd}'"

正确写法(参数化):

python 复制代码
sql = "SELECT * FROM user WHERE user=%s AND pwd=%s"
cur.execute(sql, (account, pwd))  # 参数化自动转义

7.5 事务回滚案例

python 复制代码
try:
    cur.execute("UPDATE nh_table SET account=0.5 WHERE user_id=1")
    cur.execute("UPDATE jh_table SET account=1 WHERE user_id=1")
    cur.execute("UPDATE alipay_table SET account=17 WHERE user_id=1")
    conn.commit()
except Exception:
    conn.rollback()          # 任一步骤失败,全部撤销

八、Redis --- 内存中的瑞士军刀

8.1 Redis 简介

Redis(Remote Dictionary Server) 是基于内存的键值对存储数据库,常用于缓存、消息队列、分布式锁等场景。

核心特性:

  • 基于内存,读写极快
  • 支持数据持久化(RDB/AOF)
  • 丰富的数据类型:String、Hash、List、Set、Sorted Set
  • 支持过期时间、发布订阅

8.2 安装与连接

bash 复制代码
# 安装 redis-py
pip install redis
python 复制代码
import redis

r = redis.Redis(
    host='127.0.0.1',
    port=6379,
    db=0,
    decode_responses=True   # 自动解码为字符串
)

8.3 String 操作

python 复制代码
# 设置/获取
r.set('name', '老高')
r.get('name')   # '老高'

# 批量设置/获取
r.mset({'name': '老高', 'age': 36})
r.mget(['name', 'age'])  # ['老高', '36']

# 自增/自减
r.incr('age')      # 37
r.decrby('age', 2) # 35

8.4 Hash 操作(字典)

python 复制代码
# 单个字段
r.hset('user:001', 'name', '张三')
r.hget('user:001', 'name')

# 批量
r.hmset('user:001', {'name': '张三', 'age': 25})

# 获取全部
r.hgetall('user:001')  # {'name': '张三', 'age': '25'}

# 获取所有键/值
r.hkeys('user:001')    # ['name', 'age']
r.hvals('user:001')    # ['张三', '25']

8.5 List 操作

python 复制代码
# 左侧/右侧插入
r.lpush('queue', 'a', 'b', 'c')   # ['c', 'b', 'a']
r.rpush('queue', 'd')             # ['c', 'b', 'a', 'd']

# 范围获取
r.lrange('queue', 0, -1)          # 全部

# 弹出
r.lpop('queue')   # 'c'
r.rpop('queue')   # 'd'

8.6 Set 操作(集合)

python 复制代码
# 添加
r.sadd('skills', 'python', 'mysql', 'redis')

# 获取所有
r.smembers('skills')  # {'redis', 'mysql', 'python'}

# 判断存在
r.sismember('skills', 'python')  # True

# 集合运算
r.sadd('set_a', 1, 2, 3)
r.sadd('set_b', 2, 3, 4)
r.sinter('set_a', 'set_b')   # {2, 3} 交集
r.sunion('set_a', 'set_b')   # {1, 2, 3, 4} 并集
r.sdiff('set_a', 'set_b')    # {1} 差集

8.7 Sorted Set 操作(有序集合)

python 复制代码
# 添加(分数自动排序)
r.zadd('ranking', {'张三': 95, '李四': 88, '王五': 92})

# 升序获取(带分数)
r.zrange('ranking', 0, -1, withscores=True)
# [('李四', 88.0), ('王五', 92.0), ('张三', 95.0)]

# 降序获取(前三名)
r.zrevrange('ranking', 0, 2, withscores=True)

# 修改分数
r.zincrby('ranking', 5, '李四')  # 李四 +5 分

# 获取排名(从0开始)
r.zrank('ranking', '张三')     # 2(正序)
r.zrevrank('ranking', '张三')  # 0(倒序)

8.8 键操作与过期时间

python 复制代码
# 查看所有键
r.keys('*')

# 检查是否存在
r.exists('name')  # 1 或 0

# 删除
r.delete('name')

# 设置过期时间(秒)
r.expire('session_token', 3600)

# 查看剩余时间(-1 永久,-2 已过期)
r.ttl('session_token')

# 设置值并指定过期
r.setex('captcha', 60, '123456')

# 取消过期(设为永久)
r.persist('session_token')

九、实战:Redis 缓存工具类

python 复制代码
import json
import redis

class RedisUtils:
    def __init__(self, host='127.0.0.1', port=6379, db=0):
        self._client = redis.Redis(
            host=host, port=port, db=db,
            decode_responses=True
        )

    def set_cache(self, key, value, expire_time=3600):
        """写入缓存(支持任意 Python 对象)"""
        try:
            self._client.setex(key, expire_time, json.dumps(value))
            return True
        except Exception as e:
            print(f"写入失败: {e}")
            return False

    def get_cache(self, key):
        """读取缓存,自动反序列化"""
        try:
            data = self._client.get(key)
            return json.loads(data) if data else None
        except Exception:
            return None

    def del_cache(self, key):
        """删除缓存"""
        return self._client.delete(key) > 0

    def clear_cache(self):
        """清空当前数据库(慎用)"""
        return self._client.flushdb()

# 使用示例
cache = RedisUtils()
cache.set_cache('user:001', {'name': '老高', 'age': 36})
print(cache.get_cache('user:001'))   # {'name': '老高', 'age': 36}

总结

层次 技术 适用场景
SQL MySQL DDL/DML/DQL 结构化数据存储、复杂关联查询
连接 PyMySQL Python 程序操作 MySQL
缓存 Redis(String/Hash/List/Set/ZSet) 高频读、会话管理、排行榜
工具 RedisUtils 封装 统一缓存读写接口

一条主线贯穿全文:从「数据库设计」到「SQL 增删改查」,再到「Python 连接操作」,最终抵达「Redis 缓存加速」------ 这是数据存储从持久化到高性能的完整链路。

相关推荐
索西引擎22 分钟前
基于 Docker 容器化的 MySQL 数据库部署与访问控制机制研究
数据库·mysql·docker
坐吃山猪25 分钟前
IDEA调试中Evaluate常用操作
java·python·intellij-idea
TDengine (老段)29 分钟前
TDengine 内存管理 — 池化、缓存、回收
大数据·数据库·物联网·缓存·时序数据库·tdengine·涛思数据
空堂与归30 分钟前
南大 AI 课 Token 自费:用缓存命中率算一学期账单
人工智能·缓存·ai·deepseek
Tizzy JJ35 分钟前
接口自动化测试实战:如何围绕真实业务场景设计高质量用例
python·自动化·pytest
小白说大模型36 分钟前
AI 提示词专栏:Zero-Shot 与 One-Shot Prompt 的差别与适用场景
大数据·数据库·人工智能·sql·深度学习·prompt
海兰39 分钟前
【 Python 量化交易】第10章:八大经典策略
android·python·kotlin
oradh41 分钟前
Oracle TM 锁 Mode 4(Share)问题排查总结
数据库·oracle·oracle tm 锁·tm 锁 mode 4
L-岁月染过的梦1 小时前
把常用开发小工具收进 IDEA:Develop Helper 插件介绍
java·数据库·intellij-idea