Автор работы: Пользователь скрыл имя, 30 Января 2013 в 03:08, курсовая работа
Методологической и теоретической основой исследования послужили работы зарубежных и российских авторов в области бизнес-планироания, менеджмента и маркетинга, связанные с тематикой работы.
Информационную основу исследования составили маркетинговые исследования, проводимые российскими консалтинговыми компаниями, работающими на рынке недвижимости, а также данные, полученные в ходе исследования деятельности конкурентов.
В качестве инструментов исследования были использованы сравнительный и системный анализ, качественное и количественное изучение реальности, экономико-статистические методы.
Практическое значимость предложенных рекомендаций заключается в том, что их использование позволит создаваемому агентству недвижимости успешно выйти на рынок недвижимости Москвы.
TIBRestoreService - передает серверу
команду на восстановление
TIBValidationService - аналог gfix, осуществляет
проверку БД и/или ремонт
TIBStatisticalService - аналог gstat, получает статистику из базы данных. см. IBAnalyst.
TIBLogService - позволяет получить содержимое interbase.log с сервера.
TIBSecurityService - управляет пользователями
в isc4.gdb, admin.ib или security.fdb (посредством
сервера, разумеется). Позволяет
добавлять, удалять,
TIBServerProperties - позволяет получить
информацию о сервере,
TIBLicensingService - работает только с платными версиями InterBase. Позволяет управлять пользовательскими и процессорными лицензиями на сервере (также серверными для 7.0. В 7.1 и 7.5 серверные и unlimited users лицензии регистрируются только через инсталлятор). IBConsole для управления лицензиями использует именно этот компонент.
TIBInstall, TIBUninstall - компоненты, обеспечивающие
установку, регистрацию и
Использование и управление IBTransaction в приложениях
Существование IBTransaction дает
возможность не только управлять
параметрами транзакций целиком
и полностью, но и полноценно управлять
стартом и завершением
Весь ужас в том, что при отсутствии контроля над транзакциями вы не можете понять, что происходит. Производительность системы может деградировать с каждым часом, и сделать практически ничего нельзя (кроме рестарта сервера и обретения спокойствия еще на несколько часов).
Конечно, InterBase 7.5 и выше или Firebird 2.1 и выше дадут вам возможность выяснить (при помощи временных системных таблиц tmp$ или mon$ соответственно), что же за транзакция активна уже 3 часа, и сколько их вообще таких существует. И можно эти транзакции принудительно завершить (или отловить пользователей, которые открывают ненужную форму, или не закрывают приложения уходя с работы). Но выяснить можно, а вот исправить - нет. То есть, необходимость переделки пользовательских приложений зависнет над вашей головой как дамоклов меч.
Поскольку, как уже было сказано, IBX (как и FIBPlus) позволяет полноценно управлять транзакциями, следует соблюдать несколько правил:
Никогда не полагайтесь на defaultTransaction, неявный старт транзакций или их автоматическое завершение. У вас должна быть всегда возможность выяснить, в каком месте кода и с какими параметрами стартует конкретная транзакция, и когда завершается. Это увеличивает количество строк кода? Да, несомненно, но не намного, однако работа ваших приложений улучшится в геометрической прогрессии. При этом в коде будет четко видно, какие операции выполняются в транзакции (если, конечно, не вызывать Commit/Rollback в другом модуле относительно StartTransaction).
Не рекомендуется стартовать или завершать транзакции обращением к свойству IBTransaction.Active. В описании IBTransaction об этом уже было сказано, но стоит повторить еще раз - привычка вызывать в коде Active так же, как вы это делаете в дизайн-тайме (кликая на свойство active в Object Inspector) может сослужить плохую службу - если транзакция в IBTransaction уже активна, то при вызове IBTransaction.Active:=False; транзакция безусловно завершится по Rollback (это можно легко увидеть в коде IBDatabase.pas, метод TIBTransaction.SetActive). Поэтому, а также для улучшения читаемости кода, свойство Active рекомендуется использовать только для проверки состояния компонента (для этого есть свойство inTransaction, кстати). А старт и завершение транзакции лучше всегда писать явно, используя методы StartTransaction, Commit или Rollback.
примечание: в FIBlus свойство TimeoutAction (аналогичное DefaultAction в IBX) равно taRollback. Это нужно учитывать, особенно если вы планируете заменить IBX на FIBPlus. Кстати, если при закрытии IBDatabase к нему "прицеплены" активные транзакции, то они завершаются как раз по TimeoutAction/DefaultAction, а не как Active:=False. Соответственно, при таком завершении (IBDatabase.Close, IBTransaction.Free) приложения в IBX изменения, произведенные в незакрытых к этому моменту транзакциях сохранятся, а в FIBPlus - исчезнут. Умолчательное поведение обоих наборов компонент может быть нежелательным в различных случаях.
Транзакция - это блок логической работы (последовательность операторов), который либо переводит базу данных из одного целостного состояния, либо оставляет в исходном состоянии. То есть, между StartTransaction и Commit/Rollback может быть любое число команд SQL, но оно должно быть осмысленным и взаимосвязанным.
Самый типичный пример транзакций - перевод денег с одного счета на другой.
StartTransaction;
update accounts set ac1 = ac1 - 100 where user_id = :x;
update accounts set ac2 = ac2 + 100 where user_id = :x;
Commit;
Здесь первый оператор снимает
определенную сумму с одного счета,
а второй - прибавляет эту сумму
к другому счету. Если бы не было
транзакций, то при сбое после выполнения
1-го оператора у некоего
При работе с транзакциями все нормально - ни одна другая конкурирующая транзакция (приложение) не увидит изменений (перевода денег с одного на другой счет), пока "переводящая" транзакция не завершится. Более того, если она завершится по Rollback, база данных (и состояние счетов пользователя) останется нетронутым.
Итак, вы сами определяете, что выполняется в транзакции. Тут все зависит от требований прикладной задачи. Допустим, вы решаете выписку накладной оформить в одной транзакции. Это хорошо. Однако, если позиций в накладной может быть много, и примерно "посередине" оформления накладной произойдет сбой приложения (сети, сервера и т.п.), то оператору придется все начинать сначала. Появление требования к сохранности промежуточного ввода может потребовать отказаться от оформления всей накладной в одной длинной транзакции. Может получиться, что выгоднее с этой точки зрения каждый элемент накладной вводить и сохранять в отдельной короткой транзакции.
Точно так же к использованию
коротких транзакций вас может подвигнуть
организация "списывания" товара
(путем update таблицы товаров) при его
выписке в накладной (триггером
на insert/update/delete). Если выписка одной
накладной занимает некоторое время,
то возрастет вероятность
Транзакции должны быть максимально короткими, независимо от условий задачи. Вы можете спросить - а как же просмотр данных, или ввод большой "карточки"? Здесь есть два исключения - в Firebird с 1.0 и InterBase с 6.0 транзакции read read_committed rec_version - они стартуют сразу в "завершенном" состоянии, поэтому могут длиться вечно (без необходимости commit/rollback и без влияния на накопление или сборку мусора). И второе - транзакции snapshot, которые обычно используются для формирования отчетов. Но, в любом случае, стартовать транзакцию при открытии формы, а потом ждать действий пользователя, который на самом деле вполне мог в этот момент уйти на обед - плохо для версионного сервера.
То есть, в версионном сервере с длительностью транзакций легче, чем в блокировочном. Например, "короткой" можно считать транзакцию длительностью и в пол-часа. Но, здесь все зависит от активности конкурирующих транзакций. То есть, длительность транзакции - понятие относительное. И в версионном сервере она влияет не на блокировку записей (в отношении update/delete - разумеется да, но не по чтению) , а на количество накапливаемых версий записей, которые могли бы стать "мусором", если бы транзакция была короче.
Конечно, к длительной работе с транзакциями подвигают стандартные Data Controls компоненты вроде DBEdit. Для того чтобы редактировать данные вы должны работать с открытым DataSet. А он может быть открыт только во время работы транзакции (использование ClientDataSet или CachedUpdates пока опустим). Многие разработчики уже поняли этот недостаток, и действуют не по следующей схеме
StartTransaction;
IBDataSet.Edit; // вход в режим редактирования
ожидание ввода пользователя
IBDataSet.Post; // отправка результатов редактирования на сервер
Commit;
А по другой:
получаем данные из DataSet, прицепленного к читающей транзакции ожидаем ввод пользователя в компонентах TEdit и т.п. по нажатию кнопки "Сохранить"
StartTransaction
IBDataSet.Edit;
// заполняем столбцы или параметры запроса данными из обычных контролов
IBDataSet.Post;
Commit;
Как видите, во втором случае длительность транзакции минимальна, т.к. она не зависит от того, сколько минут или часов пользователь набивает изменения одним пальцем на клавиатуре. Конечно, настоящие разработчики даже IBDataSet.Edit не вызывают. Вместо этого они используют отдельный компонент IBSQL с запросом update, и заполняют параметры запроса из контролов редактирования данных. Это дает возможность избежать головной боли по поводу "редактируемых запросов", а также гарантирует полный контроль над тем, что происходит в программе. Больше кода? Увы, да. Но если вы делаете нечто сложнее примера "Телефонная Книга" или курсовой, вам придется использовать такой подход.
Транзакций должно быть столько, сколько нужно в данный момент. Самый безобразный пример - в поставке Delphi, IBMastApp. Там всего один компонент IBTransaction на все приложение. Кстати, возможно некоторых смутила фраза "...прицепленного к читающей транзакции" в предыдущем примере. Ничего сложного здесь нет. Операторов SQL для работы с данными всего 5, и делятся они на две группы - которые читают данные, и которые модифицируют. Соответственно, можно взять два компонента IBTransaction, положить их на форму, и к одному прицеплять те IBDataSet, которые показывают данные в гридах, лукапах, комбобоксах и т.п., а ко второму - которые модифицируют данные (например IBSQL/IBQuery с операторами insert/update/delete).
Отсюда следует, что по человечески с компонентом IBDataSet (а также с упомянутой ранее комбинацией IBQuery + IBUpdateSQL) в одной транзакции работать не получится. И действительно - к IBDataSet можно прицепить только одну транзакцию. Но IBDataSet может одновременно как читать так и редактировать данные. А для сохранения изменений данных придется делать Commit. А выполнение Commit приведет к тому, что IBDataSet будет автоматически закрыт, значит для удобства пользователя его надо снова открыть (а значит еще раз выполнится запрос на чтение данных, что нагрузит сервер и сеть), и спозиционировать на ту запись, на которой до сохранения данных (и Commit) находился пользователь.
Эта проблема решается, причем один из способов описан выше - это вынос запросов insert/update/delete в отдельные компоненты IBSQL/IBQuery. Второй способ - использование IBQuery + специальная модификация IBUpdateSQL (см. IBUpdateSQLW выше), которая может быть "прицеплена" к другой транзакции, нежели IBQuery (В FIBPlus компонент pFIBDataSet по умолчанию имеет 2 свойства для подключения читающей и пишущей транзакции). Таким образом, получается, что мы можем выполнять чтение (IBQuery) в одной транзакции, а модификацию (IBUpdateSQL) - в другой. И эту другую, пишущую транзакцию, можно сделать максимально короткой - в самом простом случае в ней будет выполняться всего один оператор.
примечание: Под "читающей" и "пишущей" транзакцией имеются в виду два компонента IBTransaction, в контексте которых будут выполняться операции чтения и записи. По умолчанию стартуемая транзакция (вообще) работает в режиме read write, поэтому при таком использовании транзакций параметры у них нужно указывать явно (вообще указывать параметры транзакций желательно всегда, даже умолчательные - по крайней мере так на форме вам будет легче понять, в каком режиме будет работать транзакция. Кроме того, как было указано выше, умолчательные параметры компонента, управляющего транзакциями, отличаются у IBX и FIBPlus). Как указать параметры транзакции только для чтения (и другие) см. в этом же документе, или в общем описании параметров транзакций.
На рисунке изображен пример формы с указанными компонентами. TR и TW - читающая и пишущая транзакции соответственно, IBQuery1 прицеплен к TR, а IBUpdateSQLW1 - к TW.
На такую читающую транзакцию можно "навесить" массу других читающих IBDataSet/IBQuery (на картинке компоненты лежат на форме, но они могут быть и в DataModule). Например, в трехзвенных приложениях такую транзакцию можно использовать для чтения справочников. Количество же "пишущих" транзакций не ограничено.
примечание: по использованию
транзакций в FIBPlus читайте статью www.devrace.com/ru/fibplus/
CommitRetaining?
Выше не случайно упомянут пример IBMastApp. Также тема завершения транзакций подробно изложена в документе. Кроме этого, если использовать компонент FIBPlus.pFIBDataSet с двумя разными транзакциями, пишущая транзакция по умолчанию выполняет CommitRetaining сразу после выполнения операторов (действий) Insert/Update/Delete. Это поведение неверно (! зависит от версии FIBPlus. Обязательно проверьте поведение вашей версии при помощи компонента SQLMonitor, и только потом следуйте указанному здесь совету по настройкам timeOutAction. Также см. статью по управлению транзакциями в FIBPlus.). Короткую транзакцию не нужно завершать CommitRetaining. На самом деле CommitRetaining просто продлевает жизнь транзакции, а соответственно из "короткой" превращает ее в длинную. То есть, для сервера завершение по CommitRetaining будет сохранять все те побочные эффекты, которые вызываются длинными транзакциями.