👋 欢迎来到如约数科

一名Java后端开发者,持续深耕跨境电商供应链技术领域

从单体应用到微服务架构,从关务系统到智能化供应链, 在业务和技术的碰撞中不断学习和实践。

这里记录: • 🏗️ 生产环境的技术选型思考与架构演进实践 • 🌏 跨境电商场景下的业务痛点与技术解决方案 • ☕ 从Java基础到分布式系统的系统化学习笔记

没有标准答案,只有真实的技术探索和踩坑记录。

什么是数据库?为什么需要数据库?

引言 提出问题 假设你正在开发一个电商网站,需要存储用户信息、商品数据、订单记录。最简单的方式是什么?把数据写入文本文件! users.txt: 1,张三,zhangsan@example.com,18888888888 2,李四,lisi@example.com,13999999999 products.txt: 1,iPhone 15,6999,100 2,MacBook Pro,12999,50 orders.txt: 1,1,1,2024-01-15 10:30:00,6999 2,2,2,2024-01-15 11:45:00,12999 但当你的网站有1000万用户时,你会遇到以下问题: 如何快速查找张三的订单记录?(需要遍历1000万行) 如何保证两个用户不会同时购买最后一件商品?(并发问题) 如果服务器突然断电,刚写入一半的订单数据怎么办?(数据一致性) 如何保证用户密码不会被其他程序随意读取?(安全性) 这就是为什么我们需要数据库! 为什么重要 数据库是现代软件系统的基石: 💰 金融系统:每秒处理上万笔交易,不能有任何差错 🛒 电商平台:双十一期间,亿级用户并发访问 📱 社交媒体:存储数十亿用户的照片、视频、动态 🏥 医疗系统:保存患者病历,关乎生命安全 掌握数据库,你才能: 设计出高效、可靠的系统架构 解决生产环境的性能瓶颈 理解为什么"删库跑路"是工程师最大的噩梦 基础概念 第一性原理:什么是数据? 在计算机科学中,**数据(Data)**是对现实世界信息的抽象表示。 简单类比: 现实世界:一个名叫"张三"的人,身高180cm,体重75kg 数据表示:{"name": "张三", "height": 180, "weight": 75} 数据的本质是结构化的信息,可以被计算机存储、处理和传输。 从文件到数据库的演进 阶段一:纯文本文件(1960年代) 最原始的数据存储方式: users.txt: 张三,男,25,北京 李四,女,30,上海 王五,男,28,深圳 优点: ✅ 简单直观,易于理解 ✅ 不需要额外的软件支持 缺点: ❌ 查询效率低:需要逐行扫描 ❌ 并发问题:多个程序同时写入会数据混乱 ❌ 数据冗余:同一个数据在多个文件中重复存储 ❌ 无法保证一致性:写入一半断电会导致数据损坏 阶段二:层次数据库(1960-1970年代) 数据以树形结构组织: 公司 ├── 研发部 │ ├── 张三(工号001) │ └── 李四(工号002) └── 销售部 ├── 王五(工号003) └── 赵六(工号004) 优点: ...

2025-11-20 · maneng

MySQL简介:历史、特点与应用场景

