news 2026/9/30 12:01:26

Oracle数据库开源监控方案:oracledb_exporter+Prometheus+Grafana实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Oracle数据库开源监控方案:oracledb_exporter+Prometheus+Grafana实战

如果你们公司还有Oracle数据库在跑,我猜你对它的监控状态大概率是不满意的。MySQL有现成的mysqld_exporter,PostgreSQL有pg_stat_statements,唯独Oracle在Prometheus生态里像个后妈养的孩子,搜遍全网都是Oracle Enterprise Manager那一套,装起来又重又难伺候,想看个实时会话数还得自己写一堆SQL。直到我把oracledb_exporter配合Grafana拉起来,用docker-compose一次性把这套监控完整落地,才算是帮Oracle也补上了一块真正能看的大屏。

这篇文章就是完整的落地记录,包括docker-compose的编排方式、oracledb_exporter的环境变量与权限配置、Grafana面板导入和告警规则配置,目标读者是手里捏着Oracle数据库、又不想被商业监控软件绑定的DBA和运维。跟着做,你可以在半小时内拿到一套能看会话、表空间、IO、等待事件和解析率的Oracle实时监控大屏,技术栈全部开源,部署依赖只有一个Docker环境。

1. 为什么是这套方案:选型背后的几层考量

1.1 Oracle传统监控方式的三座大山

先说清楚我要解决什么问题。很多公司Oracle库跑了好几年,监控却一直是最薄弱的环节,原因基本绕不开这三个:第一,Oracle Enterprise Manager(OEM)功能确实全,但它是个重量级选手,12c以后还需要独立的OMS中间件,光是安装配置就得折腾一整天,额外占用内存和CPU资源,很多中小团队根本不愿意为监控再养一套环境,所以直接放弃。第二,AWR/ADDM报告适合事后分析,你可以每天定时生成一份,但它不实时,数据库出问题的时候你看到的永远是上一个小时的快照,没法做到“抬头看大屏、低头定位问题”的效果。第三,手工查v$视图完全可行,但这不是一个可持续的方案,每次排查都要人肉连上去执行SQL,换个值班的人又得从头教一遍,更别说把监控结果共享给同事和领导。

这些传统方式不是说没用,而是它们都少了“实时可视化”和“低成本部署”这两个关键能力。监控的价值在于第一时间发现问题、快速定位瓶颈,而不是出了问题之后翻报告复盘。

1.2 oracledb_exporter的组合优势

oracledb_exporter这个项目,本质上就是帮我们把Oracle的性能视图封装成Prometheus标准格式的指标。它一出现,Oracle在Prometheus生态里那个尴尬的位置就被填上了。这个exporter能捞出来的东西覆盖了日常运维最关心的大部分维度:会话数、活跃会话数、等待事件、物理读写、SGA与PGA内存、软硬解析次数、进程数、锁和阻塞会话等等。官方默认就带了一批指标,不需要写一行SQL就能直接用。

它最大的优势还不只是“有指标”,而是它支持自定义SQL指标。什么意思?Prometheus生态里其他数据库exporter想加个指标往往要改代码重新编译,但oracledb_exporter允许你通过一个YAML文件声明自定义查询,比如我想监控表空间使用率、数据文件增长趋势、某个业务表的分区情况,这些都可以自己写SQL加进去。这样一来,标准指标覆盖通用场景,自定义指标覆盖业务场景,两者一叠加,监控深度就上来了。

1.3 为什么要用docker-compose部署

我知道有人会说,exporter不就是个Python或者Go写的程序吗,直接装在本机跑不行吗?行,但坑很多。oracledb_exporter要连Oracle,必须依赖Oracle客户端库,本地装的话需要折腾Instant Client、ORACLE_HOME环境变量、LD_LIBRARY_PATH这些,稍微不小心就给你报个DPI-1047的错误,非常劝退。用容器之后,镜像里把客户端库这些依赖全部打包好了,你只需要传一个DATA_SOURCE_NAME连接串进去,它自己就能连上数据库。

