由2个SQL连接创建的死锁,每个连接都使用事务、不同的表、两个表之间的外键约束

发布于 2024-07-09 08:34:23 字数 1288 浏览 5 评论 0原文

环境

我正在开发一个 C++ 应用程序,它使用 SQL Native Client 9.0 与 SQL Server 2000 数据库进行通信。

场景

  • 2 打开到 DBMS 的连接
  • 每个连接都设置为使用事务
  • Connection1 上的查询与 TableA 配合使用
  • Connection2 上的查询与 Connection2 配合使用code>TableB
  • TableBTableA 中的 key_id 字段有外键约束

的函数:

begin a transaction on Connection1 & Connection2
prepare a query in TableA on Connection1
prepare a query on TableB on Connection2

begin loop over some_data
   (1) insert into key_id on TableA

   begin loop over some_other_data
      (2) insert into TableB using same key_id as in Table A
   end loop
end loop

commit on Connection1
commit on Connection2

我构造了执行以下操作 我遇到的情况是,查询 (1) 执行成功,但是一旦为查询 (2) 调用 SQLExecute,调试器就会陷入绝境。

问题

我是否正确地将发生的情况诊断为死锁问题?

我推测,因为 Connection1 正在 TableA 中创建密钥但未提交它,所以 Connection2 正在尝试将信息添加到 TableB 由于外键约束,TableA 中必须存在该键。 因此,SQLExecute 查询会阻塞,等待 TableA 上的事务完成,而在 TableB 完成写入之前它无法执行此操作,谢谢代码的编写方式。

附加说明

我可以并且已经围绕这个问题进行了编码,但我想确保我对问题的理解是正确的。

Environment

I'm working on a C++ application that uses SQL Native Client 9.0 to communicate with a SQL Server 2000 database.

Scenario

  • 2 connections are opened to the DBMS
  • Each connection is set to use transactions
  • A query on Connection1 works with TableA
  • A query on Connection2 works with TableB
  • TableB has a foreign key constraint on the key_id field in TableA

I constructed the function that does the following:

begin a transaction on Connection1 & Connection2
prepare a query in TableA on Connection1
prepare a query on TableB on Connection2

begin loop over some_data
   (1) insert into key_id on TableA

   begin loop over some_other_data
      (2) insert into TableB using same key_id as in Table A
   end loop
end loop

commit on Connection1
commit on Connection2

What I encountered was that query (1) executes successfully but as soon as SQLExecute is called for query (2), the debugger goes off in never-never-land.

The Question

Am I correctly diagnosing what is happening as a dead-lock issue?

I gathered that because Connection1 is creating a key in TableA but not committing it, then Connection2 is trying to add information to TableB that, because of the foreign key constraint, must have the key present in TableA. Because of this, the SQLExecute query blocks, waiting for the transaction on TableA to complete, which it cannot do until TableB completes its write, thanks to the way the code was written.

Additional Notes

I can, and have, coded around this issue but I want to make sure my understanding of the problem is correct.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2024-07-16 08:34:23

TableB 针对 TableA 的外键约束必须进行检查以确认该键是否存在。 然后它将接受或拒绝 TableB 记录。

由于包含该键的 TableA 记录(在不同的连接上)尚未提交,因此外键约束必须等待 - 在提交或回滚 TableA 记录之前,插入不会返回。

因为第一个连接上的提交等待 TableB 插入返回...所以出现死锁。

换句话说,你是对的。

The foreign key constraint on TableB against TableA must check to confirm the key's existence. It will then accept or reject the TableB record.

Because the TableA record containing the key is (on a different connection) not yet commited, the Foreign Key constraint must wait - the insert will not return until the TableA record is committed or rolledback.

Because the commit on the first connection waits for the TableB insert to return... you have deadlock.

In other words, you are correct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文