引言 提出问题 在上一篇文章中,我们理解了为什么需要数据库。但是面对市场上众多的数据库产品,你可能会困惑: 为什么阿里巴巴、腾讯、字节跳动都选择MySQL? MySQL和Oracle有什么区别?为什么Oracle那么贵还有人用? PostgreSQL被称为"最先进的开源数据库",为什么MySQL更流行? 我应该学MySQL还是学其他数据库? 这篇文章将帮你找到答案! 为什么重要 选择正确的数据库,关系到: 技术栈:你的职业发展方向 成本:开源 vs 商业授权(百万级差异) 生态:是否有丰富的工具和社区支持 就业:市场对不同数据库技能的需求 数据说话: DB-Engines排名:MySQL长期稳居第2名(仅次于Oracle) TIOBE指数:MySQL是最受欢迎的开源数据库 招聘数据:MySQL相关岗位是Oracle的3倍 MySQL的诞生与发展 起源:一个瑞典小团队的创业故事(1995年) 1995年,三位瑞典工程师创建了MySQL: Michael “Monty” Widenius David Axmark Allan Larsson 创业初衷:他们需要一个快速、可靠、免费的数据库来支持自己的咨询业务,但当时的商业数据库(如Oracle)太贵,开源数据库(如PostgreSQL)太慢。 命名来源: “My”:Monty女儿的名字 “SQL”:结构化查询语言(Structured Query Language) 有趣的细节:MySQL的海豚Logo名叫"Sakila",来自全球用户投票选出的非洲城市名。 发展历程:从小众到全球第二 阶段一:开源崛起(1995-2000) 1995年5月23日:MySQL 1.0发布 仅支持基本的SQL查询 没有事务支持 但速度快、体积小、免费 关键特性: 采用双授权模式:GPL开源 + 商业授权 专注于速度而非功能完整性 适合Web应用(LAMP架构:Linux + Apache + MySQL + PHP) 阶段二:互联网爆发(2000-2008) 2000年:MySQL 3.23发布 支持全文检索 支持事务(InnoDB存储引擎) 成为互联网公司首选 2003年:MySQL 4.0发布 支持子查询 支持Union 查询缓存 2005年:MySQL 5.0发布 支持存储过程 支持视图 支持触发器 这一时期: ...

2025-11-20 · maneng

MySQL索引原理:从O(n)到O(log n)的飞跃

引言 “计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。” —— David Wheeler 在上一篇文章《MySQL第一性原理:为什么我们需要数据库?》中,我们了解到MySQL通过索引将查询性能从O(n)提升到O(log n),实现了10万倍的性能飞跃。 但你有没有想过: 为什么索引能这么快? 从1亿条数据中查找一条,只需要3-4次磁盘IO 为什么MySQL选择B+树? 而不是哈希表、二叉搜索树、红黑树? 为什么有些查询用不上索引? WHERE id + 1 = 100 vs WHERE id = 99 联合索引的最左前缀原则是什么? 为什么(user_id, created_time)索引无法优化WHERE created_time > xxx? 今天,我们从第一性原理出发,通过对比5种数据结构,深度剖析MySQL索引的演进历程: 顺序扫描 → 哈希索引 → 二叉搜索树 → B树 → B+树 O(n) O(1) O(log₂n) O(logₘn) O(logₘn) + 顺序IO 1秒 ? ? ? 10微秒 我们还将手写300行代码,实现一个简化版B+树,彻底理解索引的实现原理。 一、问题的起点:全表扫描的性能瓶颈 让我们从一个最简单的查询开始: -- 用户表,1亿条数据 SELECT * FROM users WHERE id = 50000000; 如果没有索引,MySQL会怎么做? 1.1 顺序扫描(Full Table Scan) 执行过程: 1. 从磁盘读取第1页数据(16KB,约100行)→ 判断id是否等于50000000 → 不是 2. 从磁盘读取第2页数据 → 判断 → 不是 3. 从磁盘读取第3页数据 → 判断 → 不是 ... 500000. 从磁盘读取第50万页数据 → 判断 → 是! ✅ 总计:扫描50万页,约8GB数据 性能分析: ...

2025-11-03 · maneng

MySQL安装与环境配置

引言 提出问题 前两篇文章中,我们理解了数据库的重要性和MySQL的核心优势。但是: 如何在自己的电脑上安装MySQL? Windows、Mac、Linux系统的安装方式有什么区别? 如何快速搭建MySQL开发环境(Docker)? 安装后如何连接和使用MySQL? 有哪些好用的MySQL客户端工具? 这篇文章将带你动手实战,从零开始搭建MySQL开发环境! 为什么重要 “工欲善其事,必先利其器”。正确安装和配置MySQL是学习的第一步: ✅ 环境搭建好,后续学习才能顺畅 ✅ 掌握多平台安装,适应不同工作环境 ✅ 了解配置文件,为后续性能调优打基础 ✅ 熟悉客户端工具,提升开发效率 基础概念 MySQL的三种安装方式 方式1:官方安装包(推荐新手) 特点: ✅ 安装简单,图形化界面 ✅ 自动配置环境变量 ✅ 集成MySQL Workbench客户端 ❌ 版本更新需要重新下载安装包 适用场景: 开发环境 学习测试 Windows/macOS用户 方式2:包管理器(推荐Linux用户) 特点: ✅ 命令行一键安装 ✅ 版本更新方便(apt upgrade/yum update) ✅ 自动处理依赖关系 ❌ 版本可能不是最新 适用场景: Linux服务器 CI/CD自动化 开发环境 方式3:Docker容器(推荐进阶用户) 特点: ✅ 环境隔离,不污染主机 ✅ 秒级启动和销毁 ✅ 版本切换方便 ❌ 需要掌握Docker基础 适用场景: 快速测试 多版本切换 微服务开发 Windows系统安装 方式一:MSI安装包(推荐) 步骤1:下载MySQL安装包 访问MySQL官网:https://dev.mysql.com/downloads/mysql/ ...