docker-compose则是把这套方案里的三件事用一份YAML编排了起来:Prometheus负责抓取和存储指标,oracledb_exporter负责连Oracle采集,Grafana负责展示和告警。三个容器一套拉起,生产环境和测试环境直接复制目录就能迁移,以后换机器、换团队交接都极其省事。这套模式在我看来是这个场景下部署成本最低、维护最轻松的方案。

2. 部署前准备:Oracle账号权限与镜像选择

2.1 创建最小权限监控账号

动手之前先把Oracle这边的账号准备好。我强烈建议不要拿sys或者system这种超级账号去连监控,风险太大,而且也不必要。正确做法是创建一个专属的监控账号,只给读权限。登录数据库执行下面的SQL:

CREATE USER ORAMON IDENTIFIED BY "这里换成你的强密码"; GRANT CONNECT TO ORAMON; GRANT SELECT_CATALOG_ROLE TO ORAMON;

SELECT_CATALOG_ROLE这个角色是重点,它涵盖了v$视图和大部分性能数据字典视图的查询权限,oracledb_exporter默认采集的那些指标基本都是靠这个角色撑起来的。如果你后面要写自定义SQL,查询到了dba_data_files、dba_free_space这些数据字典,可能还需要单独补授权。我自己的经验是,直接把下面三条也加上,省得后面排查权限问题:

GRANT SELECT ON dba_data_files TO ORAMON; GRANT SELECT ON dba_free_space TO ORAMON; GRANT SELECT ON dba_tablespaces TO ORAMON;

这里多说一句,监控账号的原则是最小权限,你只需要它读性能视图和空间视图,不需要它建表、建索引、操作数据。所以除了CONNECT和SELECT权限,其他一概不给。

2.2 连接参数与镜像版本

创建完账号,需要确认Oracle的连接信息。这里有个很容易含糊的点:oracledb_exporter的DSN格式推荐用服务名(service_name),而不是SID。格式是这样的:

ORAMON/password@//10.0.0.1:1521/ORCLPDB1

如果你用的是容器数据库(CDB)里的PDB,这里填的就是PDB的服务名;如果用非容器数据库,填实例的服务名即可。不确定的话,在Oracle上用lsnrctl status或者查v$active_services都能看到服务名列表。

镜像方面,oracledb_exporter有Go版和Python版两个分支。我明确推荐用Go版,也就是iamseth/oracledb-exporter:latest这个tag。Python版虽然老,但构建镜像时对Oracle Instant Client的打包方式很坑,跑起来各种依赖缺失,排查起来非常头疼。Go版是单二进制,镜像干净,启动即用,稳定性好得多。Grafana镜像我用的grafana/grafana:10.4.2,Prometheus用的prom/prometheus:v2.47.2,这两个版本在我实际使用中都很稳,没必要盲目追新。

2.3 Docker环境准备

最后确认一下本机的Docker环境。装好Docker之后,先跑一下docker compose version,确认Compose V2能用。我遇到过一些老机器上只有docker-compose(V1)没有docker compose,语法上稍有差异,建议直接升级到2.20以上的版本。端口方面,规划好三个映射端口:Prometheus的9090、exporter的9161、Grafana的3000。生产环境上如果这三个端口被占用,记得在防火墙和安全组里放行,不然外部访问不到。

3. docker-compose全套配置:从零到一

3.1 目录结构规划

配置写起来其实不多,但目录结构我还是习惯提前规划好,不然文件一多就乱。我用的目录结构是这样的:

oracle-monitor/ ├── docker-compose.yml ├── prometheus/ │ ├── prometheus.yml │ └── rules/ │ └── oracle-alerts.yml └── oracledb-exporter/ └── custom_metrics.yaml

prometheus目录下的rules是放告警规则的,oracledb-exporter目录下放自定义指标文件。以后要加新指标、加告警,找文件的位置一目了然,不会出现“我记得配置写在哪个文件里来着”的情况。

