From 8f64eb897bf72c00a9ba2b4f8d56dce48ffceda8 Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Wed, 25 Feb 2026 11:55:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DPostgreSQL=E5=92=A8?= =?UTF-8?q?=E8=AF=A2=E9=94=81=E5=87=BD=E6=95=B0=E5=8F=82=E6=95=B0=E4=B8=8D?= =?UTF-8?q?=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/ProductSkuSaveJobRunner.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveJobRunner.cs b/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveJobRunner.cs index 515d53f..b7e10a4 100644 --- a/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveJobRunner.cs +++ b/src/Api/TakeoutSaaS.TenantApi/Services/ProductSkuSaveJobRunner.cs @@ -1,3 +1,4 @@ +using System.Buffers.Binary; using System.Text.Json; using Hangfire; using Microsoft.EntityFrameworkCore; @@ -77,8 +78,9 @@ public sealed class ProductSkuSaveJobRunner( await dbContext.SaveChangesAsync(); // 以租户+商品维度申请事务级咨询锁,保证同商品串行落库。 + var advisoryLockKey = BuildAdvisoryLockKey(job.TenantId, job.ProductId); await dbContext.Database.ExecuteSqlInterpolatedAsync( - $"SELECT pg_advisory_xact_lock({job.TenantId}, {job.ProductId});"); + $"SELECT pg_advisory_xact_lock({advisoryLockKey});"); var payload = DeserializePayload(job.PayloadJson); if (payload.Skus.Count == 0) @@ -194,5 +196,23 @@ public sealed class ProductSkuSaveJobRunner( return string.Join(Environment.NewLine, lines); } + private static long BuildAdvisoryLockKey(long tenantId, long productId) + { + Span raw = stackalloc byte[16]; + BinaryPrimitives.WriteInt64LittleEndian(raw, tenantId); + BinaryPrimitives.WriteInt64LittleEndian(raw[8..], productId); + + const ulong fnvOffsetBasis = 14695981039346656037UL; + const ulong fnvPrime = 1099511628211UL; + var hash = fnvOffsetBasis; + foreach (var b in raw) + { + hash ^= b; + hash *= fnvPrime; + } + + return unchecked((long)hash); + } + private sealed record JobMeta(long Id, long TenantId); }