четверг, 27 сентября 2012 г.

О вреде работы под Администратор 123


О вреде работы под админом в винде все знают, но всё равно работают. А вот в чём проблема работы под Администратор 123 в "АС-Библиотека-3"? Ситуация, согласись, не редкая. Вообще в библиотеках с паролями  большая проблема. Начальство требует списки паролей сотрудников в сейф, последние их забывают, а если записали, то обязательно потеряют и т.д. Поэтому, частенько, все работают под Администратором. Конечно, если коллектив небольшой и все доверяют друг другу, кроме того доступ к компьютерам только у сотрудников и сеть изолирована от Интернета - к чему эти игры в конспирацию. Однако проблема проявляется в совершенно неожиданном месте. Сам не поверил бы, если бы не увидел своими глазами. Дело, в общем то не в Администраторе, а в работе под одной учётной записью несколькими сотрудниками.
Итак, во всех многопользовательских системах обработки данных существует и успешно решается проблема "потерянных обновлений". Проще всего её показать на пальцах. Запустим два "Каталогизатора" и один "Администратор". Во всех модулях залогинимся под Администратором. В обоих "Каталогизаторах" выполним запрос одной и тоже записи (неважно какой), а в "Администраторе" сделаем выборку таблицы Demo__Lock (или другая *__Lock, если логическая база другая).


В левом "Каталогизаторе" изменим пару строк и повременим с сохранением изменений в базе. Перечитаем Demo__Lock - появилась блокировка.


Теперь изменим другое поле (например, дату) в правом "Каталогизаторе" и тоже не сохраняем.


Перечитаем Demo__Lock – та же запись, только время изменилось.


Жмём кнопку "Сохранить" в левом "Каталогизаторе".


Перечитываем Demo__Lock - таблица пустая, блокировки нет.


Жмём кнопку "Сохранить" в правом "Каталогизаторе".


Попробуй угадать, что в базе? Естественно результат второго сохранения. Перечитаем запись в обоих.


Правый "Каталогизатор" закэшировал данные и перекрыл все модификации, выполненные в левом.
Но гипотетический сотрудник, работающий за левым "Каталогизатором" уверен, что он выполнил свою работу. И впоследствии будет крайне удивлён, увидев старые данные. Это и есть один из вариантов проблемы "потерянного обновления".
А что произойдёт, если учётки разные? Перелогинимся в правом "Каталогизаторе" под "Библиотекарь" и попробуем всё повторить.


Начнём модификацию в левом. Перечитаем Demo__Lock - появилась блокировка.


Теперь попробуем модифицировать запись в правом.


Срабатывает защита.
Конечно, решение проблемы "потерянных обновлений" в "АС-Библиотека-3" немного странное, но оно работает именно так. Неважно, какими правами обладают учётки, важно, чтобы они были разными.
Аналогичная ситуация с модулями "Читатель" и "Абонемент", работающими с БД User. Попробуй сам. И не ленись писать комментарии.

четверг, 13 сентября 2012 г.

Транзакции

Этот эксперимент не касается напрямую "АС-Библиотека-3". Однако, поскольку она не может работать без поддержки СУБД он вполне уместен. К тому же производительность системы в целом существенно зависит от данного звена.

Итак, после перехода на MS SQL, решил повозиться с транзакциями, точнее различием их поведения в MS Access и MS SQL. Набросал маленький hta скриптик (в конце статьи ссылки и рекомендации для тех, кто решит повозиться сам). Смысл его в параллельном запуске двух различных SQL запросов, с различным уровнем изоляции транзакций. То есть мы, просто искусственно сталкиваем транзакции и смотрим результат. База состоит из одной таблицы Table_1, в которой два поля - fld1 и fld2. Данные появляются и изменяются в процессе работы. Вначале подключаемся к Access базе Test1.mdb и запускаем два экземпляра скрипта. По умолчанию выбрано adXactCursorStability (adXactReadCommitted) и это единственный уровень изоляции, поддерживаемый базой Access, остальные либо игнорируются, либо приводят к ошибке. В "левом" скрипте выбираем команду обновления
 update Table_1 set fld2 = :Param1 where fld1 = :Param2
и изменяем строку с fld1 = 3, присваиваем fld2 значение 7. Жмём Старт и видим окошко с предложением зафиксировать транзакцию. Пока не нажато ОК, транзакция находится в активном состоянии. В это время в "правом" скрипте запустим операцию чтения той же строки с fld1 = 3. Чтение происходит успешно.

Жмём ОК в "правом" скрипте, а затем в "левом", и смотрим результат. Всё в соответствии с описанием уровня изоляции adXactReadCommitted. "Правый" скрипт без препятствий вычитал старое значение fld2 = 3, поскольку новое fld2 = 7 ещё не было зафиксировано.


Теперь изменим параметры подключения на SQL Server, и повторим предыдущие шаги. Видим, что SQL Server встрял по полной! Как видно на скриншоте



"правый" скрипт даже PrintScreen не берёт. Более того - он встрянет даже при чтении соседней строки. Как это отражается на производительности "АС-Библиотека-3" понятно - пока кто-то проводит интенсивные изменения в базе, остальные ждут, вне зависимости от количества ядер в твоём сервере. Но главная проблема - полное несоответствие описанию поведения уровня изоляции adXactReadCommitted. Глюк? "Курим" мануалы ...
Находим интересную команду (надо сказать, что такому поведению SQL Сервера в документации посвящена целая глава и, по хорошему – сначала читаем, потом делаем, но …  ):
 alter database Test1 set read_committed_snapshot on
переводящую базу в режим контроля версий строк (off - отключить; применять в контексте базы master; работает почти мгновенно, если долго ковыряется, значит что-то блокирует базу). Применяем её и всё становится на свои места. То есть поведение блокировок ничем не отличается от Access. Посмотреть текущий режим работы баз можно запросом:
 select name, is_read_committed_snapshot_on  from sys.databases
К сожалению, протестировать этот режим в "боевых" условия при интенсивной нагрузке в настоящий момент не имею возможности - нет "полигона". Проверка в однопользовательском режиме на Демо-версии проблем не показывает, но этого мало. Если заинтересуешься и сделаешь это - сообщи в комментарии. Потребуется поддержка, готов помочь.
В конце несколько слов о содержимом архива.
Скачать архив здесь - TransactTest.zip
1. Transact.hta - запускаемый скрипт. Для редактирования строк подключения открыть в "Блокноте".
2. Test1.mdb - база Access. Для подключения в Transact.hta снять комментарий (//) и закомментировать стоку SQL Server, при необходимости откорректировать путь к базе.
3. Test1.mdf, Test1_log.ldf - база данных и журнал транзакций SQL Server. Скопируй их в стандартный каталог баз (где лежит master.mdf) или придётся возиться с настройками доступа. В Transact.hta сними комментарий со строки подключения, замени XXXX на реальный пароль sa  и закомментируй строку подключения Access. Если подключиться не удаётся – смотри в мануалах конструирование строки подключения (эта задача не тривиальна), но если ты воткнул Z-Сервер, то воткнёшь и скрипт.

На этом всё. Если есть вопросы – пиши комментарий.

Добавил видео по теме. Для просмотра лучше скачать.