3.2 docker-compose.yml详解

下面是完整的docker-compose.yml,我用了Compose V2的语法,没有写version字段,因为新版Compose已经不建议写这个字段了,写了反而会提示废弃告警。直接看配置:

services: prometheus: image: prom/prometheus:v2.47.2 container_name: prometheus volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - ./prometheus/rules:/etc/prometheus/rules - prometheus_data:/prometheus ports: - "9090:9090" command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=15d' restart: unless-stopped oracledb-exporter: image: iamseth/oracledb-exporter:latest container_name: oracledb-exporter environment: - DATA_SOURCE_NAME=ORAMON/你的密码@//10.0.0.1:1521/ORCLPDB1 - CUSTOM_METRICS=/metrics/custom_metrics.yaml volumes: - ./oracledb-exporter/custom_metrics.yaml:/metrics/custom_metrics.yaml:ro ports: - "9161:9161" restart: unless-stopped grafana: image: grafana/grafana:10.4.2 container_name: grafana environment: - GF_SECURITY_ADMIN_PASSWORD=换成你的Grafana密码 volumes: - grafana_data:/var/lib/grafana ports: - "3000:3000" depends_on: - prometheus restart: unless-stopped volumes: prometheus_data: grafana_data:

几个关键点我展开说。DATA_SOURCE_NAME是oracledb_exporter连接Oracle的唯一入口,格式必须是用户名/密码@//主机:端口/服务名,如果你密码里有特殊字符,比如@、/这些,最好先做一下URL编码,或者干脆把密码换成不含特殊字符的,这能省掉很多排查DSN解析问题的精力。

CUSTOM_METRICS环境变量指定了自定义指标文件在容器内的路径,我们通过volume把宿主机上的custom_metrics.yaml挂载进去,Exporter启动时就会加载。Prometheus的--storage.tsdb.retention.time=15d是数据保留策略,我建议保留15天到30天就够做趋势分析了。这个值是Prometheus启动命令传入的,不能写在配置文件里,容易踩坑。

Grafana的默认管理员账号是admin,密码通过GF_SECURITY_ADMIN_PASSWORD指定,如果你不设置这个环境变量,Grafana启动后会生成一个随机密码,到时候还得去容器日志里翻,很麻烦,所以一定在环境变量里直接写清楚。实际生产环境建议配一个密码管理工具管理,不要明文写在版本库里。

3.3 prometheus.yml与告警规则文件

Prometheus的抓取配置同样重要,路径是./prometheus/prometheus.yml,示例配置如下:

global: scrape_interval: 15s evaluation_interval: 15s rule_files: - "/etc/prometheus/rules/*.yml" scrape_configs: - job_name: 'oracledb' static_configs: - targets: ['oracledb-exporter:9161'] labels: instance: 'pro-oracle-01'

这个文件里我标了两个关键信息。一个是scrape_interval,我统一用了15秒。可能有人想用5秒,觉得数据更实时,但我要提醒你,exporter每次被拉取时都会执行一堆v$视图查询,频率越高,对Oracle的压力越大。对于会话数、IO这种变化不是特别剧烈的指标,15秒完全够用。之前见过有人把间隔改成3秒,直接把数据库的CPU干高了不少,后来改回15秒才恢复。

另一个是targets里写了oracledb-exporter:9161,这是容器网络里的服务名。Prometheus容器和oracledb-exporter容器在同一个compose网络里,可以直接通过服务名互相访问,不需要填宿主机IP,这就是compose编排带来的好处。labels里的instance字段很重要,它用来区分是哪套数据库。如果你以后要多套Oracle,每个exporter容器加一个不同的instance标签,在Grafana里就能按实例切换。

规则文件是挂在./prometheus/rules目录下的,Prometheus启动时通过rule_files配置加载。后面配置告警时,我们会在这个目录下建一个oracle-alerts.yml。

3.4 自定义指标:表空间使用率与增长趋势

