我有一个在RHEL7主机上运行的lua脚本,该脚本已编写为连接到MS SQL Server数据库(使用FreeTDS / unixODBC)并检索值。该脚本通常可以正常工作,但是,如果目标服务器处于脱机/不可用状态,它将暂停(大约6分20秒),最终超时并返回错误。我想要的是将这个超时时间缩短到几秒......
我觉得这应该很简单,但我似乎无法弄清楚如何指定/强制执行SQL Server的连接超时。
/etc/freetds.conf中有一个超时配置(见下文),但这似乎没有效果。
脚本通常从nginx(openresty)调用,这是我想要保持超时低的主要原因,但是观察到独立运行脚本时出现相同的挂起/超时行为。
任何人都可以帮我解决这个问题吗?我已经在下面包含了脚本和相关相关配置文件的内容。
更新: 我注意到在进一步测试期间值得一提的东西 - 如果我将测试脚本指向同一子网的未使用的IP地址OUTS,那么尝试进行SQL服务器连接时的超时时间约为6分21秒(如前所述)。如果我将它指向同一子网中未使用的IP地址,我的超时始终为~9秒。我不是网络专家,但这表明我实际看到的2次超时受到网络/传输层的影响 - 也许我的本地网络交换机只是将数据包丢弃到未知子网?
这并不能解决我原来的问题,但认为值得一提的是更新...
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
答案 0 :(得分:0)
在连接之前,您可以尝试为连接对象设置SQL_ATTR_LOGIN_TIMEOUT
。
对应于等待秒数的SQLUINTEGER值 在返回应用程序之前完成登录请求。 默认值取决于驱动程序。如果ValuePtr为0,则超时为 禁用,连接尝试将无限期等待。
local env, err = odbc.environment()
local cnn = env:connection()
cnn:setlogintimeout(10)
local ok, err = cnn:driverconnect(CNN_DRV)
<强>更新强>
还存在SQL_ATTR_CONNECTION_TIMEOUT
属性(但对于ODBC 3.0)
对应于等待秒数的SQLUINTEGER值 对于连接完成的任何请求,在返回之前 应用。驱动程序应该返回SQLSTATE HYT00(超时已过期) 任何时候都可以在没有关联的情况下超时 查询执行或登录。
如果ValuePtr等于0(默认值),则没有超时。
我不公开它,但你可以尝试这个。 (也可以在头文件中签出SQL_ATTR_CONNECTION_TIMEOUT的值)。
local SQL_ATTR_CONNECTION_TIMEOUT = 113
cnn:setuintattr(SQL_ATTR_CONNECTION_TIMEOUT, 10)
答案 1 :(得分:0)
我在树莓派PI 3上遇到了类似的问题(使用FreeTDS 1.2.3 / unixODBC)。该连接正常工作,没有问题,但是超时无法正常工作(如果我强制SQL Server脱机)。我跟踪了代码,意识到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