2025-11-20 · maneng

MySQL事务与锁:并发控制的艺术

引言 “并发是计算机科学中最难的问题之一,因为它涉及时间、顺序和不确定性。” —— Leslie Lamport 在前两篇文章中,我们了解了MySQL如何通过索引实现快速查询,如何通过WAL日志保证数据持久化。但还有一个核心问题没有解决: 如何在高并发场景下保证数据一致性? 想象这样的场景: 双11零点,100万用户同时抢购一件库存只有10个的商品 每个用户都执行: 1. 读取库存 → 10 2. 判断库存足够 → 是 3. 扣减库存 → 库存 - 1 4. 创建订单 结果:卖出了100万件,但库存只扣了10个 💥 这就是并发控制的核心难题:如何让多个并发事务互不干扰,同时保证数据一致性? 今天,我们从第一性原理出发,深度剖析MySQL的并发控制机制: 无控制 → 锁机制 → MVCC → 隔离级别 → 死锁处理 混乱 串行化 读写分离 灵活平衡 自动恢复 ❌ ⚠️ ✅ ✅ ✅ 我们还将手写MVCC核心逻辑,彻底理解MySQL如何实现读写不阻塞。 一、问题的起点:并发导致的数据混乱 让我们从一个最经典的并发问题开始:电商库存扣减。 1.1 场景:秒杀商品超卖问题 需求: 商品:iPhone 16 Pro Max(库存10件) 活动:双11零点秒杀,原价9999元,秒杀价1元 预期:10个用户抢到,其余用户提示"已抢完" 无并发控制的实现: /** * 秒杀服务(无并发控制) */ @Service public class SeckillService { @Autowired private ProductMapper productMapper; @Autowired private OrderMapper orderMapper; /** * 秒杀下单(存在并发问题) */ public boolean seckill(Long productId, Long userId) { // 1. 读取库存 Product product = productMapper.selectById(productId); int stock = product.getStock(); // 2. 判断库存是否足够 if (stock <= 0) { return false; // 库存不足 } // 3. 扣减库存 product.setStock(stock - 1); productMapper.updateById(product); // 4. 创建订单 Order order = new Order(); order.setUserId(userId); order.setProductId(productId); order.setAmount(1.00); // 秒杀价1元 orderMapper.insert(order); return true; } } 并发测试: ...

2025-11-03 · maneng

数据库与表的创建:DDL基础

引言 提出问题 安装好MySQL后,你可能迫不及待想要存储数据。但是: 如何创建一个数据库? 如何创建表来存储用户信息、订单数据? 表创建后发现字段设计不合理,如何修改? 如何删除不需要的表和数据库? DDL、DML、DQL这些术语是什么意思? 这篇文章将带你掌握MySQL的"数据定义语言",学会管理数据库对象的生命周期! 为什么重要 DDL(Data Definition Language)是使用MySQL的第一步: ✅ 没有数据库和表,就无法存储数据 ✅ 合理的表结构设计,是性能优化的基础 ✅ 掌握ALTER语句,应对需求变更 ✅ 了解DROP的风险,避免误删数据 基础概念 SQL语言的分类 SQL(Structured Query Language,结构化查询语言)按功能分为四大类: 1. DDL(Data Definition Language,数据定义语言) 作用:定义和管理数据库对象(数据库、表、索引、视图) 核心语句: CREATE:创建数据库对象 ALTER:修改数据库对象 DROP:删除数据库对象 TRUNCATE:清空表数据 RENAME:重命名对象 本文重点讲解DDL! 2. DML(Data Manipulation Language,数据操作语言) 作用:操作表中的数据 核心语句: INSERT:插入数据 UPDATE:更新数据 DELETE:删除数据 (下一篇详细讲解) 3. DQL(Data Query Language,数据查询语言) 作用:查询数据 核心语句: SELECT:查询数据 (SQL进阶篇详细讲解) 4. DCL(Data Control Language,数据控制语言) 作用:管理用户权限 核心语句: GRANT:授予权限 REVOKE:撤销权限 数据库操作 创建数据库(CREATE DATABASE) 基础语法 CREATE DATABASE database_name; 实战示例 -- 创建一个名为 mydb 的数据库 CREATE DATABASE mydb; -- 执行结果 Query OK, 1 row affected (0.01 sec) 指定字符集和校对规则 CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 参数说明: ...

2025-11-20 · maneng

MySQL查询优化:从执行计划到性能调优

引言 “过早优化是万恶之源。但当性能问题真正出现时,优化就是救命稻草。” —— Donald Knuth 在前三篇文章中,我们学习了索引、事务、锁的原理。但光有理论还不够,如何定位和优化慢查询? 想象这样的场景: 凌晨3点,你被一通电话吵醒: "数据库快挂了,所有查询都超时!" 你打开监控,发现: - CPU 100% - 慢查询日志爆满 - 某个SQL执行了10秒还没返回 如何快速定位问题?如何优化这个慢查询? 这就是查询优化的核心价值:让慢查询变快,让系统起死回生。 今天,我们从第一性原理出发,深度剖析MySQL的查询优化: SQL执行流程: 客户端 → 连接器 → 解析器 → 优化器 → 执行器 → 存储引擎 ↓ ↓ ↓ ↓ ↓ 权限检查 语法解析 生成计划 执行查询 返回数据 性能优化: 慢查询 → EXPLAIN → 找到瓶颈 → 优化索引 → 改写SQL → 性能飞跃 10秒 分析 全表扫描 建索引 覆盖索引 10ms 我们还将通过10个真实案例,将慢查询从10秒优化到10ms,性能提升1000倍。 一、SQL执行流程:从SQL到结果集 理解查询优化,首先要理解SQL是如何执行的。 1.1 MySQL的架构:两层结构 ┌─────────────────────────────────────────────────────────────┐ │ MySQL Server层 │ ├─────────────────────────────────────────────────────────────┤ │ 连接器 解析器 优化器 执行器 │ │ ↓ ↓ ↓ ↓ │ │ 权限验证 语法解析 生成计划 执行查询 │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 存储引擎层 │ ├─────────────────────────────────────────────────────────────┤ │ InnoDB MyISAM Memory Archive │ │ ↓ ↓ ↓ ↓ │ │ 事务支持 不支持 内存存储 压缩存储 │ └─────────────────────────────────────────────────────────────┘ Server层与存储引擎的职责分工: ...

2025-11-03 · maneng

数据类型详解:选择合适的数据类型

引言 提出问题 上一篇我们学会了创建表,但在定义列时遇到了很多数据类型: 存储用户ID,用 INT 还是 BIGINT? 存储金额,为什么用 DECIMAL 而不是 FLOAT? 存储用户名,VARCHAR(50) 和 VARCHAR(255) 有什么区别? 存储日期,用 DATE、DATETIME 还是 TIMESTAMP? CHAR 和 VARCHAR 怎么选择? 选择错误的数据类型会导致: 浪费存储空间(INT能搞定的用BIGINT) 性能下降(VARCHAR(255)比VARCHAR(50)慢) 精度丢失(FLOAT存金额会有误差) 查询出错(日期类型选错导致时区问题) 这篇文章将帮你理解MySQL数据类型的底层原理,学会正确选型! 数据类型分类 MySQL数据类型分为五大类: 分类 常用类型 应用场景 数值类型 INT, BIGINT, DECIMAL, FLOAT 年龄、金额、计数器 字符串类型 CHAR, VARCHAR, TEXT 用户名、描述、文章内容 日期时间类型 DATE, TIME, DATETIME, TIMESTAMP 创建时间、生日 二进制类型 BLOB, BINARY 图片、文件(不推荐存数据库) JSON类型 JSON 配置项、扩展字段 数值类型 整数类型 五种整数类型 类型 存储空间 有符号范围 无符号范围 典型应用 TINYINT 1字节 -128 ~ 127 0 ~ 255 年龄、状态码 SMALLINT 2字节 -32,768 ~ 32,767 0 ~ 65,535 分类ID MEDIUMINT 3字节 -838万 ~ 838万 0 ~ 1677万 较少使用 INT 4字节 -21亿 ~ 21亿 0 ~ 42亿 用户ID、商品ID BIGINT 8字节 -922京 ~ 922京 0 ~ 1844京 订单ID、大数据 实战示例 CREATE TABLE user_profile ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID(无符号,0-42亿)', age TINYINT UNSIGNED COMMENT '年龄(0-255)', score SMALLINT DEFAULT 0 COMMENT '积分(-32768~32767)', view_count BIGINT UNSIGNED DEFAULT 0 COMMENT '浏览量(大数据)' ); 有符号 vs 无符号(UNSIGNED) -- 有符号(默认) CREATE TABLE test1 (num INT); -- 范围:-2147483648 ~ 2147483647 -- 无符号(推荐用于ID、计数器) CREATE TABLE test2 (num INT UNSIGNED); -- 范围:0 ~ 4294967295 选择原则: ...

2025-11-20 · maneng

基础增删改查:DML操作入门

引言 提出问题 前面几篇我们学会了创建数据库和表,但表只是一个空壳,现在要学习: 如何往表里插入数据?(INSERT) 如何修改已有的数据?(UPDATE) 如何删除不需要的数据?(DELETE) 如何查询数据?(SELECT) 批量插入和批量更新如何操作? 这就是CRUD操作(Create增、Read读、Update改、Delete删),是使用数据库的核心! DML语句概述 DML(Data Manipulation Language,数据操作语言):操作表中的数据 操作 语句 作用 对应CRUD 插入 INSERT 向表中添加新数据 Create 查询 SELECT 从表中读取数据 Read 更新 UPDATE 修改表中已有数据 Update 删除 DELETE 从表中删除数据 Delete INSERT:插入数据 基础语法 INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...); 实战准备:创建测试表 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, age INT, status TINYINT DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); 插入单行数据 -- 方式1:指定列名(推荐) INSERT INTO users (username, email, age) VALUES ('zhangsan', 'zhangsan@example.com', 25); -- 方式2:不指定列名(必须提供所有列的值,按顺序) INSERT INTO users VALUES (NULL, 'lisi', 'lisi@example.com', 30, 1, CURRENT_TIMESTAMP); -- NULL:让AUTO_INCREMENT自动生成ID -- CURRENT_TIMESTAMP:当前时间 推荐使用方式1,因为: ...