oracledb_exporter默认指标里其实已经有了一些表空间相关的指标,但使用率、剩余空间这种业务上最关心的数据还是自己写SQL更灵活。我这里的custom_metrics.yaml就是一个声明式文件,内容举例如下:

queries: - metricName: oracle_tablespace_used_percent labels: - TABLESPACE_NAME sql: | SELECT df.tablespace_name AS TABLESPACE_NAME, ROUND((df.bytes - fs.free_bytes) / df.bytes * 100, 2) AS used_percent FROM (SELECT tablespace_name, SUM(bytes) AS bytes FROM dba_data_files GROUP BY tablespace_name) df JOIN (SELECT tablespace_name, SUM(bytes) AS free_bytes FROM dba_free_space GROUP BY tablespace_name) fs ON df.tablespace_name = fs.tablespace_name metricType: GAUGE

这个查询的逻辑说起来不难。dba_data_files里存的是每个数据文件的已分配空间,dba_free_space里存的是每个表空间的剩余空间,两个表按表空间名关联,就能算出来每个表空间已用多少、还剩多少、使用率是多少。查询结果里TABLESPACE_NAME作为label,used_percent就是指标值。在Grafana里,同一个指标会根据TABLESPACE_NAME自动拆成多条曲线,每个表空间一条线,看起来非常直观。

写这个文件的时候有个细节要注意,YAML的字段名在不同版本的exporter里略有差异,老Python版和新Go版对queries、metricName这些字段的大小写和结构定义不完全一致。我自己遇到过字段名不对导致Exporter启动时加载失败的情况,排查了半天才发现是版本差异。稳妥起见,写完文件后先启动容器,看日志确认没有custom metrics相关的报错,再用curl验证指标有没有出现。

到这里,配置层面已经全部完成,接下来就是拉起服务、导入面板、配告警,把整个监控真正跑起来。

4. 完整实操流程:启动、验证、导入大屏

4.1 启动服务并验证exporter指标

目录和配置文件都准备好了,在oracle-monitor目录下执行:

docker compose up -d

这个命令会自动拉取三个镜像并启动容器。第一次启动可能会等一会儿,因为要下载镜像。等命令执行完,先看下所有容器的状态:

docker compose ps

理想状态是三个容器都是Up状态。如果哪个容器反复重启,用日志命令看报错:

docker compose logs oracledb-exporter

排除问题后,先验证exporter是否在正常采集Oracle指标。直接在宿主机上请求一下它的metrics接口:

curl -s http://localhost:9161/metrics | grep oracle_sessions

如果你看到了类似oracle_sessions_count、oracle_sessions_active_count这样的指标,说明exporter已经和Oracle建立了连接,指标采集是通的。这一步是整个链路的第一步,它通了,后面的事才顺。

4.2 Grafana数据源与面板导入

接下来打开浏览器访问http://localhost:3000,用admin和你设置的密码登录。Grafana的监控看板配置指导其实很简单,核心就两步:先加数据源,再导入面板。

左侧菜单进入Configuration -> Data sources -> Add data source,选择Prometheus类型。在URL一栏填http://prometheus:9090,这里要注意,Grafana容器访问Prometheus容器,要用容器网络里的服务名,不能填localhost或者宿主机IP。填完之后点Save & test,看到绿色的成功提示就代表连通了。

然后就是导入面板。进入Dashboards -> Import,在“Import via dashboard model”或者“Find and import dashboards”的输入框里填官方推荐的面板ID:8699。这是oracledb_exporter项目官方推荐的“OracleDB Exporter Overview”模板,直接Load加载。加载之后会让你选择数据源,选刚才配好的Prometheus,然后Import完成。

导入完你就能看到整个Oracle监控大屏了,上面有会话、IO、内存、Top SQL等很多个Panel。如果某个Panel显示NoData,多半是数据源的指标名和面板里写死的指标名不完全匹配,后面排障部分我再细说怎么处理。整体来说,导入之后大屏基本可用,再根据业务微调面板就够了。

