gpt4 book ai didi

SqlTransaction with UPDLOCK(使用UPDLOCK进行Sql事务处理)

转载 作者:bug小助手 更新时间:2023-10-28 13:13:29 28 4
gpt4 key购买 nike



So I have a patientinfo table where I'm inserting a patient with a click of a button.

所以我有一个PatientInfo表,我只需点击一个按钮就可以插入一个患者。


That same button, generates the ID of the patient but for some reason, if I run a timer to execute this code from 5 apps at the exact same time, only one will go through, while the other ones will fail. Although I have tried to use ROWlock in this query, Updlock, and even Tablockx.

同样的按钮会生成患者的ID,但出于某种原因,如果我运行计时器同时从5个应用程序执行此代码,则只有一个应用程序会通过,而其他应用程序将失败。尽管我已经尝试在这个查询中使用rowlock、updlock,甚至Tablockx。


Any thoughts on what could be causing that? There are no errors aside from the Primary key error when the insertion fails because I'm inserting the same generated ID.

有没有想过是什么导致的?当插入失败时,除了主键错误之外,没有其他错误,因为我插入了相同的生成ID。


    Private Function GetNextPatientId(labID As String) As String
Dim connectionString As String = My.Settings.PatientsConnectionString
Dim result As String = ""

Using connection As New SqlConnection(connectionString)
connection.Open()

Dim retryCount As Integer = 0
Dim maxRetries As Integer = 3
Dim delayMilliseconds As Integer = 400

Using transaction As SqlTransaction = connection.BeginTransaction()
While retryCount < maxRetries
Try
Dim queryString As String = "
BEGIN TRAN
DECLARE @nextPatientId AS VARCHAR(12);

SELECT TOP 1 @nextPatientId = (CAST(SUBSTRING(PatientID, 3, 12) AS BIGINT) + 1)
FROM patientinfo WITH (UPDLOCK)
WHERE SUBSTRING(patientid, 1, 2) = @labID
ORDER BY SUBSTRING(PatientID, 3, 12) DESC;

IF @nextPatientId IS NULL
SET @nextPatientId = '01';

SELECT @nextPatientId AS nextPatientIdValue;
COMMIT TRAN;"

Dim command As New SqlCommand(queryString, connection, transaction)
command.Parameters.AddWithValue("@labID", labID)

Dim nextPatientIdValue As String = ""
Using reader As SqlDataReader = command.ExecuteReader()
If reader.Read() Then
nextPatientIdValue = Convert.ToString(reader("nextPatientIdValue"))
End If
End Using

result = nextPatientIdValue

Exit While
Catch ex As SqlException When ex.Number = 1205 AndAlso retryCount < maxRetries
retryCount += 1
Threading.Thread.Sleep(delayMilliseconds)
Catch ex As Exception
transaction.Rollback()
Throw
End Try
End While

transaction.Commit()
End Using
End Using

Return result
End Function

更多回答

I would recommend just using IDENTITY instead of this scheme but WITH (UPDLOCK, HOLDLOCK) might work. As it will lock the range and hold the lock until the end of the transaction

我建议只使用IDENTITY而不是这个方案,但WITH(IDENTITY,HOLDIDENTITY)可能会起作用。因为它将锁定范围并保持锁直到事务结束

I'll give it a try. Any reason on why the combination you mentioned would work but TABLOCKX wouldn't?

我要试一试。为什么你提到的组合可行,而TABLOCKX不行?

TABLOCKX doesn't mention that the locks will be held until the end of the transaction and presumably they aren't from the behaviour you describe learn.microsoft.com/en-us/sql/t-sql/queries/…

TABLOCKX没有提到这些锁将一直保持到事务结束,而且它们大概不是您所描述的learn.microsoft.com/en-us/sql/t-sql/queries/…的行为。

Okay so using updlock holdlock didn't really do the trick. I have a question though. It should be totally fine that the insert and SELECT are not in the same query. Correct?

好吧,所以使用锁死锁并没有真正起到作用。不过,我有一个问题。INSERT和SELECT不在同一个查询中应该完全没有问题。对,是这样?

You should put your SELECT generating nextPatientIdValue and INSERT in patientinfo inside a common transaction for the UPDLOCK to have any effect. Currently second app waits only until COMMIT is executed by the first app and gets the same MAX(PatientID) from patientinfo table as the first app has not INSERTed anything there yet.

您应该将生成nextPatientIdValue的SELECT和INSERT放在一个公共事务中,才能使UPDLOCK生效。目前,第二个应用程序只等待第一个应用程序执行提交,并从PatientInfo表中获得相同的Max(PatientID),因为第一个应用程序还没有在那里插入任何内容。

优秀答案推荐
更多回答

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com