2025-11-20 · maneng

MySQL核心原理:关键技术深度解析

引言 通过前5篇文章,我们已经掌握了MySQL的核心技术。本文将深入MySQL内部,理解关键组件的工作原理。 一、InnoDB核心组件 1.1 Buffer Pool:内存缓存池 作用:缓存数据页和索引页,减少磁盘IO Buffer Pool结构: ┌─────────────────────────────────────┐ │ Buffer Pool (默认128MB) │ ├─────────────────────────────────────┤ │ 数据页缓存 (75%) │ │ ├─ Page 1: users表数据 │ │ ├─ Page 2: orders表数据 │ │ └─ ... │ ├─────────────────────────────────────┤ │ 索引页缓存 (20%) │ │ ├─ Index Page 1: uk_username │ │ ├─ Index Page 2: idx_created_time │ │ └─ ... │ ├─────────────────────────────────────┤ │ Undo页缓存 (5%) │ │ └─ 历史版本数据 │ └─────────────────────────────────────┘ 淘汰算法: LRU (Least Recently Used) 热数据: 靠近链表头部 冷数据: 靠近链表尾部 新数据: 先放入中间位置(避免扫描污染) 关键参数: ...

2025-11-03 · maneng

如约数科科技工作室

浙ICP备2025203501号

👀 本站总访问量 ...| 👤 访客数 ...| 📅 今日访问 ...