4.3 告警规则配置实战

监控大屏可看还不够,告警才是真正能在半夜帮你扛事的东西。Grafana从8.0开始自带统一告警,可以直接在页面上配规则,不需要额外装组件。我的做法是:表空间使用率这种关键指标走Prometheus的rule文件,而像会话数超阈值这种更灵活的条件就放Grafana里配。

先说Prometheus rule文件的写法,路径在./prometheus/rules/oracle-alerts.yml,示例内容如下:

groups: - name: oracle-alerts rules: - alert: OracleTablespaceUsageHigh expr: oracle_tablespace_used_percent > 90 for: 5m labels: severity: warning annotations: summary: "表空间 {{ $labels.TABLESPACE_NAME }} 使用率超过 90%"

这个规则的含义是:当oracle_tablespace_used_percent这个指标大于90,并且连续保持5分钟,就触发告警。5分钟这个for字段是我个人强烈建议加上的,很多表空间使用率会上下抖动,如果一超过阈值就报警,告警疲劳很快就会出现,最后大家都不看了。加个持续时间的门槛,能过滤掉大量无效告警。

配置好规则文件后,Prometheus会每15秒重新评估一次规则,但rule文件更新后需要重载配置才生效,执行:

docker compose exec prometheus kill -HUP 1

然后在Prometheus的Alerts页面就能看到规则的状态了。Grafana里的告警配置也类似,进入Alerting -> Alert rules -> New alert rule,写查询表达式、设置阈值和持续时间,通知渠道可以接邮件、钉钉、企业微信等。如果你已经有现成的告警平台,也可以通过webhook中转。我自己在Grafana里只留了少数几条对实时性要求高的规则,其他的都统一走Prometheus了。

5. 大屏怎么看:核心指标深度解读

5.1 会话与等待事件透视图

会话数这个指标看起来简单,但很多人没分清“当前会话数”和“活跃会话数”的区别。当前会话数(sessions_count)是Oracle里所有连接到实例的会话总数,包括空闲会话;活跃会话数(active_count)则是正在占用CPU、等待I/O或执行SQL的会话。判断数据库是否忙,要看活跃会话数,而不是总会话数。比如有300个会话连着,但活跃的只有10个,说明数据库整体很闲,那些会话都是应用连接池的空闲连接。

等待事件则是性能诊断的核心维度。打开大屏上等待事件相关的面板,你会看到类似db file sequential read、log file sync、enq: TX - row lock contention这样的名字。这些事件其实是在告诉你会话正在等什么。我整理了一个速查表,方便对照:

等待事件含义排查方向
db file sequential read单块读,常见于索引扫描检查SQL执行计划是否走索引、I/O延迟是否正常
db file scattered read多块读,常见于全表扫描关注SQL是否需要大量全表扫描、表碎片情况
log file sync会话等待日志写入检查redo日志磁盘I/O、是否频繁commit
enq: TX - row lock contention行锁竞争查看阻塞源SQL、事务是否长时间未提交

5.2 内存与解析态势

SGA和PGA是两个基础内存区域,SGA共享给所有会话用,PGA是每个会话私有的。oracledb_exporter把这两块的总大小和当前使用情况都暴露出来了,你可以直接在大屏上看到内存有没有逼近上限。如果PGA使用率长期很高,或者出现PGA自动管理频繁调整的情况,说明排序、hash join这类内存密集型操作比较多,要么优化SQL,要么适当调大PGA_AGGREGATE_TARGET。

比内存更值得关注的是解析率的指标。软解析(soft parse)表示SQL在共享池里找到了相同的语句,可以直接复用执行计划;硬解析(hard parse)则需要从头解析SQL、生成执行计划,代价大到可能是软解析的几十倍。大屏上如果看到硬解析比例居高不下,大概率是应用的SQL没有用绑定变量,每次都生成新的SQL文本。这个问题的典型症状是CPU高、共享池碎片化、大量library cache lock。处理方向很简单,推动开发在Java的PreparedStatement或者Python的绑定参数里把变量传进去,硬解析率马上就会降下来。

