如何通过 SSIS 在 Ingres 连接上设置 LOCKMODE SESSION WHERE LEVEL = MVCC
How to SET LOCKMODE SESSION WHERE LEVEL = MVCC on Ingres connection via SSIS
任何人都可以提供有关如何从 SSIS 加入 MVCC 会话的建议吗?
从 Ingres 数据库中读取,我们需要启用 MVCC 并在 SSIS 2008 R2 包中指定隔离级别。
此数据库上存在一个不使用 MVCC 的现有应用程序,因此不适合在现有 DBMS 上简单地启用 MVCC。我们希望我们的读取在 MVCC 中登记的原因是确保我们不会导致锁定并破坏这个现有的应用程序(当我们不使用 MVCC 执行这些读取时,当前会定期发生)。
数据库版本为Ingres II 10.0.0 (su9.us5/132)
ADO.NET驱动版本为Ingres.Client.IngresConnection, Ingres.Client, Version=2.1.0.0
驱动,
我们有一个类似的要求,即从 Tibco BusinessWorks 中以编程方式执行此操作,并通过例如 SQL Squirrel 以交互方式执行此操作,并通过直接 SQL 执行(通过 JDBC):
SET LOCKMODE SESSION WHERE LEVEL = MVCC;
SET SESSION ISOLATION LEVEL READ COMMITTED;
在SSIS中我们可以使用task/sequence的IsolationLevel
属性设置会话隔离级别。但是我找不到直接发出MVCC命令的方法。
我试图通过 Exceute SQL Task
步骤发出命令,但遇到以下错误:
Syntax error on line 1. Last symbol read was: 'SET LOCKMODE'
我已经尝试过,但无济于事:
- 有或没有终止符
;
- 执行序列内部或外部的步骤
- 在序列和步骤级别启用
DelayValidation
属性
- 序列和任务级别的各种
TransactionOption
设置(如果它们很重要!)
- 通过 windows 环境变量
ING_SET = "SET LOCKMODE SESSION WHERE LEVEL = MVCC"
设置锁定模式。但是我的测试表明,我们在 SSIS 中使用的 ADO.NET 驱动程序 不支持 (顺便说一句,我们使用的 JDBC 驱动程序也不支持它对于 SQL Squirrel 或 Tibco)。我相信这可能是一个 ODBC 功能。
- 从数据流中的 ADO.NET 源步骤中发出命令。相同的语法错误。
- [更新] 还尝试将
SET ...
命令包装在 Ingres 过程中,但这导致语法错误,表明 SET ...
命令在过程中的任何地方都无效。
任何人都可以提供有关如何从 SSIS 加入 MVCC 会话的建议吗?
在这个阶段(我相信)我们受限于 ADO.NET 驱动程序,但如果没有其他选项可以与 ODBC 一起使用,那就这样吧。
在这里回答我自己的问题。
设想了两种可能的方法。
1.使用脚本组件(在数据流步骤中)
在脚本组件中,我能够通过 ADO.NET 直接发出 SET ...
命令。
这种方法的问题是我无法为后续(或并行,在同一数据流中)ADO.NET 保留这些命令所在的连接 运行组件。
尝试通过事务通过特定连接工作是不好的,因为这些命令必须在正在进行的事务之外发出。
所以最终我还必须从该组件中发出源 select,即使这样也不太理想,因为随后的目标插入操作无法在与源相同的事务中登记 select.
使用这种方法的解决方案最终是:
- 使用 MVCC,将数据从源视图复制到源系统上的临时暂存区 table。
- 然后使用事务,从源分段 table 读取到目标系统。
代码看起来像这样(NB 必须显式添加对 Ingres .NET 数据的引用 Provider\v2.1\Ingres.Client.dll
/* Microsoft SQL Server Integration Services Script Component
* Write scripts using Microsoft Visual C# 2008.
* ScriptMain is the entry point class of the script.*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Ingres.Client;
using System.Collections.Generic;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private bool debug = true;
private IDTSConnectionManager100 cm;
private IngresConnection conn;
public override void AcquireConnections(object Transaction)
{
// The connection manager used here must be configured in the Script Component editor's "Connection Managers" page.
// "Connection" is the (default) strongly typed name for the first connection added.
// In this case, it needs to be a reference to the xxxxx connection manager (by convention it should be "xxxxx_ADONET").
cm = this.Connections.Connection;
conn = (IngresConnection)cm.AcquireConnection(Transaction);
}
public override void PreExecute()
{
debugMessage("PreExecute", "Started");
base.PreExecute();
string viewName = Variables.vViewName;
IngresCommand cmdSetSessionLockMode = conn.CreateCommand();
IngresCommand cmdSetSessionIsolationLevel = conn.CreateCommand();
IngresCommand cmdReaderQuery = conn.CreateCommand();
List<string> sqlCommandStrings = new List<string>();
if (Variables.vUseIngresMVCC)
{
sqlCommandStrings.Add("SET LOCKMODE SESSION WHERE LEVEL = MVCC");
}
sqlCommandStrings.Add("SET SESSION ISOLATION LEVEL READ COMMITTED");
sqlCommandStrings.Add(String.Format("MODIFY {0}_STAGING TO TRUNCATED", viewName));
sqlCommandStrings.Add(String.Format("INSERT INTO {0}_STAGING SELECT * FROM {0}", viewName));
foreach (string sqlCommandString in sqlCommandStrings)
{
debugMessage("PreExecute", "Executing: '{0}'", sqlCommandString);
IngresCommand command = conn.CreateCommand();
command.CommandText = sqlCommandString;
int rowsAffected = command.ExecuteNonQuery();
string rowsAffectedString = rowsAffected >= 0 ? rowsAffected.ToString() : "No";
debugMessage("PreExecute", "Command executed OK, {0} rows affected.", rowsAffectedString);
}
debugMessage("PreExecute", "Finished");
}
public override void CreateNewOutputRows()
{
// SSIS requires that we output at least one row from this source script.
Output0Buffer.AddRow();
Output0Buffer.CompletedOK = true;
}
public override void PostExecute()
{
base.PostExecute();
// NB While it is "best practice" to release the connection here, doing so with an Ingres connection will cause a COM exception.
// This exception kills the SSIS BIDS designer such that you'll be unable to edit this code through that tool.
// Re-enable the following line at your own peril.
//cm.ReleaseConnection(conn);
}
private void debugMessage(string method, string messageFormat, params object[] messageArgs)
{
if (this.debug)
{
string message = string.Format(messageFormat, messageArgs);
string description = string.Format("{0}: {1}", method, message);
bool fireAgain = true;
this.ComponentMetaData.FireInformation(0, this.ComponentMetaData.Name, description, "", 0, ref fireAgain);
}
}
}
在这里回答我自己的问题。
设想了两种可能的方法。
2。在现有数据库上设置 Ingres DBMS 的启用 MVCC 的专用进程,并通过此连接
这是我们目前正在采用的方法(因为它受到支持,并且理想情况下是透明的)。一旦他们知道我会更新细节。
任何人都可以提供有关如何从 SSIS 加入 MVCC 会话的建议吗?
从 Ingres 数据库中读取,我们需要启用 MVCC 并在 SSIS 2008 R2 包中指定隔离级别。
此数据库上存在一个不使用 MVCC 的现有应用程序,因此不适合在现有 DBMS 上简单地启用 MVCC。我们希望我们的读取在 MVCC 中登记的原因是确保我们不会导致锁定并破坏这个现有的应用程序(当我们不使用 MVCC 执行这些读取时,当前会定期发生)。
数据库版本为Ingres II 10.0.0 (su9.us5/132)
ADO.NET驱动版本为Ingres.Client.IngresConnection, Ingres.Client, Version=2.1.0.0
驱动,
我们有一个类似的要求,即从 Tibco BusinessWorks 中以编程方式执行此操作,并通过例如 SQL Squirrel 以交互方式执行此操作,并通过直接 SQL 执行(通过 JDBC):
SET LOCKMODE SESSION WHERE LEVEL = MVCC;
SET SESSION ISOLATION LEVEL READ COMMITTED;
在SSIS中我们可以使用task/sequence的IsolationLevel
属性设置会话隔离级别。但是我找不到直接发出MVCC命令的方法。
我试图通过 Exceute SQL Task
步骤发出命令,但遇到以下错误:
Syntax error on line 1. Last symbol read was: 'SET LOCKMODE'
我已经尝试过,但无济于事:
- 有或没有终止符
;
- 执行序列内部或外部的步骤
- 在序列和步骤级别启用
DelayValidation
属性 - 序列和任务级别的各种
TransactionOption
设置(如果它们很重要!) - 通过 windows 环境变量
ING_SET = "SET LOCKMODE SESSION WHERE LEVEL = MVCC"
设置锁定模式。但是我的测试表明,我们在 SSIS 中使用的 ADO.NET 驱动程序 不支持 (顺便说一句,我们使用的 JDBC 驱动程序也不支持它对于 SQL Squirrel 或 Tibco)。我相信这可能是一个 ODBC 功能。 - 从数据流中的 ADO.NET 源步骤中发出命令。相同的语法错误。
- [更新] 还尝试将
SET ...
命令包装在 Ingres 过程中,但这导致语法错误,表明SET ...
命令在过程中的任何地方都无效。
任何人都可以提供有关如何从 SSIS 加入 MVCC 会话的建议吗?
在这个阶段(我相信)我们受限于 ADO.NET 驱动程序,但如果没有其他选项可以与 ODBC 一起使用,那就这样吧。
在这里回答我自己的问题。
设想了两种可能的方法。
1.使用脚本组件(在数据流步骤中)
在脚本组件中,我能够通过 ADO.NET 直接发出 SET ...
命令。
这种方法的问题是我无法为后续(或并行,在同一数据流中)ADO.NET 保留这些命令所在的连接 运行组件。
尝试通过事务通过特定连接工作是不好的,因为这些命令必须在正在进行的事务之外发出。
所以最终我还必须从该组件中发出源 select,即使这样也不太理想,因为随后的目标插入操作无法在与源相同的事务中登记 select.
使用这种方法的解决方案最终是: - 使用 MVCC,将数据从源视图复制到源系统上的临时暂存区 table。 - 然后使用事务,从源分段 table 读取到目标系统。
代码看起来像这样(NB 必须显式添加对 Ingres .NET 数据的引用 Provider\v2.1\Ingres.Client.dll
/* Microsoft SQL Server Integration Services Script Component
* Write scripts using Microsoft Visual C# 2008.
* ScriptMain is the entry point class of the script.*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Ingres.Client;
using System.Collections.Generic;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private bool debug = true;
private IDTSConnectionManager100 cm;
private IngresConnection conn;
public override void AcquireConnections(object Transaction)
{
// The connection manager used here must be configured in the Script Component editor's "Connection Managers" page.
// "Connection" is the (default) strongly typed name for the first connection added.
// In this case, it needs to be a reference to the xxxxx connection manager (by convention it should be "xxxxx_ADONET").
cm = this.Connections.Connection;
conn = (IngresConnection)cm.AcquireConnection(Transaction);
}
public override void PreExecute()
{
debugMessage("PreExecute", "Started");
base.PreExecute();
string viewName = Variables.vViewName;
IngresCommand cmdSetSessionLockMode = conn.CreateCommand();
IngresCommand cmdSetSessionIsolationLevel = conn.CreateCommand();
IngresCommand cmdReaderQuery = conn.CreateCommand();
List<string> sqlCommandStrings = new List<string>();
if (Variables.vUseIngresMVCC)
{
sqlCommandStrings.Add("SET LOCKMODE SESSION WHERE LEVEL = MVCC");
}
sqlCommandStrings.Add("SET SESSION ISOLATION LEVEL READ COMMITTED");
sqlCommandStrings.Add(String.Format("MODIFY {0}_STAGING TO TRUNCATED", viewName));
sqlCommandStrings.Add(String.Format("INSERT INTO {0}_STAGING SELECT * FROM {0}", viewName));
foreach (string sqlCommandString in sqlCommandStrings)
{
debugMessage("PreExecute", "Executing: '{0}'", sqlCommandString);
IngresCommand command = conn.CreateCommand();
command.CommandText = sqlCommandString;
int rowsAffected = command.ExecuteNonQuery();
string rowsAffectedString = rowsAffected >= 0 ? rowsAffected.ToString() : "No";
debugMessage("PreExecute", "Command executed OK, {0} rows affected.", rowsAffectedString);
}
debugMessage("PreExecute", "Finished");
}
public override void CreateNewOutputRows()
{
// SSIS requires that we output at least one row from this source script.
Output0Buffer.AddRow();
Output0Buffer.CompletedOK = true;
}
public override void PostExecute()
{
base.PostExecute();
// NB While it is "best practice" to release the connection here, doing so with an Ingres connection will cause a COM exception.
// This exception kills the SSIS BIDS designer such that you'll be unable to edit this code through that tool.
// Re-enable the following line at your own peril.
//cm.ReleaseConnection(conn);
}
private void debugMessage(string method, string messageFormat, params object[] messageArgs)
{
if (this.debug)
{
string message = string.Format(messageFormat, messageArgs);
string description = string.Format("{0}: {1}", method, message);
bool fireAgain = true;
this.ComponentMetaData.FireInformation(0, this.ComponentMetaData.Name, description, "", 0, ref fireAgain);
}
}
}
在这里回答我自己的问题。
设想了两种可能的方法。
2。在现有数据库上设置 Ingres DBMS 的启用 MVCC 的专用进程,并通过此连接
这是我们目前正在采用的方法(因为它受到支持,并且理想情况下是透明的)。一旦他们知道我会更新细节。