一、项目前言&背景
1.1 业务痛点
日常企业数据场景存在两大核心痛点:
- 业务人员不会写SQL:运营、产品想要统计订单数据,必须依赖后端/DBA开发人员写查询,沟通成本高、报表交付慢;
- DBA重复低效工作:海量慢SQL人工分析EXPLAIN执行计划、手动设计索引,重复性运维工作占用大量精力;
- 传统NL2SQL工具安全性差:很多开源工具未做SQL拦截,存在删改表、篡改数据风险,密钥硬编码极易泄露。
1.2 项目核心价值
本项目基于openEuler国产操作系统+MySQL8.0+腾讯云TokenHub大模型聚合平台,打造轻量化一体化智能SQL工具:
- 自然语言一键生成只读SQL:仅允许
SELECT语句,自动拦截INSERT/UPDATE/DELETE/ALTER等危险操作; - 自动执行查询+AI业务解读:查询结果表格化输出,大模型自动生成通俗易懂的业务总结,替代人工报表;
- 全自动SQL性能调优:解析
EXPLAIN执行计划,定位全表扫描、文件排序等瓶颈,直接输出可执行索引创建SQL与优化后语句; - 双端交互入口:服务器终端交互式菜单 + Streamlit可视化Web面板,运维/业务人员按需使用;
- 完善安全机制:敏感账号密钥独立
.env配置文件,文件权限设置600,全程不打印明文密码。
1.3 开发周期&人员
- 开发人数:1~3人小组单人开发均可
- 总周期:3个工作日(每日8小时)
- Day1:openEuler环境部署、MySQL8.0搭建、大模型API申请、运维知识点梳理
- Day2:Python分层脚本开发、NL2SQL、SQL调优、终端主程序联调
- Day3:多场景测试、提示词优化、权限安全加固、整体验收
二、整体技术方案与四层架构
2.1 软硬件环境清单
硬件环境
| 类别 | 参数规格 | 用途 |
|---|---|---|
| 虚拟机/云ECS | CPU≥2核,内存≥4GB,磁盘≥20GB | 运行openEuler、MySQL、Python程序 |
软件环境
| 软件 | 版本 | 作用 |
|---|---|---|
| 操作系统 | openEuler/RHEL9 | 底层运行系统,国产适配 |
| MySQL | 8.0.45 | 存储电商订单测试数据order_info |
| Python | 3.11.9(源码编译) | 项目开发主语言 |
| 大模型平台 | 腾讯云TokenHub | 兼容DeepSeek V4 Pro、Qwen3.5-Plus |
| Web框架 | Streamlit | 零前端可视化网页面板 |
| Python依赖 | pymysql、python-dotenv、langchain-openai、tabulate | 数据库连接、配置读取、大模型调用、表格渲染 |
网络&账号资源
- 服务器外网可访问443端口,用于调用大模型API;
- 腾讯云账号完成实名认证,获取TokenHub API Key。
2.2 四层分层架构详解
层级1:接入交互层(双入口)
面向运维、业务、开发人员,两种使用模式完全复用底层逻辑:
- 命令行终端:
python3 main.py交互式菜单,适合服务器本地运维快速排查; - Web可视化页面:Streamlit
web_main.py,浏览器访问,图形化输入、一键复制SQL、表格展示结果,非技术人员友好。
层级2:Python程序核心层(5个核心文件,解耦设计)
main.py:项目总调度入口,封装NL2SQL查询、AI总结、SQL调优三大核心业务,终端/Web共用底层函数;mysql_client.py:数据库统一封装类,管理连接、安全校验、执行SQL、获取EXPLAIN执行计划;prompts.py:提示词工程统一管理,内置NL2SQL、SQL调优两套Prompt,附带正则提取纯净SQL工具;web_main.py:Streamlit前端页面,输入校验、页面美化、结果渲染;.env:独立配置文件,存放数据库账号、大模型密钥,敏感信息与代码隔离。
层级3:底层数据持久层
openEuler虚拟机部署MySQL8.0.45,创建testdb数据库、order_info电商订单表,预置20条测试订单数据,作为项目唯一数据源。
层级4:AI大模型服务层
腾讯云TokenHub聚合平台作为统一AI网关,一套代码无缝切换多款开源大模型,统一鉴权、计费、运维,兼容OpenAI标准接口。
三、完整环境搭建实操(openEuler)
3.1 openEuler系统初始化
1)关闭防火墙与SELinux
# 关闭SELinux永久生效sed-i'7s/enforcing/disabled/'/etc/selinux/config# 关闭并禁用防火墙systemctl disable--nowfirewalld systemctl status firewalld# 修改主机名hostnamectl set-hostname serverbash2)时间同步+安装系统依赖
# 配置阿里云时间服务器vim/etc/chrony.conf server ntp.aliyun.com iburst systemctl restart chronyd chronyc sources# 安装编译全套依赖dnfinstall-ygcc gcc-c++makecmake zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel libffi-devel tk-develwgettarvimtree net-tools openssh-server3.2 源码编译安装Python3.11.9
# 上传源码至/usr/local/srccd/usr/local/srctar-zxvfPython-3.11.9.tgzcdPython-3.11.9# 编译配置./configure--prefix=/usr/local/python3.11 --enable-sharedmake-j$(nproc)&&makeinstall# 配置动态链接库echo"/usr/local/python3.11/lib">/etc/ld.so.conf.d/python311.conf ldconfig# 全局软链接,不覆盖系统Pythonln-s/usr/local/python3.11/bin/python3.11 /usr/local/bin/python3ln-s/usr/local/python3.11/bin/pip3.11 /usr/local/bin/pip3bash# 验证安装python3-Vpip3-V# 校验SSL(大模型接口必备)python3-c"import ssl; print(ssl.OPENSSL_VERSION)"配置阿里pip镜像源
mkdir~/.pipvim~/.pip/pip.conf[global]index-url=http://mirrors.aliyun.com/pypi/simple/[install]trusted-host=mirrors.aliyun.com# 安装项目依赖pip3install--upgradepip pip3installpymysql python-dotenv tabulate langchain langchain-openai streamlit3.3 MySQL8.0.45部署初始化
1)解压安装并初始化
# 上传MySQL压缩包,移动至/usr/local/mysqltar-xvfmysql-8.0.45-linux-glibc2.28-x86_64.tar.xzmvmysql-8.0.45-linux-glibc2.28-x86_64 /usr/local/mysqlcd/usr/local/mysql# 创建mysql用户组与系统用户groupaddmysqluseradd-r-gmysql-s/sbin/nologin mysqlmkdirdatachmod-R750datachown-Rmysql:mysql /usr/local/mysql# 初始化数据库(保存输出的初始密码)bin/mysqld--initialize--user=mysql--basedir=/usr/local/mysql--datadir=/usr/local/mysql/data# 后台启动bin/mysqld_safe--user=mysql&2)修改root密码、配置systemd服务
# 登录数据库修改密码bin/mysql-uroot-pmysql>alter user'root'@'localhost'identified with mysql_native_password by'123456';mysql>flush privileges;exit;# 编写my.cnf配置vim/etc/my.cnf[client]port=3306socket=/tmp/mysql.sock[mysqld]port=3306basedir=/usr/local/mysql datadir=/usr/local/mysql/data tmpdir=/tmp socket=/tmp/mysql.sock character-set-server=utf8mb4 collation-server=utf8mb4_general_ci default-storage-engine=INNODB log_error=error.log# systemd服务文件vim/usr/lib/systemd/system/mysqld.service[Unit]Description=MySQL ServerAfter=network.target remote-fs.target nss-lookup.target[Service]Type=notifyUser=mysqlGroup=mysqlExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnfLimitNOFILE=65535LimitNPROC=65535Restart=on-failureRestartPreventExitStatus=1TimeoutSec=0[Install]WantedBy=multi-user.target# 重载并开机自启systemctl daemon-reload systemctlenable--nowmysqld.service# 配置环境变量echo"export PATH=$PATH:/usr/local/mysql/bin">>~/.bash_profilesource~/.bash_profile mysql-V3)创建业务库与订单测试表
createdatabasetestdb;usetestdb;createtableorder_info(idBIGINTAUTO_INCREMENTPRIMARYKEYCOMMENT'订单ID',user_idINTCOMMENT'用户ID',order_nameVARCHAR(200)COMMENT'商品名称',pay_amountDECIMAL(10,2)COMMENT'支付金额',create_timeDATETIMECOMMENT'下单时间')ENGINE=InnoDBCOMMENT='电商订单业务表';-- 插入20条测试数据INSERTINTOorder_info(user_id,order_name,pay_amount,create_time)VALUES(1001,'智能手机',2999.00,'2026-05-01 10:20:00'),(1001,'有线入耳耳机',199.00,'2026-05-02 14:10:00'),(1002,'14英寸轻薄笔记本电脑',5499.00,'2026-05-03 09:30:00'),(1002,'无线蓝牙鼠标',89.00,'2026-05-03 09:35:00'),(1003,'平板学习机',1799.00,'2026-05-04 11:05:00'),(1003,'平板专用保护壳',49.00,'2026-05-04 11:08:00'),(1004,'机械游戏键盘',349.00,'2026-05-05 16:42:00'),(1004,'电竞头戴耳机',459.00,'2026-05-05 16:48:00'),(1005,'大屏智能电视',3299.00,'2026-05-06 08:15:00'),(1005,'电视壁挂支架',129.00,'2026-05-06 08:20:00'),(1006,'无线快充充电器',129.00,'2026-05-03 13:22:00'),(1006,'降噪蓝牙耳机',399.00,'2026-05-03 13:25:00'),(1007,'电竞显示器',1899.00,'2026-05-07 10:10:00'),(1007,'显示器增高支架',79.00,'2026-05-07 10:15:00'),(1008,'折叠平板支架',39.00,'2026-05-04 15:30:00'),(1008,'便携充电宝',159.00,'2026-05-04 15:33:00'),(1009,'台式游戏主机',6999.00,'2026-05-08 09:05:00'),(1009,'电竞防滑鼠标垫',59.00,'2026-05-08 09:08:00'),(1010,'手机钢化膜',29.00,'2026-05-05 17:12:00'),(1010,'桌面收纳支架',45.00,'2026-05-05 17:16:00');3.4 腾讯云TokenHub大模型API配置
- 访问腾讯云官网,注册并实名认证;
- 进入TokenHub控制台 → API Key管理 → 创建密钥,保存
sk-xxx密钥; - 模型推荐:
deepseek-v4-pro/Qwen3.5-Plus(无多余思考链,避免SQL解析报错)。
四、项目核心代码分层讲解
4.1 项目目录创建
mkdir-p/opt/mysql_ai_toolscd/opt/mysql_ai_toolstouchmain.py mysql_client.py prompts.py web_main.py .env4.2 .env 配置文件(安全加固 chmod 600)
# MySQL数据库配置 MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_USER=root MYSQL_PASSWORD=123456 MYSQL_DB=testdb # 腾讯云TokenHub大模型配置 LLM_API_KEY=sk-jUJebmj56mEQhhBep04A3AIaVlVV2NA97F45iimZ*** LLM_BASE_URL=https://tokenhub.tencentmaas.com/v1 LLM_MODEL_NAME=deepseek-v4-pro LLM_TEMPERATURE=0权限加固(关键安全操作)
chmod600/opt/mysql_ai_tools/.env4.3 mysql_client.py 数据库封装&SQL安全拦截
核心亮点:内置危险SQL黑名单,仅放行SELECT查询,防止数据误删改;统一管理连接释放,自动获取EXPLAIN执行计划。
# -*- coding: utf-8 -*-importpymysqlimportosimportrefromdotenvimportload_dotenv load_dotenv()classMysql80Client:def__init__(self):self.host=os.getenv("MYSQL_HOST","127.0.0.1")self.port=int(os.getenv("MYSQL_PORT","3306"))self.user=os.getenv("MYSQL_USER","root")self.password=os.getenv("MYSQL_PASSWORD","")self.database=os.getenv("MYSQL_DB","testdb")self.conn=Noneself.connect()defconnect(self):try:self.conn=pymysql.connect(host=self.host,port=self.port,user=self.user,password=self.password,database=self.database,charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)exceptExceptionase:raiseException(f"数据库连接失败:{str(e)}")@staticmethoddef_check_sql_safety(sql:str)->None:# 危险操作黑名单,拦截增删改、DDL语句sql_trim=sql.strip().upper()danger_keywords=["INSERT","UPDATE","DELETE","DROP","ALTER","CREATE","TRUNCATE","REPLACE"]forkwindanger_keywords:ifre.search(r'\b'+re.escape(kw)+r'\b',sql_trim):raiseException(f"安全拦截:禁止执行{kw}语句,仅支持SELECT")defexecute_query(self,sql:str):self._check_sql_safety(sql)withself.conn.cursor()ascursor:cursor.execute(sql)columns=[desc[0]fordescincursor.description]rows=cursor.fetchall()returncolumns,rowsdefget_explain_plan(self,sql:str):self._check_sql_safety(sql)explain_sql=f"EXPLAIN{sql}"withself.conn.cursor()ascursor:cursor.execute(explain_sql)columns=[desc[0]fordescincursor.description]rows=cursor.fetchall()returncolumns,rowsdefclose(self):ifself.connandnotself.conn._closed:self.conn.close()4.4 prompts.py 提示词工程+SQL提取工具
统一管理两套Prompt,严格约束大模型输出格式,搭配正则三层匹配提取纯净SQL,解决模型输出杂乱问题。
# -*- coding: utf-8 -*-importreclassUnifiedPrompt:# 全局订单表结构,统一维护一处TABLE_SCHEMA=""" 表名: order_info (订单信息表) 字段说明: - id: 订单ID (主键,BIGINT) - user_id: 用户ID (INT) - order_name: 商品名称 (VARCHAR) - pay_amount: 支付金额 (DECIMAL(10,2)) - create_time: 下单时间 (DATETIME) """# 自然语言转SQL提示词NL_TO_SQL_PROMPT=f""" 你是严谨MySQL8.0工程师,根据用户业务需求生成标准SELECT语句。 表结构:{TABLE_SCHEMA}强制规则: 1. 仅输出SELECT,禁止任何增删改、建表语句; 2. 只能使用给定字段,禁止编造字段; 3. SQL关键字大写,中文别名无空格; 4. SQL包裹在```sql ```代码块,不输出多余解释文字; 用户需求:{{user_input}} """# SQL性能调优提示词SQL_TUNE_PROMPT=f""" 你是资深MySQL DBA,根据SQL+EXPLAIN执行计划输出优化方案。 表结构:{TABLE_SCHEMA}待分析SQL:{{sql_input}} 执行计划数据:{{explain_data}} 输出要求: 1. 点明核心性能问题(全表扫描、文件排序、无索引等); 2. 给出可直接执行的建索引SQL; 3. 输出优化改写后的完整SQL; 4. 分点简洁输出。 """# 三层正则提取纯净SQL@staticmethoddefextract_sql(response_text:str)->str:ifnotresponse_text:return""# 优先级1:标准markdown sql代码块match=re.search(r"```sql\s*(.*?)\s*```",response_text,re.DOTALL|re.IGNORECASE)ifmatch:returnmatch.group(1).strip()# 优先级2:兜底匹配SELECT开头语句match=re.search(r"(SELECT\s+.*?;)",response_text,re.DOTALL|re.IGNORECASE)ifmatch:returnmatch.group(1).strip()return""prompt_helper=UnifiedPrompt()4.5 main.py 核心调度+终端交互入口
实现两大核心业务:自然语言查询、SQL性能调优;内置SQL清洗工具,兼容各类模型输出格式,终端菜单循环交互。
完整代码见项目PDF文档,核心逻辑:
- nl2sql_query:自然语言生成SQL、执行查询、AI业务总结
- sql_tune_analyze:获取EXPLAIN、AI分析性能瓶颈、输出调优方案
- main_cli:终端交互式菜单
4.6 web_main.py Streamlit可视化网页
核心能力
- 左侧侧边栏导航,切换「数据查询」「SQL调优」两大页面;
- 输入前置校验:区分自然语言输入与SQL输入,防止用户操作混淆;
- 美化页面CSS、表格、代码复制按钮、加载动画;
- 完全复用
main.py底层业务函数,无重复开发。
4.7 Streamlit后台systemd常驻服务
vim/etc/systemd/system/mysql-ai-web.service[Unit]Description=InnoAI SQL Streamlit Web服务After=network.target mysqld.service[Service]Type=simpleUser=rootWorkingDirectory=/opt/mysql_ai_toolsExecStart=/usr/local/python3.11/bin/python3-mstreamlit run web_main.py--server.address0.0.0.0--server.port8501--server.headlesstrueRestart=alwaysRestartSec=3StandardOutput=journalStandardError=journal[Install]WantedBy=multi-user.target# 重载并开机自启systemctl daemon-reload systemctlenable--nowmysql-ai-web# 查看服务器IP,浏览器访问 ip:8501hostname-I五、项目功能实测演示
5.1 自然语言查询测试用例
测试需求:1001、1002、1003 每个用户的订单总消费金额与订单笔数,按总消费从高到低排序
1)自动生成SQL
SELECTuser_idAS用户ID,SUM(pay_amount)AS总消费金额,COUNT(id)AS订单笔数FROMorder_infoWHEREuser_idIN(1001,1002,1003)GROUPBYuser_idORDERBY总消费金额DESC2)查询结果表格
| 用户ID | 总消费金额 | 订单笔数 |
|---|---|---|
| 1002 | 5588.00 | 2 |
| 1001 | 3198.00 | 2 |
| 1003 | 1848.00 | 2 |
3)AI自动业务总结
- 用户分层明显:1002为高价值用户,总消费5588元,客单价远超其他两位用户;
- 三位用户订单笔数均为2单,复购节奏高度相似;
- 样本数据订单数量统一,建议扩大数据范围验证用户消费规律。
5.2 SQL性能调优实测
待优化SQL
SELECTuser_idAS用户ID,SUM(pay_amount)AS总消费金额,COUNT(id)AS订单笔数FROMorder_infoWHEREuser_idIN(1001,1002,1003)GROUPBYuser_idORDERBY总消费金额DESC执行计划问题
type=ALL全表扫描、Using temporary; Using filesort临时表+文件排序,无任何索引命中。
AI输出优化方案
- 创建覆盖索引
ALTERTABLEorder_infoADDINDEXidx_user_id_pay_amount(user_id,pay_amount);- 优化改写SQL
SELECTuser_idAS用户ID,SUM(pay_amount)AS总消费金额,COUNT(*)AS订单笔数FROMorder_infoWHEREuser_idIN(1001,1002,1003)GROUPBYuser_idORDERBY总消费金额DESC;六、项目安全&稳定性设计
6.1 数据安全防护
- SQL黑白名单拦截:仅放行SELECT,自动拦截所有增删改、DDL危险语句;
- 配置文件权限隔离:
.env设置600权限,仅root可读,不打印账号密钥明文; - 数据库使用只读逻辑,无数据写入/修改操作,避免业务数据损坏。
6.2 程序稳定性保障
- 全流程异常捕获:数据库连接、大模型API、SQL语法错误统一捕获,程序不崩溃;
- 输入容错:空白输入、超长需求、无匹配数据友好提示;
- SQL标准化清洗:统一处理中文标点、全角空格、关键字粘连,解决模型输出语法报错;
- 数据库连接自动关闭,避免长连接占用资源。
6.3 系统兼容性
- 系统:openEuler/RHEL国产Linux兼容;
- 数据库:锁定MySQL8.0.45,适配InnoDB索引规范;
- 大模型:兼容所有OpenAI接口标准MaaS平台,一键切换DeepSeek/Qwen系列模型。
七、踩坑记录&解决方案
- Python编译后SSL缺失:编译时必须带上
openssl-devel依赖,否则大模型HTTPS接口调用失败; - 大模型输出携带思考链,SQL提取失败:选用不带推理思考的模型,增加正则过滤多余文本;
- Streamlit外部无法访问:启动参数添加
--server.address 0.0.0.0,开放局域网访问; - MySQL8.0认证插件报错:修改root账号认证方式为
mysql_native_password; - .env密钥泄露风险:必须执行
chmod 600,禁止其他用户读取配置文件。
八、项目拓展优化方向
- 权限精细化:增加Web页面登录鉴权,区分普通查询用户与调优管理员;
- 多表关联支持:扩展表结构,支持多表JOIN场景NL2SQL生成;
- 慢SQL批量分析:支持批量导入多条SQL,批量输出索引优化方案;
- Docker容器化:打包openEuler、MySQL、Python环境,一键部署;
- 本地私有大模型适配:兼容本地部署Qwen/DeepSeek离线模型,无需外网API;
- 导出报表:查询结果支持Excel下载,自动生成业务分析报告文件。
九、项目总结
- 落地价值:轻量化一站式AI数据库工具,零SQL基础业务人员可自主查询数据,解放DBA重复调优工作,适配中小企业轻量化数据平台;
- 技术学习点:覆盖国产openEuler运维、MySQL8.0深度运维、Python分层架构、大模型Prompt工程、NL2SQL落地、Streamlit低代码Web开发、systemd服务部署;
- 适用人群:计算机专业实训项目、运维工程师、后端开发、AI应用开发学习者完整实战案例;
- 部署门槛:低配虚拟机即可运行,3天完整从零搭建完成,代码模块化易二次开发改造。