Блокировка бд. Объектные блокировки. Физическая реализация блокировок в субд

Даже самый зеленый дизайнер умеет делать тени в фотошоп. Тени придают объемность дизайну и сейчас это пользуется большой популярностью. Не исключение и тени для текстов, пунктов меню и заголовков. Достаточно вспомнить оформление интерфейсов от apple

Будет полезным иметь в своем арсенале приемов навыки работы с тенями для текста.

Задача

Сделать тень для текста средствами CSS, без использования картинок. Чего мы этим добьемся?

  • гибкость — без использования картинок, текст легко менять
  • скорость — меньше картинок — меньше вес страницы, меньше обращений к серверу
  • SEO — текст лучше картинок оптимизируется, и надежней, чем использование техники замены текста картинкой

Текстовые тени для нормальных браузеров

Под нормальные браузеры попали все современные браузеры, которые шагают более-менее в ногу с рекомендациями W3C. В данном случае, эти браузеры понимают CSS3 свойство text-shadow, которое было рекомендовано еще в далеком 2003 году.

Итак, перечень браузеров, которые поддерживают свойство text-shadow:

  • Safari 3.1 (Mac/Win) — поддерживает, не поддерживаются множественные тени
  • Safari 4 (Mac/Win) — поддерживает полностью
  • Opera 9.5+ (Mac/Win/Lin) — поддерживает полностью
  • Firefox 3.1/3.5 (Mac/Win/Lin) — поддерживает полностью
  • Google Chrome 2 (Win) — поддерживает полностью
  • Shiira (Mac) — поддерживает, не поддерживаются множественные тени
  • Konqueror (Lin/Mac/Win) — поддерживает полностью
  • iCab (Mac) — поддерживает, не поддерживаются множественные тени
  • Safari on iPhone — поддерживает, не поддерживаются множественные тени
  • Nokia Symbian-Smartphones (Series 60) — поддерживает
  • Opera Mini 4.1 — поддерживает, не поддерживает размытость тени

Для этих браузеров, чтобы сделать тень тексту достаточно одной строки в CSS:

