本文档风哥主要介绍TiDB内存使用与配置优化,包括内存使用的概念、内存使用的组成部分、内存使用的影响、内存监控规划、内存优化策略、内存监控工具配置、内存瓶颈分析方法等内容,风哥教程参考TiDB官方文档性能优化相关内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 内存使用的概念
内存使用是指TiDB进程在运行过程中占用的系统内存资源。内存使用的判断标准:学习交流加群风哥微信: itpux-com
- 内存使用率:持续超过80%
- 系统响应:系统响应缓慢,SQL执行时间长
- OOM:内存不足导致进程被系统kill
- 交换空间使用:频繁使用交换空间
1.2 内存使用的组成部分
TiDB内存使用的组成部分:
## 1. 进程内存
– 代码段:存储可执行代码
– 数据段:存储全局变量和静态变量
– 堆内存:动态分配的内存
– 栈内存:存储函数调用和局部变量
## 2. 内存池
– Go语言内存池:管理Go语言的内存分配
– TiDB内存池:管理TiDB的内存分配
– 连接池:管理数据库连接
– 线程池:管理线程资源
## 3. 缓存
– 表缓存:缓存表结构信息
– 索引缓存:缓存索引数据
– 结果集缓存:缓存查询结果
– 计划缓存:缓存执行计划
## 4. 内存使用的主要模块
– SQL解析:解析SQL语句
– 查询优化:生成执行计划
– 执行引擎:执行SQL语句
– 事务管理:管理事务
– 日志处理:处理binlog和redo log
– 网络通信:处理客户端连接和数据传输
## 5. 内存使用的影响因素
– 并发连接数:并发连接数越多,内存使用越大
– 查询复杂度:复杂查询需要更多的内存
– 数据量:处理的数据量越大,内存使用越大
– 配置参数:内存相关的配置参数影响内存使用
– 系统负载:系统负载越高,内存使用越大
风哥提示:
1.3 内存使用的影响
内存使用的影响:
- 系统响应缓慢:内存不足导致系统响应缓慢
- OOM:内存不足导致进程被系统kill
- 性能下降:内存不足导致性能下降
- 稳定性问题:内存不足导致系统不稳定
- 其他资源竞争:内存不足可能导致CPU和IO等其他资源的竞争
Part02-生产环境规划与建议
2.1 内存监控规划
内存监控规划要点:
## 1. 监控目标
– 实时监控内存使用率
– 及时发现内存高使用情况
– 分析内存使用趋势
– 为内存优化提供依据
## 2. 监控指标
– 内存使用率:整体内存使用率
– 进程内存:TiDB进程的内存使用情况
– 交换空间:交换空间的使用情况
– 内存分配:内存分配和释放情况
– 内存碎片:内存碎片率
## 3. 监控工具
– TiDB Dashboard:查看TiDB进程的内存使用情况
– Prometheus:存储和查询内存相关指标
– Grafana:展示内存监控面板
– free/top:实时查看系统内存使用情况
– sar:收集系统内存使用统计信息
## 4. 监控频率
– 实时监控:1-5秒
– 定期监控:1-5分钟
– 离线分析:每日或每周
## 5. 告警配置
– 告警阈值:内存使用率超过80%持续5分钟
– 告警级别:紧急、重要、警告
– 告警渠道:邮件、短信、微信
– 告警策略:避免告警风暴
2.2 内存优化策略
内存优化策略:
## 1. 配置优化
– 调整内存相关参数:根据服务器内存大小调整参数
– 限制内存使用:设置内存使用上限
– 优化缓存配置:调整缓存大小
– 合理设置并发度:根据内存大小调整并发度
## 2. SQL优化
– 优化查询语句:简化查询逻辑,减少内存使用
– 减少查询数据量:只查询需要的字段
– 避免大结果集:使用LIMIT限制结果集大小
– 优化JOIN操作:减少JOIN的复杂度
– 批量处理:减少小查询的数量
## 3. 系统优化
– 增加内存资源:添加内存或升级内存
– 优化系统配置:调整系统参数,如vm.swappiness
– 关闭不必要的服务:减少系统内存使用
– 合理分配资源:使用cgroups等工具分配内存资源
## 4. 业务优化
– 错峰处理:避开业务高峰期进行批量操作
– 限流:对高并发请求进行限流
– 缓存:使用缓存减少数据库访问
– 异步处理:将耗时操作改为异步处理
## 5. 架构优化
– 读写分离:将读请求分散到多个TiDB实例
– 水平扩展:增加TiDB实例数量
– 分片:将数据分散到多个TiKV节点
– 负载均衡:使用负载均衡分散请求
2.3 内存容量规划
内存容量规划:
## 1. 容量评估学习交流加群风哥QQ113257174
– 业务峰值QPS:评估业务高峰期的QPS
– 单查询内存消耗:测量单个查询的内存消耗
– 并发连接数:评估系统的并发处理能力
– 未来增长:考虑业务增长对内存的需求
## 2. 容量计算
– 所需内存 = 基础内存 + 并发连接数 × 单连接内存消耗 + 缓存内存 + 预留内存
– 基础内存:TiDB进程的基础内存消耗
– 单连接内存消耗:每个连接的内存消耗
– 缓存内存:表缓存、索引缓存等
– 预留内存:预留20-30%的内存
## 3. 容量扩展
– 垂直扩展:增加内存容量
– 水平扩展:增加TiDB实例数量
– 混合扩展:同时进行垂直和水平扩展
## 4. 容量监控
– 定期监控内存使用率
– 分析内存使用趋势
– 预测未来内存需求
– 及时进行容量扩展
## 5. 容量优化
– 优化SQL和业务逻辑,减少内存消耗
– 合理配置TiDB参数,提高内存利用率
– 使用缓存和读写分离,减少内存负载
Part03-生产环境项目实施方案
3.1 内存监控工具配置
3.1.1 TiDB Dashboard内存监控
## 1. 访问TiDB Dashboard
http://192.168.1.10:2379/dashboard
## 2. 查看内存使用情况
– 点击左侧菜单”实例” -> “TiDB”
– 查看每个TiDB实例的内存使用情况
– 查看内存使用的历史趋势
## 3. 查看慢SQL
– 点击左侧菜单”SQL语句” -> “慢查询”
– 分析消耗内存较多的SQL语句
– 查看SQL执行计划
## 4. 查看进程列表
– 点击左侧菜单”实例” -> “TiDB” -> “进程列表”
– 查看每个进程的内存使用情况
– 识别占用内存较多的进程
3.1.2 Prometheus和Grafana内存监控
## 1. 配置Prometheus收集内存指标
$ vim prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
– job_name: ‘tidb’
static_configs:
– targets: [‘192.168.1.10:10080’]
– job_name: ‘node’
static_configs:
– targets: [‘192.168.1.10:9100’, ‘192.168.1.20:9100’, ‘192.168.1.30:9100’]
## 2. 安装Node Exporter
$ wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz
$ tar -xzf node_exporter-1.3.1.linux-amd64.tar.gz
$ cd node_exporter-1.3.1.linux-amd64
$ ./node_exporter
## 3. 配置Grafana面板
– 登录Grafana:http://192.168.1.10:3000
– 添加Prometheus数据源
– 导入内存监控面板
– 配置内存使用率告警
## 4. 查看内存监控面板
– 查看整体内存使用率
– 查看进程内存使用情况
– 查看交换空间使用情况
– 查看内存使用趋势
3.2 内存瓶颈分析方法
3.2.1 内存瓶颈分析步骤
## 1. 收集内存使用数据
– 使用free命令查看内存使用率:free -h
– 使用top命令查看进程内存使用情况:top -o %MEM
– 使用pidstat查看进程的内存使用情况:pidstat -r 1
– 使用Prometheus查询历史内存数据
## 2. 识别内存密集型进程
– 查看占用内存最多的进程:top -o %MEM
– 查看TiDB相关进程的内存使用情况:pidstat -r -p $(pgrep -f tidb-server)
– 分析进程的内存使用模式:是堆内存还是栈内存
## 3. 分析SQL语句
– 查看慢SQL日志:tail -f /tidb/app/tidb/log/tidb-slow.log
– 分析消耗内存较多的SQL语句:使用EXPLAIN查看执行计划
– 识别大结果集和复杂查询
## 4. 分析系统资源
– 查看CPU使用情况:top
– 查看磁盘IO情况:iostat -x 1
– 查看网络情况:iftop -i eth0
– 分析是否存在其他资源瓶颈
## 5. 定位根因
– 确定内存高使用的根本原因
– 分析是SQL问题、系统问题还是配置问题
– 评估影响范围和严重程度
3.2.2 常用分析工具
## 1. free/top/htop
– 功能:实时查看系统和进程的内存使用情况
– 适用场景:实时监控内存使用情况
– 优势:简单易用,实时性强
## 2. pidstat
– 功能:查看进程的内存使用情况
– 适用场景:分析特定进程的内存使用情况
– 优势:可以查看每个进程的详细内存使用情况
## 3. sar
– 功能:收集和报告系统内存使用统计信息
– 适用场景:分析内存使用趋势
– 优势:可以查看历史内存使用情况
## 4. TiDB Dashboard
– 功能:查看TiDB进程的内存使用情况和慢SQL
– 适用场景:分析TiDB相关的内存使用情况
– 优势:集成在TiDB中,使用方便
## 5. Prometheus和Grafana
– 功能:存储和可视化内存相关指标
– 适用场景:分析内存使用趋势和历史数据
– 优势:强大的查询和可视化能力
## 6. go tool pprof
– 功能:分析Go程序的内存使用情况
– 适用场景:深入分析TiDB的内存使用情况
– 优势:可以查看内存分配的详细信息
3.3 内存优化实施方案
3.3.1 配置优化实施
## 1. 调整内存相关参数
$ vim /tidb/app/tidb/conf/tidb.toml
[performance]
# 限制查询内存使用
tidb_mem_quota_query = 1073741824 # 1GB
# 限制事务内存使用
tidb_mem_quota_transaction = 1073741824 # 1GB
# 调整并发度
max-procs = 8
[server]
# 调整连接池大小
max-connections = 1000
[txn]
# 调整事务大小
txn-total-size-limit = 104857600 # 100MB
## 2. 验证配置效果
– 查看配置是否生效:SHOW VARIABLES LIKE ‘%mem%’;
– 查看内存使用率:free -h
– 查看进程内存使用情况:top -o %MEM
## 3. 优化缓存配置
$ vim /tidb/app/tidb/conf/tidb.toml
[performance]
# 调整表缓存大小
table-cache-size = 10000
# 调整计划缓存大小
prepared-plan-cache-size = 1000
## 4. 验证缓存效果
– 查看缓存使用情况:SHOW GLOBAL STATUS LIKE ‘%cache%’;
– 查看查询执行时间:SET profiling = 1; SELECT * FROM fgedu_users WHERE id = 1; SHOW PROFILES;
3.3.2 SQL优化实施
## 1. 分析慢SQL
– 查看慢SQL日志:tail -f /tidb/app/tidb/log/tidb-slow.log
– 分析SQL执行计划:EXPLAIN SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;
– 识别性能瓶颈:如大结果集、复杂JOIN等
## 2. 优化SQL语句
– 减少查询字段:只查询需要的字段
– 避免使用SELECT *:减少数据传输和内存使用
– 优化JOIN操作:使用合适的JOIN类型
– 避免子查询:尽量使用JOIN替代子查询
– 合理使用分页:使用LIMIT进行分页
## 3. 验证优化效果
– 执行优化后的SQL语句
– 查看执行时间:SET profiling = 1; SELECT name FROM fgedu_users WHERE name LIKE ‘test%’ LIMIT 10; SHOW PROFILES;
– 查看内存使用率:free -h
Part04-生产案例与实战讲解
4.1 内存使用检测与分析
4.1.1 内存使用检测
## 1. 实时监控内存使用率
$ free -h
# 输出示例
total used free shared buff/cache available
Mem: 32G 28G 2.0G 1.0G 2.0G 2.0G
Swap: 8.0G 4.0G 4.0G
## 2. 查看进程内存使用情况
$ top -o %MEM
# 输出示例
top – 10:00:00 up 1 day, 2:00, 2 users, load average: 2.50, 3.20, 4.80
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 20.0 us, 5.0 sy, 0.0 ni, 75.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 tidb 20 0 8.0g 6.0g 100m S 15.0 18.7 1:30.00 tidb-server
## 3. 查看TiDB进程的内存使用情况
$ pidstat -r -p $(pgrep -f tidb-server)
# 输出示例
Linux 5.4.0-100-generic (fgedu.net.cn) 04/09/2026 _x86_64_ (8 CPU)
10:00:00 UID PID minflt/s majflt/s VSZ RSS %MEM Command
10:00:01 1000 12345 10.0 0.0 8388608 6291456 18.7 tidb-server
## 4. 查看慢SQL日志
$ tail -f /tidb/app/tidb/log/tidb-slow.log
# 输出示例
[2026/04/09 10:00:00.000 +08:00] [SLOW] [session.go:1137] [“slow query”] [conn=12345] [user=fgedu] [db=fgedudb] [table_ids=”[1000]”] [start_time=”2026-04-09 10:00:00.000″] [elapsed=10.000s] [sql=”SELECT * FROM fgedu_users WHERE name LIKE ‘%test%'”] [digest=”abcdef123456″]
4.1.2 内存使用分析
## 1. 分析SQL执行计划
mysql> EXPLAIN SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;
# 输出示例
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
| id | estRows | task | access object | operator info | actRows | execution info | memory | disk | transaction info | operator info |
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
| TableReader_6 | 1000.00 | root | | data:TableScan_5 | 1000 | time:0.1s | 1.00 KB | N/A | | N/A |
| └─TableScan_5 | 1000.00 | cop[tikv] | table:fgedu_users | range:[-inf,+inf], keep order:false | 1000 | time:0.1s | N/A | N/A | | N/A |
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
## 2. 分析系统资源使用情况
$ top
# 输出示例
top – 10:00:00 up 1 day, 2:00, 2 users, load average: 2.50, 3.20, 4.80
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 20.0 us, 5.0 sy, 0.0 ni, 75.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 tidb 20 0 8.0g 6.0g 100m S 15.0 18.7 1:30.00 tidb-server
$ iostat -x 1
# 输出示例
Linux 5.4.0-100-generic (fgedu.net.cn) 04/09/2026 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
20.00 0.00 5.00 0.00 0.00 75.00
device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 10.00 20.00 819.20 1638.40 163.84 0.10 3.33 1.00 4.00 0.33 0.99
## 3. 定位根因
– 根因:SQL语句返回大结果集,导致内存使用高
– 影响:系统响应缓慢,其他查询受到影响
– 解决方案:限制结果集大小,添加索引
4.2 内存优化实战
4.2.1 配置优化实战
## 1. 问题:内存使用率高
– 服务器配置:32GB内存
– TiDB内存使用:28GB
– 内存使用率:87.5%
## 2. 解决方案:调整内存相关参数
– 修改tidb.toml配置文件:
[performance]
# 限制查询内存使用
tidb_mem_quota_query = 536870912 # 512MB
# 限制事务内存使用
tidb_mem_quota_transaction = 536870912 # 512MB
## 3. 验证优化效果
– 查看配置是否生效:
mysql> SHOW VARIABLES LIKE ‘%tidb_mem_quota%’;
# 输出示例
+————————-+————+|
| Variable_name | Value |
+————————-+————+|
| tidb_mem_quota_query | 536870912 |
| tidb_mem_quota_session | 1073741824 |
| tidb_mem_quota_transaction | 536870912 |
+————————-+————+|
– 查看内存使用率:
$ free -h
# 输出示例
total used free shared buff/cache available
Mem: 32G 20G 10G 1.0G 2.0G 10G
Swap: 8.0G 0.0G 8.0G
## 4. 查看进程内存使用情况:
$ top -o %MEM
# 输出示例
top – 10:05:00 up 1 day, 2:05, 2 users, load average: 2.50, 3.20, 4.80
Tasks: 200 total, 1 running, 199 sleeping, 0 stopped, 0 zombie
%Cpu(s): 20.0 us, 5.0 sy, 0.0 ni, 75.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12345 tidb 20 0 8.0g 4.0g 100m S 15.0 12.5 1:35.00 tidb-server
4.2.2 SQL优化实战
## 1. 问题:大结果集导致内存高使用
– SQL语句:SELECT * FROM fgedu_users WHERE name LIKE ‘%test%’;
– 结果集大小:1000行
– 内存使用:1GB
## 2. 解决方案:限制结果集大小,添加索引
– 添加索引:ALTER TABLE fgedu_users ADD INDEX idx_name (name);
– 优化SQL语句:SELECT name FROM fgedu_users WHERE name LIKE ‘test%’ LIMIT 10;
## 3. 优化后的执行计划
mysql> EXPLAIN SELECT name FROM fgedu_users WHERE name LIKE ‘test%’ LIMIT 10;
# 输出示例
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
| id | estRows | task | access object | operator info | actRows | execution info | memory | disk | transaction info | operator info |
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
| Limit_4 | 10.00 | root | | offset:0, count:10 | 10 | time:0.01s | 1.00 KB | N/A | | N/A |
| └─IndexReader_3 | 10.00 | root | | index:IndexRangeScan_2 | 10 | time:0.01s | 1.00 KB | N/A | | N/A |
| └─IndexRangeScan_2 | 10.00 | cop[tikv] | table:fgedu_users, index:idx_name(name) | range:[“test”,”test”), keep order:false | 10 | time:0.01s | N/A | N/A | | N/A |
+————————-+———-+———–+—————+——————————–+————————-+———+——+————————–+———————–+
## 4. 验证优化效果
– 执行优化后的SQL语句:
mysql> SET profiling = 1;
mysql> SELECT name FROM fgedu_users WHERE name LIKE ‘test%’ LIMIT 10;
mysql> SHOW PROFILES;
# 输出示例
+———-+————+————————————————+|
| Query_ID | Duration | Query |
+———-+————+————————————————+|
| 1 | 0.00123456 | SELECT name FROM fgedu_users WHERE name LIKE ‘test%’ LIMIT 10 |
+———-+————+————————————————+|
– 查看内存使用率:
$ free -h
# 输出示例
total used free shared buff/cache available
Mem: 32G 20G 10G 1.0G 2.0G 10G
Swap: 8.0G 0.0G 8.0G
4.3 内存优化效果验证
4.3.1 性能测试
## 1. 使用sysbench进行内存性能测试
$ sysbench memory –memory-block-size=1K –memory-total-size=100G –memory-access-mode=rnd run
# 输出示例
Memory speed:
operations performed: 104857600 (1048576.00 ops/sec)
General statistics:
total time: 100.0000s
total number of events: 104857600
Latency (ms):
min: 0.00
avg: 0.00
max: 0.10
approx. 95 percentile: 0.00
## 2. 使用tpcc进行数据库性能测试
$ tiup bench tpcc –host 192.168.1.10 –port 4000 –user fgedu –password password –db fgedudb –warehouses 100 prepare
$ tiup bench tpcc –host 192.168.1.10 –port 4000 –user fgedu –password password –db fgedudb –warehouses 100 –time 300 run
# 输出示例
[INFO] Benchmark finished, TPM: 10000, QPS: 100000
## 3. 验证优化前后的性能对比
– 优化前:TPM 5000, QPS 50000, 内存使用率 87.5%
– 优化后:TPM 10000, QPS 100000, 内存使用率 62.5%
– 性能提升:100%
– 内存使用率下降:25%
4.3.2 监控验证
## 1. 查看内存使用率趋势
– 登录Grafana:http://192.168.1.10:3000
– 查看内存使用率面板
– 分析优化前后的内存使用率变化
## 2. 查看SQL执行时间趋势
– 登录TiDB Dashboard:http://192.168.1.10:2379/dashboard
– 查看SQL语句面板
– 分析优化前后的SQL执行时间变化
## 3. 查看系统响应时间
– 使用ping命令:ping 192.168.1.10
– 使用curl命令:curl -s -o /dev/null -w “%{time_total}\n” http://192.168.1.10:4000/
– 分析优化前后的响应时间变化
## 4. 查看业务指标
– 查看页面响应时间
– 查看业务处理时间
– 查看并发用户数
– 分析优化前后的业务指标变化
Part05-风哥经验总结与分享
5.1 内存优化最佳实践
内存优化最佳实践:
- 配置优化:根据服务器内存大小调整内存相关参数,限制内存使用上限
- SQL优化:优化SQL语句和索引,减少内存使用
- 系统优化:调整系统参数,提高内存利用率
- 业务优化:错峰处理,避免业务高峰期的内存竞争
- 架构优化:水平扩展,增加TiDB实例数量,分散内存负载
- 监控预警:建立内存监控和预警机制,及时发现和处理内存高使用
- 容量规划:根据业务需求和增长趋势,合理规划内存容量
- 持续优化:定期分析内存使用情况,持续优化系统性能
5.2 内存高使用预防策略
内存高使用预防策略:
- 性能测试:在上线前进行充分的性能测试,发现和解决潜在的内存瓶颈
- 监控预警:设置合理的内存使用率告警阈值,及时发现内存高使用
- 容量规划:根据业务增长趋势,提前规划内存容量
- 代码审查:对SQL语句和应用代码进行审查,避免性能问题
- 索引优化:根据查询模式,合理设计和维护索引
- 并发控制:合理控制并发度,避免内存资源竞争
- 缓存策略:使用缓存减少数据库访问,降低内存负载
- 负载均衡:使用负载均衡分散内存负载
5.3 内存性能调优技巧
## 1. 配置调优技巧
– 调整tidb_mem_quota_query:限制单个查询的内存使用
– 调整tidb_mem_quota_transaction:限制单个事务的内存使用
– 调整max-connections:根据内存大小调整连接数
– 调整table-cache-size:合理设置表缓存大小
– 调整prepared-plan-cache-size:合理设置计划缓存大小
## 2. SQL调优技巧
– 使用EXPLAIN分析执行计划:了解SQL的执行方式
– 添加合适的索引:避免全表扫描
– 优化JOIN操作:使用合适的JOIN类型和顺序
– 减少查询字段:只查询需要的字段
– 批量处理:减少小查询的数量
– 使用LIMIT:限制结果集大小
## 3. 系统调优技巧
– 调整vm.swappiness:减少交换空间的使用
– 调整vm.overcommit_memory:合理设置内存过度分配策略
– 调整vm.overcommit_ratio:合理设置内存过度分配比例
– 关闭不必要的服务:减少系统内存使用
– 使用cgroups限制进程内存使用:避免单个进程占用过多内存
## 4. 业务调优技巧
– 错峰处理:避开业务高峰期进行批量操作
– 限流:对高并发请求进行限流
– 缓存:使用Redis等缓存减少数据库访问
– 异步处理:将耗时操作改为异步处理
– 批量操作:合并多个小操作为批量操作
## 5. 架构调优技巧
– 读写分离:将读请求分散到多个TiDB实例
– 水平扩展:增加TiDB实例数量
– 分片:将数据分散到多个TiKV节点
– 负载均衡:使用HAProxy或Nginx进行负载均衡
– 微服务架构:将业务拆分为多个微服务,分散内存负载
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
