multithreaded transaction causes -271 informix error code on table insertion

huangapple go评论59阅读模式
英文:

multithreaded transaction causes -271 informix error code on table insertion

问题

Our .net 6 应用程序将需要将近 10 个表作为单个事务的一部分插入。最后一个表包含一个标识主键列,其类型为序列。从一组数据中,每个数据都需要插入到 10 个表中。在该事务中,我们进行了小的计算,使用由表插入生成的主键,在以下表插入中使用。

一切都很顺利,直到事务在正常的 foreach 循环中按顺序完成。引入 Parallel.ForEachAsync 后,一些数据成功处理,但由于从最后一个表插入引发的异常,一些数据处理失败。

"[Informix][Informix ODBC Driver][Informix] 无法将新行插入到表中。 sqlerrm(TABLE_NAME)"

技术堆栈:

  1. Informix 版本:IBM Informix Dynamic Server 版本 12.10.FC7W1XPAEE
  2. 用于 ADO.net 的 Odbc 提供程序:System.Data.Odbc 6.0.0 nuget 包
  3. IBM INFORMIX ODBC 驱动程序 4.10.00.16746
  4. .net 6 Worker 模板项目部署为 Windows 服务

从文档中我们可以看到,在表中有一个锁,导致另一个尝试插入相同表的线程抛出异常。在多线程程序(在这种情况下是 Parallel.ForEachAsync 方法)中插入的解决方案有哪些?

  1. 我们能否使用避免此问题的任何隔离级别?我尝试了 ReadUnCommited、ReadCOmmited、Serializable。我不知道如何进一步进行。

  2. ODBC 提供程序在 .net 6 代码中不提供控制 Informix 锁的任何 API。

  3. 我们无法修改 DDL 或任何其他 Informix 数据库基础设施或其中的任何设置。

英文:

Our .net 6 application will need to insert nearly 10 tables as part of a single transaction. The last table contains an identity primary key column which is serial type. From a collection of data, each data needs to be inserted into 10 tables. Within that transaction we have small calculations, using the primary key generated by table insertion in following table insertion.

Everything works fine until the transaction is done sequentially in normal foreach loop. After introducing the Parallel.ForEachAsync , few data got processed successfully and few got failed because of the exception thrown from last table insertion.

"[Informix][Informix ODBC Driver][Informix]Could not insert new row into the table. sqlerrm(TABLE_NAME)"

Technology stack:

  1. Informix version: IBM Informix Dynamic Server Version
    12.10.FC7W1XPAEE
  2. Odbc provider for ADO.net: System.Data.Odbc 6.0.0 nuget package
  3. IBM INFORMIX ODBC Driver 4.10.00.16746
  4. .net 6 Worker Template project deployed as Windows Service

From the documentation, we can observe that there is a lock in the table which gave exception to another thread attempting to insert into same table. What are the solutions to insert this in multi-threaded program (in this case Parallel.ForEachAsync method) ?

  1. Can we use any isolation level which avoid this issue? I tried ReadUnCommited, ReadCOmmited, Serializable. I don't know how to proceed in this way further

  2. ODBC provider doesn't provide any API to control the informix locks in the .net 6 code.

  3. We couldn't alter the DDL or any other Informix database infrastructure or any settings there.

答案1

得分: 1

When there is a lock, the program or thread will get error or Exception from informix by default. Alternatively we can modify the behavior to wait until lock got released.

SET LOCK MODE TO WAIT

Using the above Set statement in my code as below fixes my problem. Now the insert query will wait and insert once lock released by another thread in my case.

var cmd = conn.CreateCommand();
cmd.CommandText = "SET LOCK MODE TO WAIT; INSERT INTO TABLE_NAME(column1, column2) VALUES(1, 'value');";
var rowsAdded = command.ExecuteNonQuery();

To not to make any undesired impact unknowingly in other parts of our program(since it is vast and complicated code base), I've set the lock mode back to "No wait" i.e. informix will throw error like below.

cmd.CommandText = "SET LOCK MODE TO WAIT; INSERT INTO TABLE_NAME(column1, column2) VALUES(1, 'value'); SET LOCK MODE TO NO WAIT;";

Refer: Setting the lock mode to wait

英文:

When there is a lock, the program or thread will get error or Exception from informix by default. Alternatively we can modify the behavior to wait until lock got released.

SET LOCK MODE TO WAIT

Using the above Set statement in my code as below fixes my problem. Now the insert query will wait and insert once lock released by another thread in my case.

var cmd = conn.CreateCommand();
cmd.CommandText = "SET LOCK MODE TO WAIT; INSERT INTO TABLE_NAME(column1, column2) VALUES(1, "value");";
var rowsAdded = command.ExecuteNonQuery();

To not to make any undesired impact unknowingly in other parts of our program(since it is vast and complicated code base), I've set the lock mode back to "No wait" i.e. informix will throw error like below.

cmd.CommandText = "SET LOCK MODE TO WAIT; INSERT INTO TABLE_NAME(column1, column2) VALUES(1, "value"); SET LOCK MODE TO NO WAIT;";

Refer: Setting the lock mode to wait

huangapple
  • 本文由 发表于 2023年5月10日 13:27:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215154.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定