H1 { text-shadow: 0px 1px 3px #000; }

Получим вот такой модный заголовок:

С помощью text-shadow можно добиться различных интересных эффектов.

Размытый текст

H1 { color: #fff; background: #666; text-shadow: 0px 0px 3px #fff; }

Дублирование текста

H1 { text-shadow: 0px 20px #000; }

Множественные тени позволяют добиться еще нескольких эффектов:

Вдавленный текст

H1 { background: #ccc; color: #ccc; text-shadow: -1px -1px #666, 1px 1px #FFF; font-family: serif; }

Выпуклый текст

H1 { background: #999; color: #999; text-shadow: 1px 1px 3px #666, -1px -1px 3px #FFF, 1px 1px #666, -1px -1px #FFF; font-family: serif; }

(IE тут не позволит насладиться красотой, т.к. не поддерживает text-shadow). Придумать различных эффектов с помощью text-shadow можно еще массу, единственное практически ограничение — твоя фантазия.

Теперь о грустном — что делать с горячо всеми "любимым" IE?

Текстовые тени в IE

Хотя IE вплоть до 8-й версии не понимает text-shadow, у него хватает своих "примочек". В частности для создания теней есть фильтр dropShadow (). Чтобы тени появились, у элемента должен быть установлен layout. Устанавить можно несколькими способами:

  • задав элементу свойства : block + высоту() или ширину ())
  • задав элементу : absolute
  • задав : left/right
  • задав zoom: 1

H1 { filter:progid:DXImageTransform.Microsoft.DropShadow(color="#666666",offX=2,offY=2,positive="true"); zoom: 1; }

Казалось, что можно кричать "Ура!!!" и радоваться жизни, но посмотри, как этот фильтр в реальности работает:

Вот так отобразится текст, если к нему применить фильтр dropShadow

Для тех кто не понял, по пуктам недостаки этого фильтра:

  • тень выглядит ужасно: угловатая, нет плавного, с полупрозрачностью перехода в фон
  • искажается начертание шрифта
  • тень практически не поддается регулированию (управлять можно только положением тени) — это можно частично обойти применив фильтр shadow вместо dropShadow, но критичные первые два недостатка остаются
  • обязательное наличие layout несколько ограничивает разработчика

Такой результат не приемлем в реальных проектах. Непонятно кто и как принял такую работу у разработчиков.

Kilian Valkhof предложил использовать эмуляцию тени:

  1. не применять фильтр непосредственно к тексту
  2. использовать вместо dropShadow и shadow комбинацию фильров glow и blur

Это позволит избежать искажения текста и сделать тень более гибкой.

Тестовый заголовок Тестовый заголовок

H1 { text-shadow: 3px 3px 3px #cccccc; position: relative; zoom: 1; color: #000; } h1 span { position: absolute; left: -3px; top: -3px; z-index: -1; filter: progid:DXImageTransform.Microsoft.Glow(Color=#cccccc,Strength=1) progid:DXImageTransform.Microsoft.blur(pixelradius=3, enabled="true") ; zoom: 1; }

Но даже с таким подходом, все равно остается ряд недостатков:

  • несемантический код — лишний элемент, да еще и с дублированием текста скажется не лучшим образом на логичной структурности содержимого, СЕО оптимизации. Эту проблему можено решить с помощью javascript, который будет вставлять для IE дополнительный элемент при загрузке страницы
  • не соотвествие отображению в других браузерах (которые понимают text-shadow) — фильтры позволяют проэмулировать тень, с минимальными настройками. Схожести тени с другими браузерами далеко не всегда получиться добиться
  • меньшая гибкость — фильтры не дадут всех возможностей text-shadow, например не получится реализовать множественные тени

Для создания теней для IE можно воспользоваться javascript (не в первый раз javascript спасает)

Тени для текста с помощью javascript

Из скриптов, что протестировал, для себя остановился на плагине для jquery "Drop Shadow". Его достоинства:

  • эмулирует тени с помощью вставки множества контенйнеров, т.е. без использования фильтров для IE. Это дает возможность сделать максимально схожими тени в IE с другими браузерами + нет нужды беспокоится о layout для IE
  • создает тени не только для IE, что иногда может быть полезно
  • малый вес скрипта — 4Kb (если удалить комментарии из кода), а если применить сжатие, еще меньше будет. В писаниии скрипта есть требовани — наличие скрипта jquery.dimensions.js, но я так и не понял зачем он. Тени создаются, удаляются, определеяются id и без него.
  • прост и понятен в использовании
  • можно с некоторым успехом проэмулировать множественные тени

Недостатки:

  • нельзя инициализировать скрипт по id элемента
  • если элементу задан фон, тень будет создана не для текста, а для элемента в целом
  • обязательное подключение библиотеки jquery (а это более 50Kb). Но популярность jquery практически ниверлирует этот недостаток
  • по опсианию скрипта так же требуется подключение jquery.dimensions.js (еще 2Kb). Но не понял зачем эта библиотека, вроде и без нее все нормально работает

Применение плагина Drop Shadow

Синтаксис:

JQuery(selector).dropShadow(options); // создание тени у элемента jQuery(selector).redrawShadow(); // перерисовка тени jQuery(selector).removeShadow(); // удаление тени jQuery(selector).shadowId(); // возвращает id тени элемента

Left: [целое число] (по умолчанию = 4) top: [целое число] (по умолчанию = 4) blur: [целое число] (по умолчанию = 2) opacity: [дробное число] (по умолчанию = 0.5) color: [строка] (по умолчанию = "black") swap: [логическое значение] (по умолчанию = false)

Параметры left и top — координаты начала тени относительно верхнего левого угла надписи (или объекта). Положительные значения сдвигаеют тень вправо и вниз, отрицательные — влево и вверх.

Описание

Добавляет тень к тексту, а также устанавливает её параметры: цвет тени, смещение относительно надписи и радиус размытия. Свойство text-shadow может работать совместно с псевдоэлементами :first-letter и :first-line .

Синтаксис

text-shadow: none | тень [,тень]*
где тень:
<сдвиг по x> <сдвиг по y> <радиус размытия> <цвет>

Значения

None Отменяет добавление тени. цвет Цвет тени в любом доступном CSS формате. По умолчанию цвет тени совпадает с цветом текста. Необязательный параметр. сдвиг по x Смещение тени по горизонтали относительно текста. Положительное значение этого параметра задает сдвиг тени вправо, отрицательное - влево. Обязательный параметр. сдвиг по y Смещение тени по вертикали относительно текста. Также допустимо использовать отрицательное значение, которое поднимает тень выше текста. Обязательный параметр. радиус Задает радиус размытия тени. Чем больше это значение, тем сильнее тень сглаживается, становится шире и светлее. Если этот параметр не задан, по умолчанию устанавливается равным 0. Учтите, что алгоритм сглаживания в браузерах обычно разный, поэтому вид тени может несколько различаться в зависимости от заданных параметров сглаживания.

Допускается указывать несколько параметров тени, разделяя их между собой запятой. В CSS3 учитывается следующий порядок: первая тень в списке размещается на самом верху, последняя в списке - в самом низу. В CSS2 порядок наоборот: первая тень размещается в самом низу, а последняя на самом верху.

HTML5 CSS2.1 CSS3 IE Cr Op Sa Fx

text-shadow

В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!

Результат примера показан на рис. 1.

Рис. 1. Вид тени в браузере Safari

Браузеры

Opera поддерживает максимум 6–9 параметров тени. Повышение этого значения, а также увеличение радиуса размытия свыше 100px сказывается на производительности браузера. Opera версии 9.5–10 использует отображение нескольких теней, как в CSS2.

Safari до версии 4.0 поддерживает только один параметр тени, остальные игнорируются. С версии 4.0 работает уже множество теней.

Браузер Internet Explorer понимает свойство text-shadow только с версии 10.0. Взамен используется свойство filter : Shadow(параметры) . К примеру, следующая конструкция задает цвет тени (#666666), её направление (45° от вертикали) и величину смещения (4 пиксела).

filter: Shadow(Color=#666666, Direction=45, Strength=4);

Одновременный конкурентный доступ может вызывать разные отрицательные эффекты, например чтение несуществующих данных или потерю модифицированных данных. Рассмотрим следующий практический пример, иллюстрирующий один из этих отрицательных эффектов, называемый грязным чтением. Пользователь U1 из отдела кадров получает извещение, что сотрудник "Василий Фролов" поменял место жительства. Он вносит соответствующее изменение в базу данных для данного сотрудника, но при просмотре другой информации об этом сотруднике он понимает, что изменил адрес не того человека. (В компании работают два сотрудника по имени Василий Фролов.) К счастью, приложение позволяет отменить это изменение одним нажатием кнопки. Он нажимает эту кнопку, уверенный в том, что данные после отмены операции изменения адреса уже не содержат никакой ошибки.

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

Чтобы предотвратить подобные проблемы в модели пессимистического одновременного конкурентного доступа, которую мы кратко описали в предыдущей статье, каждая система управления базами данных должна обладать механизмом для управления одновременным доступом к данным всеми пользователями. Для обеспечения согласованности данных в случае одновременного обращения к данным несколькими пользователями компонент Database Engine, подобно всем СУБД, применяет блокировки. Каждая прикладная программа блокирует требуемые ей данные, что гарантирует, что никакая другая программа не сможет модифицировать эти данные. Когда другая прикладная программа пытается получить доступ к заблокированным данным для их модификации, то система или завершает эту попытку ошибкой, или заставляет программу ожидать снятия блокировки.

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

Режимы блокировки и уровень гранулярности блокировки рассматриваются в следующих двух разделах. Последующее обсуждение относится к модели пессимистического одновременного конкурентного доступа. Модель оптимистического одновременного конкурентного доступа основана на управлении версиями строк и рассматривается в последующих статьях.

Режимы блокировки

Режимы блокировки определяют разные типы блокировок. Выбор определенного режима блокировки зависит от типа ресурса, который требуется заблокировать. Для блокировок ресурсов уровня строки и страницы применяются следующие три типа блокировок:

Разделяемая блокировка (shared lock)

Резервирует ресурс (страницу или строку) только для чтения. Другие процессы не могут изменять заблокированный таким образом ресурс, но, с другой стороны, несколько процессов могут одновременно накладывать разделяемую блокировку на один и тот же ресурс. Иными словами, чтение ресурса с разделяемой блокировкой могут одновременно выполнять несколько процессов.

Монопольная блокировка (exclusive lock)

Резервирует страницу или строку для монопольного использования одной транзакции. Блокировка этого типа применяется инструкциями DML (INSERT, UPDATE и DELETE), которые модифицируют ресурс. Монопольную блокировку нельзя установить, если на ресурс уже установлена разделяемая или монопольная блокировка другим процессом, т.е. на ресурс может быть установлена только одна монопольная блокировка. На ресурс (страницу или строку) с установленной монопольной блокировкой нельзя установить никакую другую блокировку.

Блокировка обновления (update lock)

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

Система баз данных автоматически выбирает соответствующий режим блокировки, в зависимости от типа операции (чтение или запись). Блокировка обновления применяется для предотвращения определенных распространенных типов взаимоблокировок.

Возможность совмещения разных типов блокировок приводится в таблице ниже:

Эта таблица интерпретируется следующим образом: предположим транзакция T1 имеет блокировку, указанную в заголовке соответствующей строки таблицы, а транзакция T2 запрашивает блокировку, указанную в соответствующем заголовке столбца таблицы. Значение "Да" в ячейке на пресечении строки и столбца означает, что транзакция T2 может иметь запрашиваемый тип блокировки, а значение "Нет", что не может.

Компонент Database Engine также поддерживает и другие типы блокировок, такие как кратковременные блокировки (latch lock) и взаимоблокировки (spin lock).

На уровне таблицы существует пять разных типов блокировок:

    разделяемая (shared, S);

    монопольная (exclusive, X);

    разделяемая с намерением (intent shared, IS);

    монопольная с намерением (intent exclusive, IX);

    разделяемая с монопольным намерением (shared with intent exclusive, SIX).

Разделяемые и монопольные типы блокировок для таблицы соответствуют одноименным блокировкам для строк и страниц. Обычно блокировка с намерением (intent lock) означает, что транзакция намеревается блокировать следующий нижележащий в иерархии объектов базы данных ресурс. Таким образом, блокировка с намерением помещается на уровне иерархии объектов, который выше того объекта, который этот процесс намеревается заблокировать. Это является действенным способом узнать, возможна ли подобная блокировка, а также устанавливается запрет другим процессам блокировать более высокий уровень, прежде чем процесс может установить требуемую ему блокировку.

Возможность совмещения разных типов блокировок на уровне таблиц базы данных приведена в таблице ниже. Эта таблица интерпретируется точно таким же образом, как и предыдущая таблица.

Возможность совмещения разных типов блокировок
S X IS SIX IX
S Да Нет Да Нет Нет
X Нет Нет Нет Нет Нет
IS Да Нет Да Да Да
SIX Нет Нет Да Нет Нет
IX Нет Нет Да Нет Да

Гранулярность блокировки

Гранулярность блокировки определяет, какой ресурс блокируется в одной попытке блокировки. Компонент Database Engine может блокировать следующие ресурсы: строки, страницы, индексный ключ или диапазон индексных ключей, таблицы, экстент, саму базу данных. Система выбирает требуемую гранулярность блокировки автоматически.

Строка является наименьшим ресурсом, который можно заблокировать. Блокировка уровня строки также включает как строки данных, так и элементы индексов. Блокировка на уровне строки означает, что блокируется только строка, к которой обращается приложение. Поэтому все другие строки данной таблицы остаются свободными и их могут использовать другие приложения. Компонент Database Engine также может заблокировать страницу, на которой находится подлежащая блокировке строка.

В кластеризованных таблицах страницы данных хранятся на уровне узлов (кластеризованной) индексной структуры, и поэтому для них вместо блокировки строк применяется блокировка с индексными ключами.

Блокироваться также могут единицы дискового пространства, которые называются экстентами и имеют размер 64 Кбайт. Экстенты блокируются автоматически, и когда растет таблица или индекс, то для них требуется выделять дополнительное дисковое пространство.

Гранулярность блокировки оказывает влияние на одновременный конкурентный доступ. В общем, чем выше уровень гранулярности, тем больше сокращается возможность совместного доступа к данным. Это означает, что блокировка уровня строк максимизирует одновременный конкурентный доступ, т.к. она блокирует всего лишь одну строку страницы, оставляя все другие строки доступными для других процессов. C другой стороны, низкий уровень блокировки увеличивает системные накладные расходы, поскольку для каждой отдельной строки требуется отдельная блокировка. Блокировка на уровне страниц и таблиц ограничивает уровень доступности данных, но также уменьшает системные накладные расходы.

Укрупнение блокировок

Если в процессе транзакции имеется большое количество блокировок одного уровня, то компонент Database Engine автоматически объединяет эти блокировки в одну уровня таблицы. Этот процесс преобразования большого числа блокировок уровня строки, страницы или индекса в одну блокировку уровня таблицы называется укрупнением блокировок (lock escalation) . Порогом укрупнения называется граница, на которой система баз данных применяет укрупнение блокировок. Пороги укрупнения устанавливаются динамически системой и не требуют настройки. (В настоящее время пороговым значением укрупнения блокировок является 5000 блокировок.)

Основной проблемой, касающейся укрупнения блокировок, является то обстоятельство, что решение, когда осуществлять укрупнение, принимает сервер баз данных, и это решение может не быть оптимальным для приложений, имеющих различные требования. Механизм укрупнения блокировок можно модифицировать с помощью инструкции ALTER TABLE. Эта инструкция поддерживает параметр TABLE и имеет следующий синтаксис:

Параметр table является значением по умолчанию и задает укрупнение блокировок на уровне таблиц. Параметр auto позволяет компоненту Database Engine самому выбирать уровень гранулярности, который соответствует схеме таблицы. Наконец, параметр disable отключает укрупнение блокировок в большинстве случаев. (В некоторых случаях компоненту Database Engine требуется наложить блокировку на уровне таблиц, чтобы предохранить целостность данных.)

В примере ниже показана отмена укрупнения блокировок для таблицы Employee:

USE SampleDb; ALTER TABLE Employee SET (LOCK_ESCALATION = DISABLE);

Настройка блокировок

Настройку блокировок можно осуществлять, используя подсказки блокировок (locking hints) или параметр LOCK_TIMEOUT инструкции SET. Эти возможности описываются в следующих разделах.

Подсказки блокировок (locking hints)

Подсказки блокировок задают тип блокировки, используемой компонентом Database Engine для блокировки табличных данных. Подсказки блокировки уровня таблиц применяются, когда требуется более точное управление типами блокировок, накладываемых на ресурс. (Подсказки блокировок перекрывают текущий уровень изоляции для сеанса.)

Все подсказки блокировок указываются в предложении FROM инструкции SELECT. Далее приводится список и краткое описание доступных подсказок блокировок:

UPDLOCK

Устанавливается блокировка обновления для каждой строки таблицы при операции чтения. Все блокировки обновления удерживаются до окончания транзакции.

TABLOCK

Устанавливается разделяемая (или монопольная) блокировка для таблицы. Все блокировки удерживаются до окончания транзакции.

ROWLOCK

Существующая разделяемая блокировка таблицы заменяется разделяемой блокировкой строк для каждой отвечающей требованиям строки таблицы.

PAGLOCK

Разделяемая блокировка таблицы заменяется разделяемой блокировкой страницы для каждой страницы, содержащей указанные строки.

NOLOCK

Синоним для READUNCOMMITTED, который мы рассмотрим при обсуждении уровней изоляции.

HOLDLOCK

Синоним для REPEATABLEREAD.

XLOCK

Устанавливается монопольная блокировка, удерживаемая до завершения транзакции. Если подсказка xlock указывается с подсказкой rowlock, paglock или tablock, монопольные блокировки устанавливаются на соответствующем уровне гранулярности.

READPAST

Указывает, что компонент Database Engine не должен считывать строки, заблокированные другими транзакциями.

Все эти параметры можно объединять вместе в любом имеющем смысл порядке. Например, комбинация подсказок TABLOCK с PAGLOCK не имеет смысла, поскольку каждая из них применяется для разных ресурсов.

Параметр LOCK_TIMEOUT

Чтобы процесс не ожидал освобождения блокируемого объекта до бесконечности, можно в инструкции SET использовать параметр LOCK_TIMEOUT. Этот параметр задает период в миллисекундах, в течение которого транзакция будет ожидать снятия блокировки с объекта. Например, если вы хотите чтобы период ожидания был равен восемь секунд, то это следует указать следующим образом:

SET LOCK_TIMEOUT 8000

Если данный ресурс не может быть предоставлен процессу в течение этого периода времени, инструкция завершается аварийно и выдается соответствующее сообщение об ошибке. Значение LOCK_TIMEOUT равное -1 (значение по умолчанию) указывает отсутствие периода ожидания, т.е. транзакция не будет ожидать освобождения ресурса совсем. (Подсказка блокировки READPAST предоставляет альтернативу параметру LOCK_TIMEOUT.)

Отображение информации о блокировках

Наиболее важным средством для отображения информации о блокировках является динамическое административное представление sys.dm_tran_locks . Это представление возвращает информацию о текущих активных ресурсах диспетчера блокировок. Каждая строка представления отображает активный в настоящий момент запрос на блокировку, которая была предоставлена или предоставление которой ожидается. Столбцы представления соответствуют двум группам: ресурсам и запросам. Группа ресурсов описывает ресурсы, на блокировку которых делается запрос, а группа запросов описывает запрос блокировки. Наиболее важными столбцами этого представления являются следующие:

    resource_type - указывает тип ресурса;

    resource_database_id - задает идентификатор базы данных, к которой принадлежит данный ресурс;

    request_mode - задает режим запроса;

    request_status - задает текущее состояние запроса.

В примере ниже показан запрос, использующий представление sys.dm_tran_locks для отображения блокировок в состоянии ожидания:

Взаимоблокировки

Взаимоблокировка (deadlock) - это особая проблема одновременного конкурентного доступа, в которой две транзакции блокируют друг друга. В частности, первая транзакция блокирует объект базы данных, доступ к которому хочет получить другая транзакция, и наоборот. (В общем, взаимоблокировка может быть вызвана несколькими транзакциями, которые создают цикл зависимостей.) В примере ниже показана взаимоблокировка двумя транзакциями. (При использовании базы данных небольшого размера, одновременный конкурентный доступ процессов нельзя получить естественным образом, вследствие очень быстрого выполнения каждой транзакции. Поэтому в примере ниже используется инструкция WAITFOR, чтобы приостановить обе транзакции на десять секунд, чтобы эмулировать взаимоблокировку.)

USE SampleDb; BEGIN TRANSACTION BEGIN TRANSACTION UPDATE Works_on UPDATE Employee SET Job = "Менеджер" SET DepartamentNumber = "d2" WHERE EmpId = 25348 WHERE Id = 28559 AND ProjectNumber = "p2" WAITFOR DELAY "00:00:10" WAITFOR DELAY "00:00:10" UPDATE Employee DELETE FROM Works_on SET LastName = "Фролова" WHERE EmpId = 25348 WHERE LastName = "Вершинина" AND ProjectNumber = "p2" COMMIT COMMIT

Если обе транзакции в примере выше будут выполняться в одно и то же время, то возникнет взаимоблокировка и система возвратит следующее сообщение об ошибке:

Сообщение 1205, уровень 13, состояние 45 Транзакция (процесс с идентификатором 56) находится во взаимной блокировке с другим процессом и выбрана в качестве потерпевшей взаимоблокировки. Повторите выполнение команды.)

Как можно видеть по результатам выполнения примера, система баз данных обрабатывает взаимоблокировку, выбирая одну из транзакций (на самом деле, транзакцию, которая замыкает цикл в запросах блокировки) в качестве "жертвы" и выполняя ее откат. После этого выполняется другая транзакция. На уровне прикладной программы взаимоблокировку можно обрабатывать посредством реализации условной инструкции, которая выполняет проверку на возврат номера ошибки (1205), а затем снова выполняет инструкцию, для которой был выполнен откат.

Вы можете повлиять на то, какая транзакция будет выбрана системой в качестве "жертвы" взаимоблокировки, присвоив в инструкции SET параметру DEADLOCK_PRIORITY один из 21 (от -10 до 10) разных уровней приоритета взаимоблокировки. Константа LOW соответствует значению -5, NORMAL (значение по умолчанию) - значению 0, а константа HIGH - значению 5. Сеанс "жертва" выбирается в соответствии с приоритетом взаимоблокировки сеанса.

Сегодня речь пойдет о блокировках как на уровне 1С 8.3 и 8.2, так и на уровне СУБД. Блокировка данных — обязательный элемент любой системы, количество пользователей в которой больше одного.

Ниже я распишу, как работают блокировки, и каких типов они бывают.

Блокировка — это информация о том, что ресурс системы захвачен другим пользователем. Бытует мнение, что блокировка — это ошибка. Нет, блокировка — это неизбежная мера в многопользовательской системе для разделения ресурсов.

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

Блокировки в 1С делятся условно на объектные и транзакционные.

Объектные бывают, в свою очередь, оптимистическими и пессимистическими. А транзакционные можно разделить на управляемые и автоматические.

Объектные блокировки 1С

Данный вид блокировок полностью реализован на уровне платформы 1С и никак не затрагивает СУБД.

Получите 267 видеоуроков по 1С бесплатно:

Пессимистические блокировки

Эта блокировка срабатывает, когда один пользователь что-то изменил в форме справочника, а второй пытается так же изменить объект в форме.

Оптимистические блокировки

Данная блокировка сравнивает версии объекта: если два пользователя открыли форму, и один из них изменил и записал объект, то второму при записи система выдаст ошибку, что версии объектов отличаются.

Транзакционные блокировки 1С

Механизм тразакционных блокировок 1С гораздо интереснее и более функционален, чем механизм объектных блокировок. В этом механизме активно участвуют блокировки на уровне СУБД.

Неверная работа транзакционных блокировок может привести с следующим проблемам:

  • проблема потерянного изменения;
  • проблема грязного чтения;
  • неповторяемость чтения;
  • чтение фантомов.

Подробно эти проблемы были рассмотрены в статье об .

Автоматические транзакционные блокировки 1С и СУБД

В автоматическом режиме работы за блокировки целиком и полностью отвечает СУБД. Разработчик в данном случае абсолютно не участвует в процессе. Это облегчает труд программиста 1С, однако создание информационной системы для большого количества пользователей на автоматических блокировках нежелательно (особенно для СУБД PostgreSQL, Oracle BD — при модификации данных они полностью блокируют таблицу).

Для разных СУБД в автоматическом режиме используются разные степени изоляции:

  • SERIALIZABLE на всю таблицу – файловый режим 1С, Oracle;
  • SERIALIZABLE на записи – MS SQL, IBM DB2 при работе с не объектными сущностями;
  • REPEATABLE READ на записи – MS SQL, IBM DB2 при работе с объектными сущностями.

Управляемые режим транзакционных блокировок 1С и СУБД

В всю ответственность на себя берет разработчик прикладного решения на уровне 1С. При этом СУБД устанавливает достаточно высокий уровень изоляции для транзакций — READ COMMITED (SERIALIZABLE для файловой СУБД).

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

Две блокировки НЕ совместимы, если: установлены разными пользователями, имеют несовместимые виды (исключительная/разделяемая) и установлены на один и тот же ресурс.

Физическая реализация блокировок в СУБД

Физически блокировки представляют собой таблицу, которая находится в БД под названием master. Сама таблица блокировок носит имя syslockinfo.

Таблица условно имеет четыре поля:

  1. ИД блокирующей сессии SPID;
  2. что именно заблокировано RES ID;
  3. тип блокировки — S,U или X MODE (на самом деле в MS SQL их 22 типа, однако в связки с 1С используется только три);
  4. состояние блокировки — может принимать значение GRANT (установлена) и WAIT (ожидает своей очереди).

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

Процессор Баз Данных обеспечивает три уровня блокировок:

* Блокировка Базы Данных. На этом уровне блокировки к Базе Данных может обращаться только один пользователь. Такой уровень блокировки применяется для глобального изменения или обновления данных или при техническом обслуживании Базы Данных- сжатии;
* Блокировка Таблицы. На этом уровне блокировки к таблице может обращаться только один пользователь. Такой уровень блокировки применяется в тех случаях, когда необходимо обработать сразу несколько записей таблицы.
* Блокировка страницы. На этом уровне к заблокированной странице может обращаться только один пользователь. Это самый нижний уровень блокировки.

Блокировка Базы Данных

Блокиривка на уровне Базы Данных осуществляется присвоением свойству exclusive, при открытии БД, значения true. При использовании вами элемента управления data, в его свойствах установите exclusive = true . Если же вы используете объект dao, то при присвоении значения объекту db установите в true значение второго параметра метода opendatabase:

set db = dbengine.opendatabase(“c:biblio.mdb”, true)

Когда База Данных заблокирована таким образом, тодругие пользователи не смогут ее открыть. При попытке обращения к заблокированной Базе Данных вы получите сообщение:

“couldn’t use ‘c:biblio.mdb’; file already in use.” “Невозможно использовать ‘c:biblio.mdb’; файл уже используется”

Одновременно с этим генерируется перехватываемая ошибка – 3045, используя которую вы можете завершить программу, которая обращается к заблокированной Базе Данных, т.к. после возникновения ошибки программа продолжает выполняться, хотя База Данных так и не была открыта.
При использовании элемента управления data в обработчик события error вставляется следующий код:

private sub data1_error(dataerr as integer, response as integer) if err = 3045 then msgbox "Доступ к Базе Данных закрыт. Повторите запрос через несколько минут." & ,vbcritical, "data_error" end end if end sub

При использовании объекта dao в той процедуре, где будет стоять код открытия Базы Данных, вставляется обработчик ошибок:

on error goto errhandler "Здесь вставляется код открытия БД и если возникает ошибка – 3045, то она "перехватывается и обрабатывается errhandler: if err = 3045 then msgbox "Доступ к Базе Данных закрыт. Повторите запрос черезнесколько минут." & _ ,vbcritical, "data_error" end end if

Блокировка Таблицы

Блокировка на уровне таблицы применяется при глобальных изменениях в отдельно взятой таблице. После того как вы проведете ваши изменения и закроете эту таблицу, толкко тогда к ней получат доступ другие пользователи. . При использовании вами элемента управления data, в его свойствах установите exclusive = false, для того, чтобы пользователи имели доступ к Базе Данных, а свойствu option присвойте значение 3. Это приведет к томы, что выбранная вами таблица (к примеру authors) будет открыта с параметрами denywrite(1) и denyread(2), что запрещает другим пользователям открывать эту таблицу во время действия вашей программы. При попытке обращения к заблокированной таблице вы получите сообщение:
“couldn’t lock table ‘authors’;currently in use by user ‘admin’ on machine ‘user-0000011660’ “
“Невозможно зблокировать таблицу ‘authors’ , т.к. она используется администратором машины ‘user-0000011660’ “

Одновременно с этим генерируется перехватываемая ошибка – 3265, используя которую вы можете завершить программу, которая обращается к заблокированной таблице, т.к. после возникновения ошибки программа продолжает выполняться, хотя таблица так и не была открыта. При использовании элемента управления data в обработчик события error вставляется следующий код, но предварительно дополняя предыдущий:

private sub data1_error(dataerr as integer, response as integer) select case err case 3045 msgbox "Доступ к Базе Данных закрыт. Повторите запрос черезнесколько минут." & _ ,vbcritical, "data_error" end case 3265 msgbox "Доступ к таблице закрыт. Повторите запрос через несколько минут." & ,vbcritical, "data_error" end end select end sub

Если же вы используете объект dao, то при присвоении значения объекту db установите в false значение второго параметра метода opendatabase:
set db = dbengine.opendatabase(“c:biblio.mdb”, false)
а, при присвоении значении объекту recordset:
set rs = db.openrecordset(“authors”, dbopentable, dbdenyread + dbdenywrite)

Для перехвата возникающей ошибки опять ставте код:

on error goto errhandler "Здесь вставляется код открытия таблицы и если возникает ошибка – 3265, то она "перехватывается и обрабатывается errhandler: if err = 3265 then msgbox "Доступ к таблице закрыт. Повторите запрос черезнесколько минут." & _ ,vbcritical, "data_error" end end if

Здесь указан только обработчик ошибки открытия блокированной таблицы, т.к. Базу Данных вы можете открыть в другой процедуре, в отличае от элемента data.
Внимание! Если вы откроете приложении access в то время, когда у вас стоит блокировка таблицы (во время работы вашей программы), то данная таблица открывается без извещения вас диалоговым окном о том, что таблица заблокирована. Но, при всем желании вы не сможете сделать запись или произвести редактирование какой либо записи.

Блокировка страницы

Самым нижнем уровнем блокировки является уровень таблицы. Процессор microsoft jet автоматически устанавливает блокировку страницы и не может контролироваться вашей программой. Страница данных может содержатьнесколько записей, размер его равен 26 кб. Блокировка страницы означает блокировкувсех записей, находящейся на этой странице. Если длина записи – 512 байтов, то будет заблокированно 4 записи, а если 50 байтов то 40 записей. Точное число записей нельзя заранее ни определить ни задать, т.к. таблица может содержать удаленные записи (которые удаляются только во время уплотнения). Но, не смотря на это объект recordset имеет свойство lockedits, которое позволяетуправлять страничной блокировкой из программы.
Блокировка на уровне таблицы имеетдва режима – пессимистический (lockedits ю true) и оптимистический (lockedits = false). По умолчанию устанавливается пессимистическая блокировка.
Пессимистическая блокировка блокирует страницу при вызове методов edit и addnew, и остается заблокированной до тех пор пока не будетвыполнен метод update или cancelupdate. В течении всего времени ни одна программа не имеет доступа к забликированной странице.
Преимущества. Обеспечивается максимально возможныйуровень целостности данных.
Недостатки. Страница может быть заблокирована в течении продолжительного времени.
Оптимистическая блокировка блокирует страницу только при вызове метода update. Это означает, что пользователь вызывает методы edit и addnew, производит действия с дсанными, и только в момент сохранения обновления процессор microsoft jet пытается заблокировать страницу. Если все проходит успешно, то запись попадает в таблицу, но если обнаружится, что эта запись уже была отредактированна, то обновление отменяется и пользователь получаетсообщение о том, что данные были уже кем-то изменены.
Преимущества. Страница блокируется на минимально возвожное время, тен самым уменьшаетсячисло сообщений о блокировках.
Недостатки. Может привести к ошибкам блокировки при одновременном редактировании записи двумя пользователями, когда они будут проводить обновление.
Програмно это осуществляется следующим образом:

* для элемента data — data1.recordset.lockedits = true (или false);
* для объекта dao – rs.lockedits = true (или false);

При работе с пессиместической и оптимистической блокировкой используется вызов idle. Этот метод приостанавливает выполнение программы на visual basic на время обнавления динамических и статических наборов, которые были открыты этой программой. Вызов этого метода гарантирует, что в вашу программу попадут самые последние изменения в наборе данных.
Програмно это осуществляется следующим образом.



В продолжение темы:
Windows

Часть вторая : "Важнейшие характеристики каждого семейства процессоров Intel Core i3/i5/i7. Какие из этих чипов представляют особый интерес" Введение Сначала мы приведём...

Новые статьи
/
Популярные