5.3 表空间与增长趋势分析

表空间问题是我在实际运维中遇到最多的突发事故来源,而它恰恰是完全可以提前预防的。大屏上表空间使用率面板显示了每个表空间的使用百分比,但我的习惯是重点看增长趋势,而不是只看当前值。因为你看到某个表空间已经用到88%的时候,可能已经晚了,如果它的每日增长量是3%,那么一周后就会满。提前一周看趋势,完全来得及做扩容或者清理。

oracledb_exporter默认提供的表空间指标已经包含一部分,但如果你按我前面配置的custom_metrics,多了使用率百分比和按表空间分组的灵活视图,用起来会更顺手。这里我再说一个进阶思路:把表空间剩余预估天数作为一个自定义指标加进去,用剩余空间除以最近N天的日均增长量,得到一个“还能撑多少天”的值。有了这个指标,你可以在还剩30天的时候规划扩容,而不是在还剩2天的时候紧急救火。

6. 踩坑实录:常见问题与排查方法

6.1 连接与权限类问题

这套方案部署起来不算复杂,但我在实践和帮同事救火的过程中,积累了下面这份问题速查表,基本覆盖了我见过的绝大多数情况:

现象可能原因解决方法
exporter容器反复重启,日志报ORA-12154DSN里的服务名格式不对确认使用//主机:端口/服务名格式,检查服务名是否存在
日志报ORA-12514监听里没有注册该服务名用lsnrctl status确认服务名,或者连接PDB服务名
日志报ORA-01031权限不足监控用户缺少性能视图权限执行GRANT SELECT_CATALOG_ROLE TO ORAMON;
日志报DPI-1047 Cannot locate a 64-bit Oracle Client library使用了旧版Python镜像换成iamseth/oracledb-exporter:latestGo版镜像
自定义指标加载失败YAML字段名与当前版本不匹配对照对应版本exporter的GitHub examples目录修改

这里重点说一下ORA-12154,这是新手遇到最多的一个。很多人习惯用SID的格式写DSN,比如ORAMON/pass@10.0.0.1:1521/orcl,但exporter文档明确推荐的是服务名格式,也就是ORAMON/pass@//10.0.0.1:1521/ORCLPDB1。多了//和后面的形式,差别很大。如果不确定服务名,在Oracle里执行show parameter service_names,或者直接查v$active_services拿准确值。

6.2 数据与面板类问题

服务正常启动了,指标也在出,但Grafana面板却不显示数据,这个问题也特别常见。我遇到过的场景基本有两类:一类是面板导入后选择的数据源不对,或者Prometheus里根本没抓到exporter的target。先到Prometheus的Targets页面确认一下oracledb这个job的状态是UP,如果不是,就看exporter日志;如果Prometheus那边是UP的,但Grafana面板没数据,那大概率是面板默认选择的指标名和你环境里的指标名不一致。

另一类情况是表空间自定义指标生成了,但Grafana里的曲线只有一条线,或者全是NaN。曲线只有一条线,通常是SQL查询里没有把表空间名作为label返回;全是NaN,则说明SQL返回了NULL或者非数字的内容。解决方法是先直接在Oracle客户端里执行一遍你的自定义SQL,确认查询结果本身是正确的,再回过来检查YAML里的labels字段和metricType配置。面板和指标之间的问题,我建议始终用curl -s http://localhost:9161/metrics | grep 指标名来验证数据源头的输出,数据源头对了,再往Grafana那边查。

6.3 我踩过一次的“报警轰炸”坑

