鎖是數據庫中的一個很是重要的概念,它主要用於多用戶環境下保證數據庫完整性和一致性。 咱們知道,多個用戶可以同時操縱同一個數據庫中的數據,會發生數據不一致現象。即若是沒有鎖定且多個用戶同時訪問一個數據庫,則當他們的事務同時使用相同的數據時可能會發生問題。這些問題包括:丟失更新、髒讀、不可重複讀和幻覺讀:mysql
1.當兩個或多個事務選擇同一行,而後基於最初選定的值更新該行時,會發生丟失更新問題。每一個事務都不知道其它事務的存在。最後的更新將重寫由其它事務所作的更新,這將致使數據丟失。例如,兩個編輯人員製做了同一文檔的電子複本。每一個編輯人員獨立地更改其複本,而後保存更改後的複本,這樣就覆蓋了原始文檔。最後保存其更改複本的編輯人員覆蓋了第一個編輯人員所作的更改。若是在第一個編輯人員完成以後第二個編輯人員才能進行更改,則能夠避免該問題。sql
2. 髒讀就是指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個數據。由於這個數據是尚未提交的數據,那麼另一個事務讀到的這個數據是髒數據,依據髒數據所作的操做多是不正確的。例如,一個編輯人員正在更改電子文檔。在更改過程當中,另外一個編輯人員複製了該文檔(該複本包含到目前爲止所作的所有更改)並將其分發給預期的用戶。此後,第一個編輯人員認爲目前所作的更改是錯誤的,因而刪除了所作的編輯並保存了文檔。分發給用戶的文檔包含再也不存在的編輯內容,而且這些編輯內容應認爲從未存在過。若是在第一個編輯人員肯定最終更改前任何人都不能讀取更改的文檔,則能夠避免該問題。數據庫
3.不可重複讀是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,那麼第一個事務兩次讀到的的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,做者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可重複。若是隻有在做者所有完成編寫後編輯人員才能夠讀取文檔,則能夠避免該問題。併發
4.幻覺讀是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。例如,一個編輯人員更改做者提交的文檔,但當生產部門將其更改內容合併到該文檔的主複本時,發現做者已將未編輯的新材料添加到該文檔中。若是在編輯人員和生產部門完成對原始文檔的處理以前,任何人都不能將新材料添加到文檔中,則能夠避免該問題。fetch
因此,處理多用戶併發訪問的方法是加鎖。鎖是防止其餘事務訪問指定的資源控制、實現併發控制的一種主要手段。當一個用戶鎖住數據庫中的某個對象時,其餘用戶就不能再訪問該對象。加鎖對併發訪問的影響體如今鎖的粒度上。爲了控制鎖定的資源,應該首先了解系統的空間管理。在SQL Server 2000系統中,最小的空間管理單位是頁,一個頁有8K。全部的數據、日誌、索引都存放在頁上。另外,使用頁有一個限制,這就是表中的一行數據必須在同一個頁上,不能跨頁。頁上面的空間管理單位是盤區,一個盤區是8個連續的頁。表和索引的最小佔用單位是盤區。數據庫是由一個或者多個表或者索引組成,便是由多個this
SQL語句:日誌
LOCK TABLES tablename WRITE;
LOCK TABLES tablename READ;
INSERT INTO assignment VALUES (1,7513,'0000-00-00',5),(1,7513,'2003-01-20',8.5);
UNLOCK TABLES;對象
對於多個用戶同時提交表單,而且同時向數據庫中獲得表單ID,我是這樣解決的:索引
mysql_query("lock tables po read");
mysql_query("lock tables po write");事務
mysql_query("update po set id=id +1"));// increase po id
$sql = "SELECT id FROM po";
$result = mysql_query($sql);
if ($row = mysql_fetch_assoc($result)) {
echo $row["id"]; // this order will use this id
}
mysql_free_result($result);
mysql_query("unlock tables");
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
幫忙看看如何在這段代碼先後給數據庫寫加鎖和解鎖語句
'(在這裏給數據庫加鎖,如何寫加鎖語句?)
...............
i = str(從記錄集rst0中獲得最大入庫單號)
'若不加鎖,在這容易形成併發衝突。由於在申請到最大入庫單號以後尚未來得及創建實際記錄,其它客戶端可能也申請到了一樣的入庫單號
..............
rst.open "select * from 入庫 where 入庫單號= " + i + " and 商品ID=0 ", cn, adOpenStatic, adLockOptimistic
If rst.RecordCount = 0 Then 下一個入庫單號 = i + 1
...............
'(在這裏給數據庫解鎖,如何寫解鎖語句?)
解答1:先將須要加鎖執行的語句聲明成一個事務(如2樓),而後加鎖,SQL Server中鎖的類型不少,看你須要加哪一種類型的鎖:
HOLDLOCK 將共享鎖保留到事務完成,而不是在相應的表、行或數據頁再也不須要時就當即釋放鎖。HOLDLOCK 等同於 SERIALIZABLE。
NOLOCK 不要發出共享鎖,而且不要提供排它鎖。當此選項生效時,可能會讀取未提交的事務或一組在讀取中間回滾的頁面。有可能發生髒讀。僅應用於 SELECT 語句。
PAGLOCK 在一般使用單個表鎖的地方採用頁鎖。
READCOMMITTED 用與運行在提交讀隔離級別的事務相同的鎖語義執行掃描。默認狀況下,SQL Server 2000 在此隔離級別上操做。
READPAST 跳過鎖定行。此選項致使事務跳過由其它事務鎖定的行(這些行日常會顯示在結果集內),而不是阻塞該事務,使其等待其它事務釋放在這些行上的鎖。 READPAST 鎖提示僅適用於運行在提交讀隔離級別的事務,而且只在行級鎖以後讀取。僅適用於 SELECT 語句。
READUNCOMMITTED 等同於 NOLOCK。
REPEATABLEREAD 用與運行在可重複讀隔離級別的事務相同的鎖語義執行掃描。
ROWLOCK 使用行級鎖,而不使用粒度更粗的頁級鎖和表級鎖。
SERIALIZABLE 用與運行在可串行讀隔離級別的事務相同的鎖語義執行掃描。等同於 HOLDLOCK。
TABLOCK 使用表鎖代替粒度更細的行級鎖或頁級鎖。在語句結束前,SQL Server 一直持有該鎖。可是,若是同時指定 HOLDLOCK,那麼在事務結束以前,鎖將被一直持有。
TABLOCKX 使用表的排它鎖。該鎖能夠防止其它事務讀取或更新表,並在語句或事務結束前一直持有。
UPDLOCK 讀取表時使用更新鎖,而不使用共享鎖,並將鎖一直保留到語句或事務的結束。UPDLOCK 的優勢是容許您讀取數據(不阻塞其它事務)並在之後更新數據,同時確保自從上次讀取數據後數據沒有被更改。
XLOCK 使用排它鎖並一直保持到由語句處理的全部數據上的事務結束時。可使用 PAGLOCK 或 TABLOCK 指定該鎖,這種狀況下排它鎖適用於適當級別的粒度。
解答2」要使一表在整個處理過程當中不會被併發修改可用事務begin transelect * from 表名 with HOLDLOCK --處理語句....................commit tran加了 with holdlock後,在事務提交以前,別人動不了你的表。。。。。。。。。。。。。。。。。。。。。。。。。。。。