|
https://doris.apache.org/zh-CN/download
wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-3.1.4-bin-x64.tar.gz
wget https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-4.1.3-bin-x64.tar.gz
**Apache Doris** 是高性能实时分析数据库(MPP 架构),亚秒级查询、高并发,兼容 MySQL 协议(`mysql` 客户端直连 9030)。
- 适用场景:报表分析、实时数仓、交互式查询、日志分析
- 版本约定:**3.x 必须 JDK 17**;2.1(含)之前用 JDK 8
- 本文环境:Ubuntu 20.04(WSL2)/ 28 核 31G / Doris 3.1.4 单机版
- 安装目标:`/opt/app/doris`(fe/be/jdk/mysql 全部在该目录)
|
|
| 组件 | 端口 | 用途 |
|------|------|------|
| FE | 9010 | edit_log(元数据同步)|
| FE | 9020 | rpc |
| FE | **9030** | **mysql 查询协议(客户端连接)** |
| FE | 8030 | http(Web UI / health API)|
| BE | 9050 | **heartbeat(FE 心跳 BE)** |
| BE | 9060 | thrift(BE 主服务)|
| BE | 8040 | webserver(BE http)|
检查端口占用:`ss -tln | grep -E ":(9010|9020|9030|8030|9050|9060|8040)"`
|
|
**两种架构**:
- **存算一体**(默认):数据存 BE 本地盘,部署简单性能优,适合大多数场景
- **存算分离**:数据存共享存储(对象存储),计算弹性伸缩
**FE 角色**:Follower(参与选主)/ Observer(只同步元数据)。生产建议 ≥3 Follower。
**BE 数量**:生产 3 副本建议 ≥3 BE;**开发测试单机 1 FE + 1 BE 即可**(本文场景)。
官方文档:
- 部署前准备 https://doris.apache.org/zh-CN/docs/dev/install/preparation/env-checking
- 手动部署 https://doris.apache.org/zh-CN/docs/dev/install/deploy-manually/integrated-storage-compute-deploy-manually
|
|
| 检查项 | 要求 | 检查命令 |
|--------|------|---------|
| CPU 指令集 | 支持 AVX2(否则用 no-AVX2 包)| `cat /proc/cpuinfo \| grep avx2` |
| 内存 | 建议 CPU 核数 ×2 以上(8核16G 起)| `free -h` |
| 磁盘 | FE 预留 100G+;BE 按 数据量×3副本×1.4 | `df -h /opt` |
| 文件系统 | EXT4 或 XFS | `df -T /opt` |
| 网络 | 建议万兆网卡;多网卡做链路聚合 | `ethtool eth0` |
|
|
- [ ] 关闭 swap 分区
- [ ] 关闭透明大页(THP = madvise)
- [ ] 虚拟内存区域 vm.max_map_count ≥ 2000000
- [ ] CPU 不用省电模式(performance)
- [ ] TCP 溢出自动重置 net.ipv4.tcp_abort_on_overflow = 1
- [ ] Doris 相关端口畅通 / 防火墙放行
- [ ] 文件句柄 nofile ≥ 1000000
- [ ] 集群机器 NTP 时钟同步(误差 < 5000ms)
|
|
**三个安装包**(本机存放在 `/mnt/d/tmp/doris/`):
| 包 | 说明 | 大小 |
|----|------|------|
| apache-doris-3.1.4-bin-x64.tar.gz | Doris 主程序(fe/be/ms/extensions/tools)| 3.2G |
| openjdk-17_linux-x64_bin.tar.gz | JDK 17(Doris 3.x 必需)| 187M |
| mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz | MySQL 客户端(仅用 mysql 命令,不必装服务)| 832M |
**要点**:JDK 与 MySQL 客户端只需解压 + 配环境变量即可使用,无需真正"安装"。
参考实例:`ssh xt@101.43.140.244:/opt/app/doris/`(可正常运行的环境,可对照排障)
|
|
```bash
# 1. 关闭 swap(临时;永久关闭需注释 /etc/fstab 中 swap 行后重启)
sudo swapoff -a
# 2. 透明大页 → madvise(临时 + rc.local 持久化)
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# 3. 虚拟内存区域(永久 + 立即生效)
echo "vm.max_map_count = 2000000" | sudo tee -a /etc/sysctl.conf
sudo sysctl -w vm.max_map_count=2000000
# 4. TCP 溢出自动重置(永久 + 立即生效)
echo "net.ipv4.tcp_abort_on_overflow = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -w net.ipv4.tcp_abort_on_overflow=1
sudo sysctl -p # 全部生效
```
|
|
```bash
# /etc/security/limits.conf 追加(重启会话生效)
* soft nofile 1000000
* hard nofile 1000000
# 验证当前值
ulimit -n # 应 ≥ 1000000
# CPU 省电模式 → performance(可选,不支持则跳过)
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
```
|
|
```bash
# 防火墙(开发环境直接关闭;生产放行 Doris 端口)
sudo systemctl stop firewalld.service 2>/dev/null
sudo systemctl disable firewalld.service 2>/dev/null
# Ubuntu/WSL 一般无 firewalld,用 ufw status 确认
# NTP 时钟同步(多节点集群必须;单机可跳过)
sudo apt install -y ntp
sudo systemctl restart ntp
timedatectl status
```
|
|
**目录结构**(fe/be/ms/extensions/tools + jdk-17 + mysql 全在 `/opt/app/doris`):
```bash
mkdir -p /opt/app/doris && cd /opt/app/doris
# JDK 17(只需解压)
tar -xzf /mnt/d/tmp/doris/openjdk-17_linux-x64_bin.tar.gz
# MySQL 客户端(解压 + 重命名,只用到 bin/mysql)
tar -xJf /mnt/d/tmp/doris/mysql-8.4.11-linux-glibc2.28-x86_64.tar.xz
mv mysql-8.4.11-linux-glibc2.28-x86_64 mysql
# Doris 主程序(3.2G,耗时几分钟;解压后拍平到 /opt/app/doris)
tar -xzf /mnt/d/tmp/doris/apache-doris-3.1.4-bin-x64.tar.gz
mv apache-doris-3.1.4-bin-x64/* . && rmdir apache-doris-3.1.4-bin-x64
```
解压完成验证:`ls /opt/app/doris` 应有 `fe be ms extensions tools jdk-17 mysql`
|
|
追加到 `~/.bashrc`:
```bash
# ===== Doris 环境 =====
export DORIS_HOME=/opt/app/doris
export JAVA_HOME=/opt/app/doris/jdk-17
export PATH=$JAVA_HOME:/opt/app/doris/mysql/bin:$PATH
```
生效并验证:
```bash
source ~/.bashrc
java -version # openjdk version "17"
mysql --version # Ver 8.4.11
```
|
|
测试集群可用 docker 快速拉起多节点(`--privileged` 特权 + 自定义网络):
```bash
docker network create --subnet=192.168.73.0/24 mydk
docker run -itd --privileged --name ds1 -h ds1 --net mydk --ip 192.168.73.11 \
-v /opt:/opt -v /mnt:/mnt ubuntu18:1.0 bash
# ds2~ds6 同理(IP .12~.16)
docker start ds1 ds2 ds3 ds4 ds5 ds6
```
节点内建 doris 用户与 ssh:`adduser doris`、安装 openssh-server、配 NTP。
|
|
修改 `fe/conf/fe.conf`(先备份:`cp fe/conf/fe.conf fe/conf/fe.conf.orig`),追加:
```properties
JAVA_HOME = /opt/app/doris/jdk-17
priority_networks = 172.26.112.0/20
lower_case_table_names = 1
```
**堆内存**:修改 `JAVA_OPTS_FOR_JDK_17` 行的 `-Xmx/-Xms`(默认 8G,按物理内存调):
| 物理内存 | FE -Xmx |
|---------|---------|
| 8G | 1024m |
| 16G | 2048m |
| 31G | 4096m |
|
|
修改 `be/conf/be.conf`,追加:
```properties
JAVA_HOME = /opt/app/doris/jdk-17
priority_networks = 172.26.112.0/20
mem_limit = 8G
```
**mem_limit 参照**:8G 物理内存给 1536m;16G 给 4G;31G 给 8G。
|
|
**不配 priority_networks 会选错网卡**(如 docker0 的 172.17.0.1),导致 FE/BE 通信失败。必须匹配 eth0 实际网段,且 **WSL2 重启后 IP 会漂移,重装时要重新探测**:
```bash
# 取 eth0 IP(含掩码后缀,如 172.26.114.122/20)
NIC_IP=$(ip -4 addr show eth0 | awk '/inet /{print $2}' | head -1)
# 换算网段 → 填入 fe.conf / be.conf 的 priority_networks
python3 -c "import ipaddress;print(ipaddress.ip_network('$NIC_IP', strict=False))"
# 输出示例: 172.26.112.0/20
```
|
|
**顺序:启动 FE → 注册 BE → 启动 BE**(BE 必须先在 FE 注册才能加入集群)
```bash
# 1. 启动 FE(root 默认无密码)
cd /opt/app/doris/fe && ./bin/start_fe.sh --daemon
# 等待 9030 监听(约 10 秒),失败看 log/fe.out
# 2. 注册 BE —— 必须用 eth0 实际 IP,不能用 127.0.0.1(心跳会失败)
mysql -uroot -P9030 -h127.0.0.1 -e "ALTER SYSTEM ADD BACKEND '172.26.114.122:9050';"
# 3. 启动 BE
cd /opt/app/doris/be && ./bin/start_be.sh --daemon
```
**停止顺序相反**:先 `be/bin/stop_be.sh` 再 `fe/bin/stop_fe.sh`。
|
|
```bash
# FE 状态:Alive=true, IsMaster=true, Join=true
mysql -uroot -pAa123456 -P9030 -h127.0.0.1 -e "SHOW FRONTENDS\G" | grep -E 'Alive|IsMaster|Join'
# BE 状态:Alive 必须 true
mysql -uroot -pAa123456 -P9030 -h127.0.0.1 -e "SHOW BACKENDS\G" | grep -E 'Alive|Heartbeat'
# 健康检查 API(online_backend_num=1 正常)
curl http://127.0.0.1:8030/api/health
# {"msg":"success","code":0,"data":{"online_backend_num":1,"total_backend_num":1}}
# 建表冒烟测试
mysql -udba -pAa123456 -P9030 -h127.0.0.1 -e "
CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;
CREATE TABLE t1(id INT, name VARCHAR(50)) DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1 PROPERTIES('replication_num'='1');
INSERT INTO t1 VALUES(1,'alice');
SELECT * FROM t1;
DROP DATABASE test_db;"
```
|
|
```bash
# 进程
ps aux | grep -E 'DorisFE|doris_be' | grep -v grep
# 端口(FE: 9010/9020/9030/8030,BE: 9050/9060/8040)
ss -tln | grep -E ':(9010|9020|9030|8030|9050|9060|8040)'
# 日志位置
tail -100 /opt/app/doris/fe/log/fe.out
tail -100 /opt/app/doris/be/log/be.out
grep -i error /opt/app/doris/be/log/be.INFO | tail -20
```
|
|
连接 FE 后执行(Doris 3.x 语法,注意与 MySQL 的差异):
```sql
-- 连接: mysql -uroot -P9030 -h127.0.0.1(首次 root 无密码)
SET PASSWORD = PASSWORD('Aa123456');
CREATE USER 'dba'@'%' IDENTIFIED BY 'Aa123456';
-- 全局权限必须用 *.*.*(三段式,用 *.* 报 errCode=2)
GRANT ADMIN_PRIV ON *.*.* TO 'dba'@'%';
GRANT GRANT_PRIV ON *.*.* TO 'dba'@'%';
-- 资源权限只能跟 *(*.* 或 *.*.* 都是语法错)
GRANT USAGE_PRIV ON RESOURCE * TO 'dba'@'%';
```
|
|
```sql
CREATE DATABASE IF NOT EXISTS aisql;
GRANT ALL ON aisql.* TO 'dba'@'%';
```
使用 dba 连接验证:
```bash
mysql -udba -pAa123456 -P9030 -h127.0.0.1
```
```sql
SELECT USER(); -- 'dba'@'127.0.0.1'
SHOW DATABASES; -- 应能看到 aisql
SHOW GRANTS; -- GlobalPrivs 含 Admin_priv,Grant_priv;ResourcePrivs 含 Usage_priv
```
|
|
| 语句 | 错误写法 | 正确写法(Doris 3.x)|
|------|---------|---------------------|
| 管理员授权 | `GRANT ADMIN_PRIV ON *.*` | `GRANT ADMIN_PRIV ON *.*.*` |
| 授权权限 | `GRANT GRANT_PRIV ON *.*` | `GRANT GRANT_PRIV ON *.*.*` |
| 资源权限 | `GRANT USAGE_PRIV ON RESOURCE *.*` | `GRANT USAGE_PRIV ON RESOURCE *` |
| 库级授权 | — | `GRANT ALL ON aisql.*`(库级仍用两段)|
**报错特征**:
- `errCode = 2, ADMIN_PRIV ... *.*.*` → 用了 `*.*`
- `mismatched input '.' expecting 'TO'` → RESOURCE 后跟了 `*.*`
|
|
从源 Doris(如 `101.43.140.244:9030`,dba/Aa123456,库 aisql)导出:
```bash
ssh xt@101.43.140.244 "/opt/app/mysql/bin/mysqldump -udba -pAa123456 -P9030 \
-h127.0.0.1 --no-tablespaces --skip-lock-tables \
aisql test_accounts test_transactions" > aisql_dump.sql
```
**注意**:Doris 的 DDL(DUPLICATE KEY/DISTRIBUTED BY/PROPERTIES)会被 mysqldump 原样带出,目标也是 Doris 时可直接回放。
|
|
mysqldump 的 `/*!40101 SET ...*/` 条件注释与 `SET` 语句 Doris 不认,导入前必须清洗:
```bash
python3 -c "
lines = [l for l in open('aisql_dump.sql').read().split('
')
if not (l.strip().startswith('/*!') or l.strip().startswith('--')
or l.strip().startswith('SET ') or l.strip()=='')]
open('aisql_clean.sql','w').write('
'.join(lines)+'
')"
mysql -udba -pAa123456 -P9030 -h127.0.0.1 -D aisql < aisql_clean.sql
```
|
|
**行数 + 聚合值 + 抽样** 三重比对,源库与目标库一致才算迁移成功:
```sql
-- 两边执行,结果应完全相同
SELECT COUNT(*), SUM(balance), MIN(account_id), MAX(account_id) FROM test_accounts;
-- 期望: 100 | 4867898.19 | 10001 | 10100
SELECT COUNT(*), SUM(amount) FROM test_transactions;
-- 期望: 579 | 1260460.88
```
抽样比对含中文/时间的行:
```sql
SELECT * FROM test_accounts ORDER BY account_id LIMIT 3;
```
|
|
`/opt/app/doris/start_doris.sh` 与 `stop_doris.sh`(来自参考服务器,已本地化路径):
```bash
cd /opt/app/doris
./start_doris.sh # 系统设置→检查目录→启动FE→启动BE→注册检查→状态汇总
./stop_doris.sh # BE→FE 优雅停止(官方脚本),超时自动强杀兜底
./stop_doris.sh --force # 直接按端口强杀全部进程
```
脚本要点:
- 启动前检查:目录/配置/JAVA_HOME/已有进程/swap/文件句柄
- 停止按端口找进程(FE 9030/8030/9020/9010,BE 9050/9060/8040)
- 停止后清理 `.lck` 锁文件
|
|
```bash
# 完整重启(数据不丢)
/opt/app/doris/stop_doris.sh && /opt/app/doris/start_doris.sh
# 验证重启后数据仍在
mysql -udba -pAa123456 -P9030 -h127.0.0.1 -Daisql \
-e "SELECT COUNT(*) FROM test_accounts; SELECT COUNT(*) FROM test_transactions;"
```
**连接方式**:
```bash
mysql -udba -pAa123456 -P9030 -h127.0.0.1 # dba(日常使用)
mysql -uroot -pAa123456 -P9030 -h127.0.0.1 # root
mysql -udba -pAa123456 -P9030 -h<服务器IP> # 远程连接(dba@'%' 已放开)
```
**Web UI**:`http://<IP>:8030`(默认 root,首次无密码)
|
|
```sql
SHOW FRONTENDS; -- FE 存活/角色
SHOW BACKENDS; -- BE 存活/心跳/磁盘
SHOW PROC '/backends'; -- BE 明细(另一种形式)
SHOW VARIABLES LIKE 'version'; -- 版本
SHOW DATABASES; -- 库列表
SHOW GRANTS; -- 当前用户权限
```
```bash
curl http://127.0.0.1:8030/api/health # JSON 健康检查
ss -tlnp | grep -E '9030|9050' # 端口监听
```
|
|
| # | 现象/坑 | 规避 |
|---|---------|------|
| P1 | `GRANT ADMIN_PRIV ON *.*` 报 errCode=2 | Doris 3.x 用 `ON *.*.*` |
| P2 | `ON RESOURCE *.*` 语法错 | 用 `ON RESOURCE *` |
| P3 | FE/BE 绑到 docker0 IP(172.17.0.1)| 配 priority_networks 匹配 eth0 |
| P4 | `ADD BACKEND '127.0.0.1:9050'` 心跳失败 | 用 eth0 实际 IP 注册 |
| P5 | WSL2 重启后 eth0 IP 漂移 | 重装/重启前重新探测网段 |
| P6 | mysqldump 产物导入报错 | 清洗 `/*!...*/` 与 SET 行 |
| P7 | 堆内存不当(OOM 或浪费)| 按物理内存调 -Xmx / mem_limit |
| P8 | BE 启动失败/Too many open files | max_map_count≥200万 + nofile≥100万 |
|
|
**FE 起不来(9030 不监听)**:
```bash
tail -50 /opt/app/doris/fe/log/fe.out
tail -50 /opt/app/doris/fe/log/fe.log | grep -i error
```
| 症状 | 处理 |
|------|------|
| JAVA_HOME not found | fe.conf 补 `JAVA_HOME = /opt/app/doris/jdk-17` |
| 端口占用 | `ss -tlnp \| grep 9030` 杀残留进程,清 `.lck` |
| 元数据损坏 | 删 `fe/doris-meta` 重装(丢数据,仅开发环境)|
**BE 不 Alive**:
```bash
grep -i 'error\|fail' /opt/app/doris/be/log/be.INFO | tail -20
mysql -udba -pAa123456 -P9030 -h127.0.0.1 -e "SHOW BACKENDS\G" # 看 HeartbeatFailureErrMsg
```
按 P3/P4/P8 逐项排查;改过配置先 DROP 旧 BACKEND 再用正确 IP 重加。
|
|
| 位置 | 内容 |
|------|------|
| `fe/log/fe.out` | FE 标准输出(启动失败先看)|
| `fe/log/fe.log` | FE 主日志 |
| `be/log/be.out` | BE 标准输出 |
| `be/log/be.INFO` | BE 主日志 |
| `fe/doris-meta/` | FE 元数据(损坏可删,丢元数据)|
| `be/storage/` | BE 数据目录 |
```bash
ps aux | grep -E 'DorisFE|doris_be' | grep -v grep # 进程
ss -tlnp | grep -E ':(9010|9020|9030|8030|9050|9060|8040)' # 端口归属
```
|
|
| 轮次 | 方式 | 结果 | 耗时 |
|------|------|------|------|
| 第1次 | 手动逐步安装(发现 P1/P2/P6 坑)| ✅ 全过 | ~40min |
| 第2次 | db_doris_install 智能体执行 | ✅ 16项全绿 | 1m43s |
| 第3次 | dbmng skill 一键脚本 | ✅ 16项全绿 | 1m52s |
结论:脚本化后重装约 **2 分钟**(主要耗时 3.2G 解压),且零人工干预、零踩坑。
|
|
沉淀位置:`/home/xt/wks/.config/skills/dbmng/`
```bash
SKILL=/home/xt/wks/.config/skills/dbmng
bash $SKILL/scripts/install_doris.sh # 一键安装(8步全流程,幂等)
bash $SKILL/scripts/verify_doris.sh # 16项验证(全绿 exit 0)
bash $SKILL/scripts/uninstall_doris.sh --yes # 卸载(停进程+删目录+清环境变量)
```
安装脚本内置:预检→系统配置→解压→动态探测网段配置→FE 启动→BE 注册(eth0 IP)→用户初始化(正确授权语法)→种子数据(清洗后导入)→验证。
|
|
**dbmng skill**(`.config/skills/dbmng/`)注册两个智能体:
| 智能体 | 位置 | 职责 |
|--------|------|------|
| `db_doris_install` | `.config/agent/db_doris_install/` | 安装/卸载/验证/重装/排障(含坑点 P1-P8 与检查清单)|
| `db_qianyi` | `.config/agent/db_qianyi/` | 数据迁移/异构迁移/测试数据制造(八大功能)|
**种子数据**:`dbmng/seeds/aisql_seed.sql`(test_accounts 100 行 + test_transactions 579 行,幂等 DROP/CREATE)
**安装总结文档**:`dbmng/reference/20260830_doris_install_summary.md`(九章完整实战记录)
|
官方·部署前准备
官方·安装部署