欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

SQL Server中流水號生成的注意事項

admin
2011年3月3日 17:14 本文熱度 3415

  前幾天一個人問到了關于流水號重復的問題,我想了下,雖然說這個問題比較簡單,但是具有廣泛性,所以寫了這篇博客來介紹下,希望對大家有所幫助。

  在進行數據庫應用開發時經常會遇到生成流水號的情況,比如說做了一個訂單模塊,要求訂單號是唯一的,規則是:下訂單時的年月日+6位的流水號這樣的規則。

  對于這種要生成流水號的系統,我們一般是在數據庫中新建了一個種子表,每次生成新的訂單時:

  1.讀取當天種子最大值。

  2.根據種子最大值和當時的年月日生成唯一的訂單號。

  3.更新種子最大值,使最大值+1。

  4.根據生成的訂單號將訂單數據插入到訂單表中。

  以上幾步操作是在一個事務中完成,保證了流水號的連續。這個思路是正確的,使用起來好像也沒有什么問題,但是在業務量比較大的情況下卻經常報錯:“訂單號違反主鍵約束,不能將重復的訂單號插入到訂單表中。”這是怎么回事?讓我們做一個簡單的Demo來重現一下:

  1.創建種子表和訂單表,這里只是一個簡單的Demo,所以就省去了很多字段,而且訂單號假設就是一個流水號,不用再使用年月日+6位流水號了。

CREATETABLESeek--種子表
(
  SeekValueINT
)
GO
INSERTINTOSeekVALUES(0)--種子初始值為0
GO
CREATETABLEOrders
(
  OrderIDINTPRIMARYKEY,--訂單號,主鍵
  RemarkVARCHAR(5)NOTNULL
)

  2.創建一個存儲過程,該存儲過程傳入Remark參數,根據生成的流水號插入到訂單表中:

  CREATEPROCAddOrder--Author:深藍

  @remarkVARCHAR(5)--傳入的參數

  AS

  DECLARE@seekint

  BEGINTRAN --開啟一個事務

  SELECT@seek=SeekValue--讀取種子表中的最大值作為流水號

  FROMSeek

  --生成訂單號這一步省略,因為這里假定的訂單的編號就是流水號

  UPDATESeekSETSeekValue=@seek+1--更新種子表,使最大值+1

  INSERTINTOt1VALUES(@seek,@remark)--插入一條訂單數據

  COMMIT--提交事務

  3.新建一個查詢窗口,使用以下語句調用創建的存儲過程,不斷的插入新訂單:

  WHILE1=1

  EXECAddOrder'test1'--不斷的插入訂單

  4.再新建一個查詢窗口,使用通過的方式,不斷的插入新訂單,這樣用于模擬高并發時候的情況:

WHILE1=1
EXECAddOrder'test2'

  5.運行了一段時間后,我們停止這兩個死循環,我們可以看到消息窗口中存在大量的異常:

  消息 2627,級別 14,狀態 1,過程 AddOrder,第 11 行

  違反了 PRIMARY KEY 約束 'PK__Orders__C3905BAF08EA5793'。不能在對象 'dbo.Orders' 中插入重復鍵。

  語句已終止。

  為什么會這樣呢?這得從事務隔離級別和鎖來解釋:

  一般我們寫程序時都是使用的是默認的事務隔離級別——已提交讀,在第一步查詢Seek表時,系統會為該表放置共享鎖,而鎖的兼容性中共享鎖和共享鎖是可以兼容的,所以一個事務在讀取Seek表最大值時,其他事務也可以讀取出相同的最大值,兩個事務中讀取到了相同的最大值,所以產生了相同的流水號,所以產生了相同的訂單號,所以才會出現違反主鍵約束的錯誤。

  既然知道了這其中的原理了,那么解決辦法也就有了,只需要先對種子表中的數+1,然后再進行讀取即可,修改存儲過程如下:

ALTERPROCAddOrder--Author:深藍
@remarkVARCHAR(5)
AS
DECLARE@seekint
BEGINTRAN
UPDATESeekSETSeekValue=SeekValue+1 --先修改數據
SELECT@seek=SeekValue-1--已經加了1,所以這里-1下來
FROMSeek
INSERTINTOOrdersVALUES(@seek,@remark)
COMMIT

  為什么這樣寫就可以呢?第一步執行更新操作,系統會請求更新鎖然后再升級為排他鎖,因為更新鎖和更新鎖以及排他鎖都是不兼容的,所以一個事務對Seek表進行了更新后,其他的事務就不能對表進行更新操作,只有等到事務提交以后才能繼續。

  這里附上鎖兼容性表:

現有授予模式
請求模式 IS S U IX SIX X
意向共享 (IS)
共享 (S)
更新 (U)
意向排他 (IX)
意向排他共享 (SIX)
排他 (X)


該文章在 2011/3/3 17:38:45 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved