AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 117187
Accepted
Vaccano
Vaccano
Asked: 2015-10-07 09:56:45 +0800 CST2015-10-07 09:56:45 +0800 CST 2015-10-07 09:56:45 +0800 CST

使用 RowLock 强制执行一次且仅一次

  • 772

我有一个 Web 服务,可以触发订单的一系列事件。当它收到一条消息告诉它(每秒最多约 2 次)时,它会执行此操作。

我遇到的问题是我有多个 Web 服务实例,有时订单的不同部分可以同时到达每个实例。这会导致事件链针对订单多次触发(错误)。

所以,我在想,我可以做一个表,它只是订单的 ID 和一个标志,说明“事件链”是否已经被触发。

然后我可以在我的代码中开始交易。是这样的:

mySqlConnection.BeginTransaction(); // C# Code

我可以像这样为有问题的订单选择行:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

SELECT  OrderId, IsChainFired
FROM    OrderedChainFlag WITH ( ROWLOCK, XLOCK, HOLDLOCK )
WHERE   OrderId = 123456

然后,如果 IsChainFired 为假,则触发“事件链”。然后我会运行:

UPDATE  OrderedChainFlag 
SET     IsChainFired = 1
WHERE   OrderId = 123456

然后运行(即使 IsChainFired 为真):

myConnection.CommitTransaction(); // C# Code

这将防止多个服务实例读取链可以同时自由运行。

我的担心(也是我的问题)是锁升级。如果这保持在行锁上,那么它将是解决我的问题的绝佳方法。但是,如果锁定升级到页面或表,那么我就会在我的系统中造成瓶颈。

那么,我能做些什么来确保它保持在行锁级别吗? (或者像这样将数据库锁定系统用作信号量是个好主意吗?)

注意:OrderId 将是表的主键、聚簇索引和分区索引。

sql-server sql-server-2012
  • 1 1 个回答
  • 274 Views

1 个回答

  • Voted
  1. Best Answer
    Hannah Vernon
    2015-10-07T10:05:44+08:002015-10-07T10:05:44+08:00

    您可以使用该OUTPUT子句查看是否应“触发”事件链:

    我的测试台:

    CREATE TABLE dbo.OrderedChainFlag
    (
        IsChainFired BIT NOT NULL
            CONSTRAINT DF_OrderedChainFlag_IsChainFired
            DEFAULT ((0))
        , OrderID INT NOT NULL
    );
    
    CREATE INDEX IX_OrderedChainFlag_Firing
    ON dbo.OrderedChainFlag(OrderID, IsChainFired);
    
    GO
    
    INSERT INTO dbo.OrderedChainFlag (OrderID)
    VALUES (123456);
    

    运行此命令以查看输出:

    UPDATE OrderedChainFlag 
    SET IsChainFired = 1 
    OUTPUT inserted.IsChainFired, inserted.OrderID
    WHERE OrderId = 123456 
        and IsChainFired = 0;
    

    使用aDataReader读取UPDATE语句的结果;如果返回一行,.Read()您知道表已更新,并且实际上,您可以运行事件链。

    运行UPDATE上面的语句只会在它实际将IsChainFired列更新为1. 您可以通过运行更新语句两次来证明这一点。第一个显示输出,第二个不显示。

    OrderId由于这条语句是原子的,假设您在和上有一个良好的索引IsChainFired,并且该索引已配置,那么一对一更新将成功,而不会影响锁升级WITH (ALLOW_ROW_LOCKS = ON)。


    第二种选择,与上述略有不同,是不指定下一个OrderID要处理的;而是简单地选择下一个具有IsChainFired = 0:

    CREATE INDEX IX_OrderedChainFlag_IsFired
    ON dbo.OrderedChainFlag(IsChainFired);
    
    UPDATE TOP(1) OrderedChainFlag 
    SET IsChainFired = 1 
    OUTPUT inserted.IsChainFired, inserted.OrderID
    WHERE IsChainFired = 0;
    

    本UPDATE例中的语句直接从索引返回OrderID单行。IX_OrderedChainFlag_IsFired

    我在我的测试平台的 OrderedChainFlag 表中插入了超过 750,000 行,并运行上面的UPDATE TOP(1)语句,使用我提到的索引,并得到以下计划:

    在此处输入图像描述

    这里的一个(有争议的)好处是您可能会返回多TOP(1)行数据进行处理,也许在您的 Web 服务中使用多个线程。

    您可能还应该阅读这个问题,以及有关并发性的出色答案。

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve