如何减少 Progress OpenEdge OdbcCommand 使用 ReadCommitted 事务报告 C# 锁定所需的时间?
How do I decrease the time it takes for a Progress OpenEdge OdbcCommand using ReadCommitted transaction to report a lock in C#?
我们正在编写一个例程,其中 return 是一个可编辑对象,或者是一个表明基础记录已锁定的状态对象。
我们将 C# 和 .NET Framework 4.8 与 Progress OpenEdge ODBC 驱动程序一起用于 OpenEdge 数据库。记录可能被遗留 ABL 代码锁定,这就是为什么我们要检查 ReadCommitted 事务以查看开始编辑它是否安全。
在功能上,代码运行良好,完全按照我们的预期进行。当底层记录未被锁定时,它会在几毫秒内 returns 对象;当它被锁定时,它return是一个描述记录锁定状态的对象。
但是当底层记录确实被锁定时,它需要超过 15 秒才能达到 return,达到预期的 "ERROR [HY000] [DataDirect][ODBC Progress OpenEdge Wire Protocol driver][OPENEDGE]Failure getting record lock on a record from table PUB.i-mst."
我曾尝试减小 CommandTimeout 值,但最终(最终,当我逐渐减小它时)最终将失败更改为超时错误。
是否有一些较低级别的设置来控制 ODBC 或 OpenEdge 在失败之前等待锁定被释放的时间?
代码如下:
public static dynamic ReadOdbcForEdit(OdbcConnection connection, string type, string criteria, string domain,
string parentClass, string application)
{
connection.Open();
var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
Type objectType = Object.GetJohnstonType(parentClass + type, domain, application);
var tempObj = Activator.CreateInstance(objectType);
try
{
var odbcCommand = new OdbcCommand(criteria)
{
Connection = connection,
Transaction = transaction,
CommandTimeout = 30
};
var reader = odbcCommand.ExecuteReader();
while (reader.Read())
{
foreach (var property in tempObj.GetType().GetProperties())
{
var propertyType = property.PropertyType;
var propertyName = property.Name;
if (propertyType.IsArray ||
propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof(List<>))
{
continue;
}
try
{
if (reader[propertyName].GetType() != typeof(DBNull))
{
property.SetValue(tempObj, reader[propertyName]);
}
}
catch (Exception e)
{
Logging.Message($"Could not fill {propertyName} from database column");
Logging.Exception(e);
}
}
}
return tempObj;
}
catch (Exception e)
{
var openRecordStatus = new OpenRecordStatus
{
StatusCode = e.HResult,
StatusMessage = e.Message
};
return openRecordStatus;
}
}
您可能想要调整 -SQLLockWaitTimeout
https://knowledgebase.progress.com/articles/Article/What-is-the-SQLLockWaitTimeout-Parameter
The -SQLLockWaitTimeout parameter is used to identify the number of
seconds to wait when a lock conflict occurs. The default is 5 seconds.
This value applies to all lock conflicts experienced by SQL
applications. So an installation that gets a lot of lock conflicts
(does a lot of updating) would want to consider the impact of changing
this parameter.
对于旧版本的 Progress(11.4 之前):https://knowledgebase.progress.com/articles/Article/P123923
The PROSQL_LOCKWAIT_TIMEOUT environment variable was introduced in
9.1D06 and is used to limit how long a client will wait for a record that has a share or exclusive lock against it. This setting does not
effect and is not needed for an SQL Client with an isolation level of
READ UNCOMMITTED, because it will read a record that has a share or
exclusive lock against it.
The PROSQL_LOCKWAIT_TIMEOUT environment variable enables one to
determine how long SQL clients will wait in a lock queue for a
particular record. The environment variable must be present before a
broker is started and is applied to every SQL connection of the
broker.
The minimum time-out value is the default of five seconds
(DFLT_LOCKWAIT-TIMEOUT). The maximum time-out value is limited to a
32-bit integer value of 4,294,967,295 seconds or 1,193,046.5 hours.
This environment variable can be set prior to starting the database
broker or AdminServer. For example, to set it to 30 seconds:
UNIX: PROSQL_LOCKWAIT_TIMEOUT=30 ; export PROSQL_LOCKWAIT_TIMEOUT
Windows: Control Panel -> System -> Advanced tab -> Environment
Variables -> System Variables. Add a new variable.
In OpenEdge 11.4 and later there is a -SQLLockWaitTimeout startup
parameter that can be used to accomplish the same goal as the
environment variable. See article: 000064602, What is the
-SQLLockWaitTimeout Parameter? for additional information.
我们正在编写一个例程,其中 return 是一个可编辑对象,或者是一个表明基础记录已锁定的状态对象。
我们将 C# 和 .NET Framework 4.8 与 Progress OpenEdge ODBC 驱动程序一起用于 OpenEdge 数据库。记录可能被遗留 ABL 代码锁定,这就是为什么我们要检查 ReadCommitted 事务以查看开始编辑它是否安全。
在功能上,代码运行良好,完全按照我们的预期进行。当底层记录未被锁定时,它会在几毫秒内 returns 对象;当它被锁定时,它return是一个描述记录锁定状态的对象。
但是当底层记录确实被锁定时,它需要超过 15 秒才能达到 return,达到预期的 "ERROR [HY000] [DataDirect][ODBC Progress OpenEdge Wire Protocol driver][OPENEDGE]Failure getting record lock on a record from table PUB.i-mst."
我曾尝试减小 CommandTimeout 值,但最终(最终,当我逐渐减小它时)最终将失败更改为超时错误。
是否有一些较低级别的设置来控制 ODBC 或 OpenEdge 在失败之前等待锁定被释放的时间?
代码如下:
public static dynamic ReadOdbcForEdit(OdbcConnection connection, string type, string criteria, string domain,
string parentClass, string application)
{
connection.Open();
var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
Type objectType = Object.GetJohnstonType(parentClass + type, domain, application);
var tempObj = Activator.CreateInstance(objectType);
try
{
var odbcCommand = new OdbcCommand(criteria)
{
Connection = connection,
Transaction = transaction,
CommandTimeout = 30
};
var reader = odbcCommand.ExecuteReader();
while (reader.Read())
{
foreach (var property in tempObj.GetType().GetProperties())
{
var propertyType = property.PropertyType;
var propertyName = property.Name;
if (propertyType.IsArray ||
propertyType.IsGenericType &&
propertyType.GetGenericTypeDefinition() == typeof(List<>))
{
continue;
}
try
{
if (reader[propertyName].GetType() != typeof(DBNull))
{
property.SetValue(tempObj, reader[propertyName]);
}
}
catch (Exception e)
{
Logging.Message($"Could not fill {propertyName} from database column");
Logging.Exception(e);
}
}
}
return tempObj;
}
catch (Exception e)
{
var openRecordStatus = new OpenRecordStatus
{
StatusCode = e.HResult,
StatusMessage = e.Message
};
return openRecordStatus;
}
}
您可能想要调整 -SQLLockWaitTimeout
https://knowledgebase.progress.com/articles/Article/What-is-the-SQLLockWaitTimeout-Parameter
The -SQLLockWaitTimeout parameter is used to identify the number of seconds to wait when a lock conflict occurs. The default is 5 seconds.
This value applies to all lock conflicts experienced by SQL applications. So an installation that gets a lot of lock conflicts (does a lot of updating) would want to consider the impact of changing this parameter.
对于旧版本的 Progress(11.4 之前):https://knowledgebase.progress.com/articles/Article/P123923
The PROSQL_LOCKWAIT_TIMEOUT environment variable was introduced in 9.1D06 and is used to limit how long a client will wait for a record that has a share or exclusive lock against it. This setting does not effect and is not needed for an SQL Client with an isolation level of READ UNCOMMITTED, because it will read a record that has a share or exclusive lock against it.
The PROSQL_LOCKWAIT_TIMEOUT environment variable enables one to determine how long SQL clients will wait in a lock queue for a particular record. The environment variable must be present before a broker is started and is applied to every SQL connection of the broker.
The minimum time-out value is the default of five seconds (DFLT_LOCKWAIT-TIMEOUT). The maximum time-out value is limited to a 32-bit integer value of 4,294,967,295 seconds or 1,193,046.5 hours.
This environment variable can be set prior to starting the database broker or AdminServer. For example, to set it to 30 seconds:
UNIX: PROSQL_LOCKWAIT_TIMEOUT=30 ; export PROSQL_LOCKWAIT_TIMEOUT
Windows: Control Panel -> System -> Advanced tab -> Environment Variables -> System Variables. Add a new variable.
In OpenEdge 11.4 and later there is a -SQLLockWaitTimeout startup parameter that can be used to accomplish the same goal as the environment variable. See article: 000064602, What is the -SQLLockWaitTimeout Parameter? for additional information.