国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

使用ServiceBroker自動激活模擬"秒殺"場景

2024-07-21 02:50:40
字體:
來源:轉載
供稿:網友
使用ServiceBroker自動激活模擬"秒殺"場景 2014-03-24 08:49 by JentleWang, ... 閱讀, ... 評論, 收藏, 編輯 1.簡介

  SQL Server Service Broker 是SQL server里面比較獨特的一個功能。它可幫助開發人員構建異步的松散耦合應用程序

  ServiceBroker入門文章:http://blogs.msdn.com/b/apgcdsd/archive/2012/07/27/sql-server-service-broker-demo.aspx

  ServiceBroker的隊列存在自動激活(ACTIVATION)功能,其中內部激活可以激活數據庫存儲過程接受和處理隊列的消息,而且可以啟動激活存儲過程的多個實例(MAX_QUEUE_READERS)。當SQLServer的SCHEDULER個數大于1(即多CPU)時,會有多個實例同時去接受并處理消息。

  所以,接下來以發送出庫消息,接受并更新庫存為例,模擬并發條件下的庫存檢查及更新過程。

2.實現步驟2.1 創建測試數據庫及表

代碼如下:其中inventory為庫存表,表中兩個字段,產品和庫存數量

use mastercreate database wmsgouse wms gocreate table inventory(    material  int,    quantity  int)
2.2 創建ServiceBroker對象,搭建基礎框架

創建ServiceBroker服務對象,包括消息類型、約定、隊列及服務等。簡化起見,演示程序是運行在同一個數據庫實例下的同一個數據庫中

use wms--創建消息類型create message type inventoryio--創建約定create contract inventory_contract(    inventoryio sent by initiator)--創建客戶端隊列create queue inventory_client_queue--創建客戶端服務create service inventory_client on queue inventory_client_queue;--創建庫存隊列create queue inventoryio_queue--創建庫存更新服務create service inventoryioon queue inventoryio_queue(    [inventory_contract]);

2.3 開啟會話,發送出庫消息
--發送出庫消息begin transaction    declare @dialog_id uniqueidentifier    begin dialog conversation @dialog_id        from service inventory_client        to service 'inventoryio'        on contract [inventory_contract]        with encryption = off;        send on conversation @dialog_id message type  inventoryio        (        '<InventoryUpdate>        <material>1</material>        <quantity>1</quantity>        </InventoryUpdate>'            ); commit transaction;

為了記下來測試并發情況,連續運行上面的代碼四次。發送完后,查詢目標服務的隊列

select * from inventoryio_queue

結果如下:

2.4 創建庫存更新的存儲過程

接下里創建存儲過程,該存儲過程接受隊列的出庫指令,檢查庫存,當庫存滿足時,更新庫存;庫存不足時,回滾事務,消息重新回到隊列

代碼如下:

create PRoc InventoryProc asbegin transaction    declare @dialog_id uniqueidentifier    declare @message_body xml    declare @quantity int;    declare @material int;        waitfor(    receive        @dialog_id = conversation_handle,        @message_body = message_body     from [dbo].inventoryio_queue),timeout 5000;        if(@dialog_id is not null)    begin         set @quantity = @message_body.value('(/InventoryUpdate/quantity)[1]','int');        set @material = @message_body.value('(/InventoryUpdate/material)[1]','int');        --檢查庫存是否足夠        if exists( select 1 from inventory where  material = @material and quantity>=@quantity)        begin             print 'come here'            --更新庫存            Update inventory set quantity =quantity-@quantity where material = @material;        end        else         begin             rollback            return        end     end    end conversation @dialog_id; commit transaction; go
2.5 修改隊列,啟用自動激活功能

啟用隊列的自動激活功能,激活的存儲過程為上面創建的存儲,設置最大讀取器個數為5.

ALTER QUEUE [dbo].[inventoryio_queue] WITH STATUS = ON , RETENTION = OFF , ACTIVATION (  STATUS = ON , PROCEDURE_NAME = [dbo].[InventoryProc] , MAX_QUEUE_READERS = 5 , EXECUTE AS N'dbo'  ), POISON_MESSAGE_HANDLING (STATUS = OFF) 

注意:

POISON_MESSAGE_HANDLING的設置必須為OFF,將有害消息處理設置為 OFF 的隊列在五個連續的事務回滾之后不會被禁用。否則默認為ON,隊列在回滾5次后,會被禁用啟用自動激活后,可以查看目前激活的實例select * from sys.dm_broker_activated_tasks
2.6 插入庫存,查看更新結果
insert into inventoryvalues(1,1)select * from inventoryio_queueselect * from inventory

結果如下:

可以看到隊列中已經沒有消息了,庫存數量已經減少,但更新結果不準確.原因是在更新庫存之前,多個存儲過程實例都讀取了庫存數,并判斷出庫存滿足,然后對庫存進行了更新。注:最終庫存數量不一定為-3,需視Scheduler數量以及同時有多少個存儲過程實例可以獲得CPU來執行有關解決方法: 一種是設置隊列的自動激活的最大實例數為1,即不允許并發讀取另外就是在讀取庫存時,增加提示 with(holdlock),這樣只允許一個實例讀取庫存表的一行數據,直到事務結束。可查閱這篇文章:http://www.cnblogs.com/buaaboyi/archive/2011/08/30/2159860.html代碼如下:
--檢查庫存是否足夠        if exists( select 1 from inventory with(holdlock) where  material = @material and quantity>=@quantity)
3. 總結

本文演示了一個ServiceBroker單數據庫的簡單實例,并介紹了自動激活機制。簡單涉及了SQLServer的CPU調度。同時,提及了SQLServer的 with(holdlock)提示

注:本文代碼僅供演示使用而非實際應用于生產環境。如有問題及建議,請指正!^_^

參考文章:http://www.cnblogs.com/markj/archive/2013/03/31/2991777.html


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 淮北市| 台江县| 崇州市| 宜州市| 西吉县| 临洮县| 内黄县| 卢氏县| 曲松县| 朝阳市| 鱼台县| 黄陵县| 岫岩| 会泽县| 叶城县| 大安市| 大厂| 布拖县| 佛山市| 江达县| 鹤庆县| 南木林县| 扎囊县| 改则县| 兴城市| 东台市| 平利县| 游戏| 吉安县| 瓦房店市| 即墨市| 和田市| 城固县| 凤山县| 黄梅县| 耒阳市| 辽中县| 广宗县| 南投县| 内黄县| 会宁县|