开发者

Is a half-written values reading prevented when SELECT WITH (NOLOCK) hint?

I think it is inter-DBMS question although I specify it in SQL Server terminology.

Having read msdn documentation, for ex., [ 1 ], I could not understand:

Is it possible to select half-written )partially-overwritten, -updated, -deleted, -inserted) values WITH( NOLOCK) values and if not how is it (half-written values reading) prevented (if no locks are respected)?

Violation of which DBMS principle is reading of half-written value?

I am having difficulties in identifying its term (is it consistence, integrity break)?

What is the name of corresponding term?

Update:

I deleted from this post the questions on UPDATE (DELETE) WITH(NOLOCK).

msdn docs, for example, [ 1 ] and multiple articles tell that SELECT WITH(NOLOCK) is the same as READUNCOMMITTED and "No shared locks are issued to prevent other transactions from modifying data read by the current transaction, and exclusive locks set by other transactions do not block the current transaction from reading the locked data".

Do I understand correctly that DBMS ensures that only completely written (committed or not) values can be read?

How is it ensured if no locks are used or respected?

This question i开发者_JAVA百科s not about which transaction can read what and when but how reading of incompletely written values is prevented.

Update2:

Since this question started to be downvoted and closed, I moved questions on UPDATE(DELETE) WITH(NOLOCK) to msdn forum:

  • What is the meaning of UPDATE and DELETE WITH(NOLOCK) statements?

I also repeated this same question in msdn forum:

  • Is a half-written values reading prevented WITH (NOLOCK) hint?

which caused there complete confusion.

Though, why is it (being closed here as not a question having an answer)?

It is very basic fundamental concept, having simple answer, obligatory for clear understanding by database developers and DBAs.

[ 1 ] Table Hints (Transact-SQL)

SQL Server 2008 R2

http://msdn.microsoft.com/en-us/library/ms187373.aspx


Oracle doesn't allow dirty reads under any circumstances (ie reading another session's uncommitted values). It violates 'Isolation' (the I in ACID) for the database and potentially gives an apparent inconsistency for the reading operation [eg seeing a child record without a parent].

There are two mechanisms in play. Firstly, each record has a lock byte indicating whether it is currently locked or not. The value of the byte points to a transaction in the block header, so a session can determine whether the lock is its own or belongs to another session. If a read sees that the byte is set then it uses a pointer in the block header to find an older version of the block. If it is still locked, it keeps following the pointers until it gets to a version of the block where the record shows as unlocked. Then it returns the value.

The same mechanism is also used for time based consistency. If a select started at 3pm and it finds a block modified at 3:02 pm then it follows the history back to find the version of the block that was current at 3:00. It may then find that the record it wants was locked at 3:00pm [it may have been committed at 3:01pm] and has to go back further to see what the committed value was at 3:00pm.

The other protection mechanism is a latch. When it reads a block, it takes a latch on it for the duration of the read. This prevents another process (potentially running on another CPU) from accessing the block during the duration of the read (ie process A cannot set the lock byte at the same time as thread B is reading the block - it has to wait until the read is finished). These latches are very low level CPU operations and are only held for very short durations. On a single core/cpu box, latching isn't necessary as there's only one core so only on thread can execute at one time anyway.


After some contemplation and experimenting, I believe, that DBMS-es do not provide such value integrity:

  • Had we assumed such possibility, then we immediately come to conclusion that the same transaction in the same transaction scope can use incompletely defined (written, inserted, updated, deleted) values what really never happens;
  • Values are used not only by DBMS but outside of it by operating system and other software frameworks

It is most probably the transaction features implemented at operating system, or even more low (machine, hardware) level.

Update:
The Gary's answer supports it:

"These latches are very low level CPU operations and are only held for very short durations."

Though, I did not intend to mix discussion of DBMS transaction isolation phenomena with low-level transaction support provided by hardware.

Update2:
And, how would be better to name the corresponding low-level (hardware transaction support) term distinctively in order to avoid its confusion and inconsistencies with DBMS transaction terminology? Is it value consistency or value integrity?

Update3:
Suppose I have 2 GB string in nvarchar(max) having 1GB RAM. How would CPU provide integrity for this value on hardware level?

The answer by Razvan Socol in msdn thread Is a half-written values reading prevented WITH (NOLOCK) hint? gives a script catching the reading of partially-updated values. That site is currently down and I re-produce this code here:

1) Create a Test table and fill 10 rows of it:

if object_id('Test') IS not NULL
drop table Test;

CREATE TABLE Test (
  ID int IDENTITY PRIMARY KEY,
  Txt nvarchar(max) NOT NULL
)
GO
-----------
INSERT INTO Test
SELECT REPLICATE(CONVERT(nvarchar(max), 
     CHAR(65+ABS(CHECKSUM(NEWID()))%26)),100000)
GO 10
---

2)
In first session (tab of SSMS) launch time-consuming update:

UPDATE Test 
SET Txt=REPLICATE(CONVERT(nvarchar(max),
           CHAR(65+ABS(CHECKSUM(NEWID()))%26)),100000)

GO 1000 

3)
In second session (tab of SSMS) launch catching half-overwritten values:

WHILE 1=1 BEGIN
  SELECT Txt FROM Test WITH (NOLOCK) 
  WHERE LEN(REPLACE(Txt,LEFT(Txt,1),''))<>0;
  select 'rowcount inside=',@@rowcount;
  IF @@ROWCOUNT<>0 BREAK
END
--for wishing to try it in non-SqlServer DBMS
-- WITH(NOLOCK) hint is another way as setting READ UNCOMMITTED tx iso level
--SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

Well, it is SSMS of SQL Server 2008 R2 catching quite rapidly a bunch of half-overwritten values.
I am curious what are the results in other DBMS?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