ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SMP数据库连接实操指南:驱动、连接池与事务处理全解析

SMP数据库连接实操指南:驱动、连接池与事务处理全解析 这是SMP软件制作平台语言基础知识的第三十七篇。前面讲了变量、流程控制、函数、文件处理今天终于轮到数据库连接这一块。很多朋友在SMP上写完业务逻辑卡在“怎么把数据存进数据库”这一步或者一个连接串调了一下午还是连不上这篇就是来解决这个的。适合正在学SMP的初级开发也适合打算把SMP接到达梦、MySQL、Oracle等数据库上的老手参考。读完你会掌握SMP里连接数据库的标准流程能用dbx数据库连接工具快速验证配置也会知道达梦数据库连接工具在开发中到底扮演什么角色。1. 数据库连接在SMP平台中的定位与设计思路1.1 数据库连接到底在解决什么问题数据库连接说白了就是让SMP程序能和数据库“通上话”。SMP平台擅长快速搭建业务应用但应用里总有客户信息、订单状态、流水日志这些要长期留存的内容不可能全部放在内存或本地文件里。这时候就需要把SMP程序和一个外部数据库对接起来由数据库负责存储、索引、事务、并发控制SMP负责业务逻辑和界面展示。有人可能会问直接用数据库自带的命令行工具、或者用可视化工具不就能操作库了吗这里有个根本区别。那些工具是人敲命令用的SMP程序需要在自动化流程里按指令读写数据。比如一个审批流程表单提交后自动往订单表插入一条记录再用SQL查询状态更新页面。这个场景必须由代码建立连接、执行SQL、获取结果整套动作交给人工去点显然不现实。所以SMP语言把“连接数据库”抽成了一个基础设施能力。它不是让你每次拼一个字符串连上去那么野蛮而是提供了一套相对固定的方式统一管理驱动、连接参数、连接池、异常处理。理解了这一点你就知道为什么后面所有操作都围绕“连接对象”来展开。1.2 为什么SMP要自带连接工具与驱动策略实际项目里数据库种类五花八门。有的客户用MySQL有的用Oracle还有不少政府和企业项目点名要达梦数据库。SMP平台不能只针对一种数据库做适配于是它的策略是把驱动管理、连接串解析、方言转换统一收口对外呈现出一套基本一致的连接语法。这里就要提到dbx数据库连接工具。很多人第一次接触这个名字会以为是个专业插件其实它是SMP配套的可视化连接配置工具专门用来新建连接、填参数、点一下“测试连接”再把配置保存成命名连接。它的好处是不用在代码里写一长串看不懂的字符串保存后SMP脚本只需要引用名字就行。可以把它理解成配置的“登记窗口”SMP执行引擎真正建立连接时还是按照登记好的参数去连接目标数据库。达梦数据库连接工具则是达梦官方提供的一套管理维护工具用于直接操作达梦数据库实例比如查看表空间、管理用户、执行SQL。它和dbx配合使用时一个偏数据库本身的治理一个是SMP应用侧的连接配置。开发期我用达梦工具把用户权限、表结构、字符集都确认好再到dbx里做应用连接测试两边互补能省掉大把定位问题的时间。2. 环境准备与连接配置核心细节2.1 驱动与依赖先给SMP准备好“翻译官”数据库驱动是连接过程中最容易忽略、又最容易出错的一环。打个比方SMP说中文数据库说自己的方言驱动就是那个翻译官。没有驱动或者驱动版本不对双方各说各话程序只能报错。在SMP平台里驱动一般以jar包或动态库的形式存在。以Java体系为例连接达梦数据库会用到DmJdbcDriver18之类的驱动包连接MySQL用mysql-connector-j连接Oracle用ojdbc8。自己动手前第一件事就是确认平台的驱动目录里放了对应版本的jar包并且路径正确。有个特别容易踩的坑是版本不匹配。数据库大版本升级后旧驱动可能还能连但部分新特性会失效反过来新驱动连接特别老的数据库也可能出现协议不支持。我的习惯是先在SMP自带的组件清单里查一下支持的数据库版本区间或者启动一个最小测试工程跑通再说。千万不要图省事直接拷贝一个网上随便下的驱动包有的驱动包看着文件名一样实际JDK编译版本、数据库兼容版本完全不同。2.2 连接字符串参数拆解不管用dbx工具还是直接写连接串本质上都是在描述五个要素主机、端口、数据库名、用户名、密码。再往后才是字符集、超时时间、连接池开关这些附加项。把这些参数理解透了连接问题基本就解决了一半。主机和端口要一起看。有些开发机装了数据库后只监听127.0.0.1换成另一台机器远程访问就提示连接拒绝。端口也要确认清楚MySQL默认3306Oracle默认1521达梦数据库默认5236。SMP里的连接串一般写成类似CONNECT TO dm8://192.168.10.25:5236/TESTDB USER SYSDBA IDENTIFIED BY password如果密码里带着、#、%这类特殊字符就很容易被连接串解析器误判。最稳妥的办法是用dbx工具保存命名连接不要在代码里反复拼密码实在要拼先看平台手册里有没有转义符号支持。字符集参数也是大头建议直接指定UTF-8让客户端、服务端、表结构保持一个编码口径不然中文写入后查出来全是一堆问号。2.3 连接方式选择直连还是连接池连接数据库有两种基础玩法直连和连接池。直连很好理解每次需要访问数据库时新建一个连接用完立即销毁。这种方式代码简单适合脚本工具、低频任务。但它的问题也很明显一次连接包含网络握手、认证、会话创建短则几十毫秒长则几百毫秒一旦业务请求量大起来光建连接就把数据库拖垮。连接池的思路是提前创建一批连接放池子里谁要用就取一条用完归还而不是真的关闭。SMP的连接池参数一般有最小连接数、最大连接数、空闲超时、最大等待时间。配置连接池后第一次请求稍慢后面都从池里复用性能瞬间提起来。比如一个订单导入功能循环插入一万条数据如果每条都新建连接大概率跑到一半就超时或拖垮数据库换成连接池效果完全不一样。什么时候该调大最大连接数没有绝对公式可以从并发请求量倒推。假设一个SMP服务最多同时处理100个请求数据库最大连接数是50那池子最大连接数设为50到80比较合理。设置太大反而会让数据库端线程数膨胀拖慢整体响应。反正我的原则是池子要偏保守宁可等待也不要把数据库压垮同时把连接获取超时时间设成一个可接受的范围比如3秒到5秒。3. 在SMP中实现数据库连接的完整实操3.1 第一步创建连接对象在SMP里建立连接推荐的方式是先通过dbx工具保存一个命名连接然后脚本里直接引用。比如在dbx里新建了一个名为“ProdDB”的连接指向达梦数据库192.168.10.25:5236/TESTDB那么后面脚本就可以用下面这种写法初始化CONNECT BY NAME ProdDB AS conn如果你希望完全用代码控制连接参数也可以使用连接函数或关键字直接传入。大致逻辑上SMP的写法是把参数收集到一个连接描述里再显式建立连接DEFINE dbname dm8://192.168.10.25:5236/TESTDB DEFINE user SYSDBA DEFINE pwd ChangeMe_2024 CONNECT TO ${dbname} USER ${user} IDENTIFIED BY ${pwd}这段代码看起来平淡但我建议尽量少做。原因很简单明文密码会出现在脚本源码里一旦版本库泄露或者屏幕被截图密码就全裸了。如果平台支持优先用dbx保存连接即使连错了也能快速修改参数不用重新发布脚本。3.2 第二步执行SQL与获取结果连接建立好之后就是对数据库发号施令。SMP里执行SQL通常分两类查询和更新。查询用SELECT更新用INSERT、UPDATE、DELETE。下面是一个典型的查询过程USE CONN ProdDB EXECUTE SELECT id, name, amount FROM orders WHERE status ? PARAMS (NEW) INTO resultSet这里的?是占位符第二个参数PARAMS用来绑定值。为什么要用占位符而不是直接拼字符串因为直接拼接SQL会产生SQL注入风险而且数据库每次都要重新解析SQL语句性能也差。绑定参数会让SQL结构固定不变数据库可以复用执行计划安全性和性能都更好。拿到resultSet之后还需要遍历它。SMP里通常用循环语句处理WHILE resultSet.NEXT() BEGIN DEFINE var_id resultSet.GET(id) DEFINE var_name resultSet.GET(name) DEFINE var_amount resultSet.GET(amount) -- 处理每行数据 END如果是INSERT、UPDATE、DELETE这类更新操作关键返回值是影响行数。SMP里经常会这样用执行后判断影响行数如果等于0说明操作没有命中任何记录可以提示用户“没有可更新的数据”。多张表需要同步更新的时候操作顺序也很重要先删子表再删主表先插主表再插子表不然外键约束会挡住你。3.3 第三步事务管理与资源释放数据库连接只是一个“通道”真正保证业务一致性的靠事务。SMP里的事务控制一般有开始、提交、回滚三个动作BEGIN TRANSACTION EXECUTE INSERT INTO orders(order_no, amount) VALUES(?, ?) PARAMS (SO20240001, 299.00) EXECUTE UPDATE stock SET count count - 1 WHERE sku ? PARAMS (A10001) COMMIT如果中间任何一步失败了可以用回滚让整个操作回到起点。这一段逻辑千万别省只要涉及多张表的写操作或者对外部系统有影响的重试操作都应该包在事务里。否则可能出现订单插入成功、库存扣减失败最后对账怎么都对不上。资源释放是另一个老生常谈但永远有人犯错的地方。连接、结果集、语句对象用完之后必须归还或关闭。SMP如果开启了连接池不关闭连接会导致池里可用连接越来越少最终“连接耗尽”。我的处理习惯是把关闭操作放在异常处理的出口附近保证正常流程和出错流程都能释放资源。你可以把连接想象成图书馆座位占着不走别人永远没法用。3.4 第四步错误处理与日志埋点与数据库打交道一定要有出错预案。数据库重启、网络抖动、约束冲突随时都可能发生。SMP的异常捕获方式一般是TRY-CATCH结构出错后可以读取错误码和错误信息TRY BEGIN EXECUTE SELECT ... FROM orders END CATCH err BEGIN LOG_TO_FILE(db_error.log, 错误码: err.CODE , 信息: err.MESSAGE) END这里的日志埋点就很有价值。我把执行前、执行中、执行后的关键信息都记录一下特别是SQL、绑定参数、影响行数。问题复现时看日志基本就能还原现场。如果连接可能不稳定还会在失败后做有限次重试但记住重试次数要设上限比如三次而且每次间隔几十毫秒到几百毫秒否则数据库刚恢复就被重试请求打满了。4. 常见问题与排查技巧实录4.1 连接超时、拒绝连接、端口不通这是现场遇到最多的报错典型提示是“Connection refused”或“Connect timed out”。先别急着怀疑代码按照下面顺序排查大概率能定位。先确认数据库进程是不是真的在运行。达梦数据库可以看dmserver进程是否存在MySQL可以看mysqld服务状态。接着确认网络用ping看主机通不通再用telnet命令测端口通不通ping 192.168.10.25 telnet 192.168.10.25 5236如果ping通但telnet不通多半是防火墙、安全组或数据库监听配置的问题。云环境特别容易忽略安全组规则本地环境要检查数据库是否只监听了127.0.0.1。数据库实例建好后有些默认配置不会自动开启远程访问要在服务端设置监听地址。下面这个表是我排查时常用的参考。报错现象可能原因常用解法Connection refused数据库进程未启动 / 监听端口错误启动实例检查端口号Connect timed out网络不通 / 防火墙拦截ping、telnet分段测试放通端口连接可以建立但登录失败用户名密码错误 / 用户被锁用官方工具重置密码或解锁能连上但数据库报错数据库模式或权限限制检查用户角色和资源权限4.2 驱动类错误与版本不匹配“No suitable driver”或者“未找到驱动类”这类错误基本就是驱动没放对位置或者SMP没扫描到驱动。检查一下驱动jar包是否在平台的驱动目录里再看看平台启动日志里有没有加载记录。另一类问题是驱动版本和数据库版本不匹配例如用MySQL 8的驱动连接MySQL 5.5可能出现认证协议不兼容。达梦数据库也类似不同版本对驱动的类名可能有要求。解决办法就是去官方下载与数据库版本对应、且能匹配JDK版本的驱动包。dbx工具在这里帮助很大它内置了一批经过验证的驱动选择数据库类型后工具会主动匹配最佳驱动不用手工去查版本。4.3 字符集乱码与编码不一致中文乱码十有八九是字符集不一致。数据库本身可能用了GBKSMP工程用了UTF-8连接层没有指定字符集传输时按原始编码乱传等到查出来全成了问号。我的做法是让全链路统一使用UTF-8。在dbx工具里面把连接字符集设置为UTF-8SMP工程的源码文件编码也设置为UTF-8数据库表如果有条件也尽量采用支持中文的UTF-8字符集。如果已经是存量数据乱码已经写入那就麻了。先查表结构和数据库默认字符集再确认数据到底是存错了还是显示错了。有时原始数据没错只是查询工具显示错了这种最简单改连接字符集就能解决。真正的数据损坏只能做数据修复成本非常高所以尽量在建表和连接初期就统一字符集。4.4 连接池耗尽和SQL执行慢连接池耗尽的典型表现是获取连接时报“连接等待超时”或“池中无可用连接”。原因无非两点代码里没关连接或者某个SQL执行太久占着连接不放。排查时先看应用日志里有没有异常退出导致连接未归还的痕迹再用数据库自带的管理视图看当前活动连接数。达梦可以查V$SESSIONS视图MySQL可以查SHOW PROCESSLIST。如果是慢SQL占连接重点看有没有全表扫描、大范围排序、循环里逐条执行更新。解决办法要么加索引要么把批量操作改成批处理。千万别一味调大连接池最大连接数那样只是把压力往后推数据库端线程竞争只会更严重。4.5 权限不足与口令特殊字符登录时报“Invalid username/password”或“权限不足”先确认用户名密码在官方工具里能正常登录。能登录说明数据库侧没问题问题可能出在SMP连接串解析。密码里带、#、%等特殊字符时连接串语法很容易被误解成主机名分隔符或参数标记。常见处理是去dbx工具的配置界面保存密码让工具自动处理转义或者根据手册对特殊字符做转义。还有一类权限不是“能不能登录”而是“能不能执行SQL”。有的业务账号只给了查询权限SMP里一执行INSERT就报权限不足。这种问题不要硬扛直接用达梦数据库连接工具查看该用户拥有的对象权限和系统权限缺哪个补哪个。我记得有一次排查了半小时最后发现是账号只有SELECT权限根本不是连接问题。5. 工具选型解析dbx与达梦连接工具的实际使用经验5.1 为什么开发期一定要配一个dbx工具dbx数据库连接工具的价值在于把“连不连得上”和“怎么配置”这两件事提前解决了。没有它你只能写一段SMP脚本、跑一下、报错、改参数、再跑一遍非常浪费调试时间。用dbx的话填完数据库类型、主机、端口、账号密码点一下测试几秒钟就知道连接配置对不对。我平时的工作流是这样的先在dbx里新建连接选择数据库类型“达梦DM8”填好主机和端口测试通过后保存为命名连接。然后回到SMP脚本里直接引用这个命名连接。这样既不用在脚本里写明文密码也不用每次改机房IP后重新发布代码只要在dbx里改一次配置即可。团队协作时配置管理也清爽很多。5.2 达梦数据库连接工具与dbx的配合达梦数据库连接工具是达梦数据库生态里自带的客户端工具它的界面和主流数据库管理工具类似能直接管理表结构、索引、视图、用户权限。在这些场景里dbx并不擅长因为dbx的核心职责是“连接配置和测试”不是做数据库治理。使用经验上我通常在项目初始化阶段先用达梦数据库连接工具建库建用户把核心表结构、初始数据准备好。之后再到dbx里配置SMP侧的连接用SMP写业务逻辑。一旦SMP执行出错先回达梦工具里确认对象和数据是否存在再回头检查SMP脚本逻辑。两边的角色非常互补缺少哪一个都会增加排错难度。这里要特别提醒一种情况达梦数据库有兼容Oracle和兼容MySQL两种模式建库时选定的兼容模式会影响SQL写法。比如某些函数、序列、自增列的定义方式在两种模式下有明显差异。SMP脚本里的SQL要跟着兼容模式走否则在dbx里测试连接是好的一执行具体SQL就报语法错误。碰到这种问题先确认数据库实例模式再调整SQL写法。5.3 我的连接配置自查清单最后分享一份我在项目上一直在用的自查清单每次连接调试先过一遍能少走不少弯路。驱动是否就位版本是否匹配数据库和JDK主机能否ping通端口能否telnet通用户名密码在官方工具里能否正常登录连接串里的特殊字符是否转义字符集是否统一为UTF-8连接池参数是否合理超时时间够不够数据库兼容模式是否与SQL写法一致有一次现场系统上线前告警SMP服务连不上测试库我按这个清单一项项查最后发现是安全组忘了放行达梦的5236端口。连上之后又因为字符集没设置中文显示乱码调整dbx连接配置后彻底好了。整个过程没有动过一行业务代码全靠清单快速收敛问题。说到底数据库连接这件事看起来就一个“连接”背后是驱动、网络、权限、字符集、池化、事务六个维度的协作。SMP的这三十七篇把连接的基础知识讲到位剩下的就是多上手、多踩坑、多积累自己的排查清单。下次再遇到连不上的问题记得先打开dbx工具测试再回来看代码。
返回列表