在 Lua 脚本中使用 FreeTDS 和 unixODBC 连接 MS SQL Server 数据库时配置连接超时
我有一个在运行 RHEL7 主机上的 Lua 脚本,该脚本已编写以使用 FreeTDS / unixODBC 连接到 MS SQL Server 数据库并检索值。脚本通常运行良好,但是如果目标服务器离线/不可用,它将会挂起(大约 6 分钟 20 秒),直到某些东西最终超时并返回错误。我想要的是将此超时时间缩短到几秒钟...
我觉得这应该很简单,但是我似乎无法弄清楚如何指定/强制 SQL Server 的连接超时。
在 /etc/freetds.conf 中有一个超时配置(如下所示),但它似乎没有影响。
该脚本通常从 nginx(openresty)调用,这也是我想保持超时时间低的主要原因,但是独立运行该脚本也会观察到相同的挂起/超时行为。
有人能帮我解决这个问题吗?我已经在下面包括了脚本和相关配置文件的内容。
UPDATE: 在进一步测试过程中,我注意到了值得一提的事情-如果我将我的测试脚本指向同一子网之外的未使用 IP 地址,则在尝试进行 SQL 服务器连接时的超时时间为 6 分钟 21 秒(如先前提到的)。但是,如果我将其指向同一子网中未使用的 IP 地址,则我的超时时间始终为 ~9 秒钟。我不是网络专家,但这表明我实际上在这里看到的两个超时受到了网络/传输层的影响-也许我的本地网络交换机只是将未知子网的数据包丢弃了?
这解决不了我的原始问题,但是认为这是一个值得提及的更新...
getvalue.lua:
local odbc = require \"odbc\"
local keyvalue = \"some_value\"
local retval = \"\"
CNN_DRV = {
{Driver='{FreeTDS}'};
{Server='10.10.60.100,1433'};
{Database='databasename'};
{Uid='sqlusername'};
{Pwd='sqlpassword'};
};
dbassert = odbc.assert
env,err = odbc.environment()
local cnn, err = env:driverconnect(CNN_DRV)
stmt,err = cnn:prepare("{?= call dbo.GetRetValForKeyValue(?)}")
ret = stmt:vbind_param_ulong(1, ret, odbc.PARAM_OUTPUT)
val = stmt:vbind_param_char(2, keyvalue)
dbassert(stmt:execute())
stmt:foreach(function(f1)
if tonumber(f1)
then
retval = string.format(\"%d\", f1)
else
retval = ''
end
end
)
print(retval)
/etc/odbcinst.ini:
[FreeTDS]
Description = FreeTDS TDS driver (for Sybase/MS SQL)
Driver = /usr/lib64/libtdsodbc.so.0
Setup = /usr/lib64/libtdsS.so.2
/etc/freetds.conf:
# Global settings are overridden by those in a database
# server specific section
[global]
# TDS protocol version
; tds version = 4.2
# Whether to write a TDSDUMP file for diagnostic purposes
# (setting this to /tmp is insecure on a multi-user system)
; dump file = /tmp/freetds.log
; debug flags = 0xffff
# Command and connection timeouts
; timeout = 10
; connect timeout = 10
# If you get out-of-memory errors, it may mean that your client
# is trying to allocate a huge buffer for a TEXT field.
# Try setting 'text size' to a more reasonable limit
text size = 64512
我在树莓派3上使用FreeTDS 1.2.3 / unixODBC遇到了类似的问题。连接没有问题,但是如果我让SQL服务器下线,就无法设置超时。我追踪了代码,并意识到freetds.conf中的timeout参数从未达到freeTDS库,因此在packet.c中等待数据包的函数会永远悬挂在那里。
我的解决方案是使用以下更改修改freeTDS库,以便在读取odbc.ini时将超时值馈送给freeTDS库。我不确定这是修复此问题的正确方法还是我遗漏了什么,但我找不到网上的任何信息。
odbc.h(在odbc参数列表中添加了超时)
#define ODBC_PARAM_LIST \
ODBC_PARAM(Servername) \
ODBC_PARAM(Server) \
ODBC_PARAM(DSN) \
ODBC_PARAM(UID) \
ODBC_PARAM(PWD) \
ODBC_PARAM(Address) \
ODBC_PARAM(Port) \
ODBC_PARAM(TDS_Version) \
ODBC_PARAM(Language) \
ODBC_PARAM(Database) \
ODBC_PARAM(TextSize) \
ODBC_PARAM(PacketSize) \
ODBC_PARAM(ClientCharset) \
ODBC_PARAM(DumpFile) \
ODBC_PARAM(DumpFileAppend) \
ODBC_PARAM(DebugFlags) \
ODBC_PARAM(Encryption) \
ODBC_PARAM(Trusted_Connection) \
ODBC_PARAM(APP) \
ODBC_PARAM(WSID) \
ODBC_PARAM(UseNTLMv2) \
ODBC_PARAM(MARS_Connection) \
ODBC_PARAM(REALM) \
ODBC_PARAM(ServerSPN) \
ODBC_PARAM(AttachDbFilename) \
ODBC_PARAM(ApplicationIntent) \
ODBC_PARAM(Timeout)
connectparams.c(在函数中添加了超时属性,并在获取dsn信息时读取它)
int
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
{
....
hLastProperty = definePropertyString(hLastProperty, odbc_param_Timeout, "10", "The timeout for connection and queries.");
return 1;
}
/**
* Read connection information from given DSN
* @param DSN DSN name
* @param login where to store connection info
* @return 1 if success 0 otherwhise
*/
int
odbc_get_dsn_info(TDS_ERRS *errs, const char *DSN, TDSLOGIN * login)
{
....
if (myGetPrivateProfileString(DSN, odbc_param_Timeout, tmp) > 0)
tds_parse_conf_section(TDS_STR_TIMEOUT, tmp, login);
return 1;
}
odbc.ini
[TestServer]
Driver=FreeTDS
Database=MyDatabase
Port=1433
Server=<<ip address>>
timeout=10
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

在连接之前可以尝试为连接对象设置
SQL_ATTR_LOGIN_TIMEOUT。local env, err = odbc.environment() local cnn = env:connection() cnn:setlogintimeout(10) local ok, err = cnn:driverconnect(CNN_DRV)更新
同样存在 ODBC 3.0 的
SQL_ATTR_CONNECTION_TIMEOUT属性。我没有公开它,但您可以尝试这个。 (在您的头文件中也可以查看 SQL_ATTR_CONNECTION_TIMEOUT 的值)。
local SQL_ATTR_CONNECTION_TIMEOUT = 113 cnn:setuintattr(SQL_ATTR_CONNECTION_TIMEOUT, 10)