Предотвращается ли чтение половинных значений при подсказке SELECT WITH (NOLOCK)? - PullRequest
0 голосов

Я думаю, что это вопрос между СУБД, хотя я указываю его в терминологии SQL Server.

Прочитав документацию msdn, например, [1], я не смог понять:

Можно ли выбрать значения наполовину записанных) частично перезаписанных, обновленных, удаленных, вставленных) со значениями WITH (NOLOCK) и, если нет, как предотвратить это (чтение наполовину записанных значений) (если блокировок нет уважаемый)?

Нарушение какого принципа СУБД - чтение половинного значения?
У меня возникают трудности с определением его термина (это последовательность, нарушение целостности)?
Как называется соответствующий термин?

Обновление:
Я удалил из этого поста вопросы ОБНОВЛЕНИЕ (УДАЛЕНИЕ) С (НОЛК).

MSDN документы, например, [1] и несколько статей сообщают, что SELECT WITH (NOLOCK) - это то же самое, что READUNCOMMITTED, и «общие блокировки не выдаются, чтобы помешать другим транзакциям изменять данные, считанные текущей транзакцией, и исключительные блокировки установленные другими транзакциями не блокируют текущую транзакцию от чтения заблокированных данных ".

Правильно ли я понимаю, что СУБД обеспечивает чтение только полностью записанных (подтвержденных или нет) значений?
Как это обеспечивается, если замки не используются или соблюдаются?
Вопрос не в том, какая транзакция может прочитать, что и когда, а в том, как предотвратить чтение не полностью записанных значений.

Update2:
Поскольку этот вопрос начал опускаться и закрываться, я переместил вопросы по UPDATE (DELETE) WITH (NOLOCK) на форум msdn:

Я также повторил этот же вопрос на форуме MSDN:

, что вызвало там полное замешательство.
Хотя, почему это (закрыто здесь как вопрос, не имеющий ответа)?
Это очень базовая фундаментальная концепция, имеющая простой ответ, обязательная для ясного понимания разработчиками баз данных и администраторами баз данных.

[1] Табличные подсказки (Transact-SQL)
SQL Server 2008 R2
http://msdn.microsoft.com/en-us/library/ms187373.aspx

Ответы [ 2 ]

4 голосов
/ 26 ноября 2010

Oracle не допускает грязного чтения ни при каких обстоятельствах (т. Е. При чтении незафиксированных значений другого сеанса). Это нарушает 'Изоляцию' (I в ACID ) для базы данных и потенциально дает явное несоответствие операции чтения (например, просмотр дочерней записи без родителя).

В игре два механизма. Во-первых, каждая запись имеет байт блокировки, указывающий, заблокирована ли она в данный момент или нет. Значение байта указывает на транзакцию в заголовке блока, поэтому сеанс может определить, является ли блокировка собственной или принадлежит другому сеансу. Если чтение видит, что байт установлен, он использует указатель в заголовке блока, чтобы найти более старую версию блока. Если он все еще заблокирован, он продолжает следовать указателям, пока не доберется до версии блока, где запись отображается как разблокированная. Затем он возвращает значение.

Тот же механизм также используется для согласованности по времени. Если выборка началась в 15:00, и он находит блок, измененный в 15:02, то он следует за историей, чтобы найти версию блока, которая была текущей в 3:00. Затем он может обнаружить, что требуемая запись была заблокирована в 3:00 вечера [возможно, она была зафиксирована в 15:01] и должен вернуться назад, чтобы посмотреть, какое значение было зафиксировано в 3:00 вечера.

Другой защитный механизм - защелка. Когда он читает блок, он захватывает его на время чтения. Это не позволяет другому процессу (потенциально работающему на другом процессоре) получить доступ к блоку во время чтения (т. Е. Процесс A не может установить байт блокировки в то время, когда поток B читает блок - он должен ждать, пока чтение законченный). Эти защелки являются очень низкоуровневыми операциями процессора и удерживаются только в течение очень коротких периодов времени. На одном ядре / процессоре блокировка не требуется, поскольку имеется только одно ядро, поэтому в любой момент может выполняться только один поток.

0 голосов

После некоторого созерцания и экспериментов, я полагаю, что СУБД не обеспечивают такой целостности значений:

  • Если бы мы предполагали такую ​​возможность, то мы немедленно пришли к выводу, что та же самая транзакция вВ одной и той же области транзакции могут использоваться не полностью определенные (записанные, вставленные, обновленные, удаленные) значения, чего на самом деле никогда не происходит;
  • Значения используются не только СУБД, но и вне ее операционной системой и другими программными платформами

Скорее всего, это функции транзакций, реализованные на операционной системе или даже на более низком (машинном, аппаратном) уровне.

Обновление:
Ответ Гэри поддерживает его:

"Эти защелки представляют собой операции ЦП очень низкого уровня и удерживаются только в течение очень коротких периодов времени."

Хотя я не собирался смешивать обсуждение явлений изоляции транзакций СУБД с поддержкой транзакций низкого уровня, предоставляемой оборудованием.

Update2:
И как было бы лучше назвать соответствующий термин низкого уровня (поддержка аппаратных транзакций), чтобы избежать его путаницы и несоответствия с терминологией транзакций СУБД?Это постоянство ценностей или целостность ценностей?

Update3:
Предположим, у меня есть строка 2 ГБ в nvarchar (макс.), Имеющая 1 ГБ ОЗУ.Как CPU обеспечит целостность этого значения на аппаратном уровне?

Ответ Razvan Socol в потоке msdn Предотвращено ли чтение наполовину записанных подсказок WITH (NOLOCK)? дает скрипт, перехватывающий чтение частично обновленных значений.Этот сайт в настоящее время недоступен, и я заново создаю этот код здесь:

1) Создайте тестовую таблицу и заполните ее 10 строками:

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)
В первом сеансе(вкладка SSMS) обновление, отнимающее много времени:

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

GO 1000 

3)
Во втором сеансе (вкладка SSMS) запускается перехват перезаписанных значений:

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Это SSMS SQL Server 2008 R2, довольно быстро перехватывающая кучу перезаписанных значений.
Мне интересно, каковы результаты в других СУБД?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...