最后说一个特别实际的教训。最开始我把表空间告警直接设成超过85%就触发,结果上线第一天晚上就连续收到几十条告警。因为很多表空间的使用率是波动的,AWR快照、临时段分配这些操作会让使用率瞬间冲高又回落,85%阈值触发了一阵子又恢复正常,很快又触发。后来我加上了for: 10m的条件,并且把阈值调整到90%,告警才变得真正有意义。这里我的建议是:告警规则上线前先在测试环境观察一周,把历史数据拉出来看看正常业务波动范围,再定阈值和时间窗口。如果一开始不确定,宁可先宽松一点,也别为了“安全感”把阈值设得太死,告警疲劳一旦形成,运维反而会忽略真正的故障。

结尾

这套东西我在生产环境跑了快两年,最大的感受不是Grafana大屏多好看,而是它把Oracle从一个沉默的黑盒变成了随时可以用数字说话的系统。以前数据库出性能问题,我都要翻半天AWR或者手动登上去查v$视图,现在直接在浏览器里打开大屏,会话、等待事件、IO、表空间一目了然,定位问题的速度提升了好几个量级。最后再分享一个小技巧:如果你以后有多套Oracle库要监控,最好在prometheus.yml里把每个exporter的instance标签起得规范一些,然后回到Grafana面板上添加一个模板变量,用instance来做下拉切换。这样一套面板就能巡完所有生产实例,不用为每个库复制一整个dashboard,维护成本会低非常多。后续如果还想深入,可以把表空间的日增量预估、AWR报告自动推送这些也做成自定义指标,整个监控体系就会越来越顺手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 12:00:50

C++模板元编程:从黑魔法到现代编译期计算的性能进化

很多C开发者听到“模板元编程”这五个字,第一反应往往是:那是大神用来炫技的黑魔法,跟我没关系。我入行这些年,见过太多人一提到模板就把头摇成拨浪鼓,觉得那是《C Templates》里才有的高阶玩法,是只有写Bo…

作者头像 李华
网站建设 2026/9/30 12:00:08

npm.ps1无法加载?一文搞定PowerShell执行策略报错

很多朋友第一次在Windows上跑前端项目时,都会撞上同一个报错:装好了Node.js,兴冲冲地在项目目录里敲下npm run dev,结果终端毫不留情地弹出一行红字——npm : 无法加载文件 D:\app\nodejs\npm.ps1,因为在此系统上禁止运…

作者头像 李华
网站建设 2026/9/30 11:59:42

CSP第一题满分攻略:签到题题型、读入输出与边界条件汇总

CSP 第一题在选手圈子里有个外号叫"签到题",意思是你进考场先把这题的分揣兜里,再去啃后面那些真正要动脑子的。但有意思的是,每年考完总有人在群里喊"第一题只过了 60%",问题往往不是不会写,而是…

作者头像 李华
网站建设 2026/9/30 11:59:13

合规性折旧:知识资产在等保/GDPR/信创下的技术性归零与保值实践

知识资产不是‘存下来’就完事:一次技术视角的合规归零诊断在企业知识管理系统(KMS)开发或运维中,我们常默认‘文件上传成功 权限配置完成 资产入库’。但真实生产环境中,一份合同PDF或制度Word可能在通过CI/CD发布后…

作者头像 李华
网站建设 2026/9/30 11:58:51

C#上位机Socket与PLC通信:连接后的稳定运行实战

简介:面向C#上位机开发者与工业自动化入门者的TCP通信学习笔记,聚焦基于Socket类库实现与PLC服务器之间的通信连接,适用于需要掌握上位机与设备数据交互的初学者。文中以Visual Studio 2019为开发环境,配合TIA Portal与S7-PLCSIM …

作者头像 李华
网站建设 2026/9/30 11:58:51

JetBrains扩展注解:让IDE帮你拦截并发、国际化和参数越界问题

把这个标题拆开看,其实是在说一件事:怎么用JetBrains IDE里的扩展注解,把“代码里看不见的约定”变成“IDE能帮你检查的规则”。很多人以为注解只是写给同事看的注释,但在IDEA里,注解更像是一套给静态分析引擎的信号灯…

作者头像 李华