Управление транзакциями в системах баз данных Понятие транзакции icon

Управление транзакциями в системах баз данных Понятие транзакции


Смотрите также:
Перспективы развития баз данных, их роль и место в распределенных информационных системах...
Учебное пособие Введение...
Тема: Базы и банки информационных данных. Понятие баз данных. Система управления базами данных...
Понятия о базах данных и системах управления ими. Классификация баз данных...
Развитие технологии баз данных...
Программа учебной дисциплины " публикация баз данных в интернете "...
Программа учебной дисциплины " публикация баз данных в интернете "...
Тема Базы данных...
Методические указания к лабораторным работам по дисциплине "организация баз данных" для...
II. анализ потребностей и обзор специализированных баз данных...
Рабочая программа дисциплины управление данными для специальности 230201 Информационные системы...
Рабочая программа дисциплины регистрация и лицензирование программ направления 010400...



Загрузка...
скачать

Базы данных, базы знаний и экспертные системы 2 Лекция 4

Управление транзакциями в системах баз данных


Понятие транзакции

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

Транзакция представляет собой последовательность операторов языка SQL, которая рассматривается как некоторое неделимое действие над базой данных, осмысленное с точки зрения пользователя. Транзакция - это логическая единица работы, выполняемая базой данных. Она может быть представлена отдельной программой, являться частью алгоритма программы или даже отдельной командой (например, командой insert) и включать произвольное количество операций, выполняемых в базе данных.

Например, если имеется структура данных следующего вида: «Персонал (номер, фамилия, адрес, телефон, должность, зарплата)», то простейшей транзакцией может быть модификация зарплаты определенного работника.

Традиционное понимание транзакции может быть охарактеризовано четырьмя классическими свойствами: атомарности (atomicity), согласованности (consistency), изолированности (isolation) и долговечности (прочности) (durability)- ACID. Эти свойства означают следующее:

  1. свойство атомарности выражается в том, что транзакция должна быть выполнена в целом или не выполнена вообще;

  2. свойство согласованности гарантирует, что по мере выполнения транзакций данные переходят из одного согласованного состояния в другое - не нарушается взаимная согласованность данных;

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

  4. свойство долговечности трактуется следующим образом: если транзакция завершена успешно, то те изменения, которые были произведены в данных, не могут быть потеряны ни при каких обстоятельствах.


^ Транзакции и целостность баз данных.

Возможны два варианта завершения работы транзакции. Если все операторы выполнены успешно и в процессе выполнения транзакции не произошло никаких сбоев программного или аппаратного обеспечения, транзакция фиксируется. Фиксация транзакции (commit)- это действие, обеспечивающее запись на диск изменений в базе данных, которые были сделаны в ходе выполнения транзакции. До тех пор, пока транзакция не зафиксирована, возможно произвести отмену всех изменений и восстановить базу данных в исходное, на момент начала транзакции, состояние. Фиксация означает, что все результаты выполнения транзакции становятся постоянными и доступными другим пользователям системы. Надо отметить, что до момента фиксации транзакции пользователи имеют дело с данными, в том виде, в котором они находились на момент начала выполнения текущей транзакции.

Если же в процессе работы случилось нечто, что делает выполнение транзакции невозможным, база данных возвращается в исходное состояние. Откат транзакции (roll back)- это действие, обеспечивающее аннулирование всех изменений данных, которые были сделаны операторами SQL в теле текущей незавершенной транзакции.

Если оказывается, что зафиксированная транзакция является ошибочной, то требуется выполнить другую транзакцию, отменяющую действия, выполненные первой транзакцией. Такая транзакция называется компенсирующей.

В стандарте ANSI/ISO SQL определены модель транзакций и функции операторов COMMIT и ROLLBACK. Стандарт определяет, что транзакция начинается с первого SQL-оператора, инициируемого пользователем или содержащемся в программе. Все последующие операторы составляют тело транзакции. Транзакция завершается одним из четырех возможных вариантов (рис.1):

  1. оператор COMMIT означает успешное завершение транзакции; его использование делает постоянными изменения, внесенные в базу данных в рамках текущей транзакции;

  2. оператор ROLLBACK прерывает транзакцию, отменяя все изменения, сделанные в рамках текущей транзакции; новая транзакция начинается непосредственно после оператора ROLLBACK;

  3. успешное завершение программы, в которой была инициирована текущая транзакция, означает успешное завершение транзакции (аналогично работе оператора COMMIT);

  4. ошибочное завершение программы прерывает выполнение транзакции (аналогично работе оператора ROLLBACK).






Рис 1


Различаются два вида ограничений целостности: немедленно проверяемые и откладываемые. К немедленно проверяемым относятся ограничения целостности, проверку которых бессмысленно или невозможно откладывать (например, ограничение на возрастные рамки - более 150 лет). Эти ограничения целостности соответствуют уровню отдельных операторов языка СУБД и при их нарушении производится не откат транзакции, а лишь отвергается определенный оператор. Откладываемые ограничения - это ограничения на базу данных, а не на какие-либо отдельные операции. По умолчанию такие ограничения проверяются в конце транзакции, и их нарушение вызывает автоматическую замену оператора COMMIT на оператор ROLLBACK. Однако в некоторых системах поддерживается специальный оператор насильственной поддержки ограничений целостности внутри транзакций.

Возможности отката и фиксации транзакция обеспечивается благодаря наличию в СУБД функции ведения журнала транзакций.


^ Параллельное выполнение транзакций.

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

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





^ Рис.2 Подсистема обработка транзакций типичной СУБД.


Менеджер транзакций осуществляет координацию работы транзакций, выполняемых прикладными программами. Он взаимодействует с планировщиком (менеджер блокировок), отвечающим за реализацию выбранной стратегии управления параллельностью; второе название применимо в том случае, если выбран протокол управления на основе системы блокировок. Цель работы планировщика – достижение максимально возможного уровня параллельности, при условии исключения влияния параллельно выполняющихся транзакций друг на друга, поскольку это может послужить источником нарушения согласованности базы данных. Если в процессе выполнения транзакции происходит откат, то база данных может находиться в несогласованном состоянии. Задачей менеджера восстановления является предоставление гарантий того, что в подобном случае база данных будет автоматически восстановлена в то состояние, в котором она находилась на момент начала выполнения транзакции. Менеджер буферов отвечает за передачу данных основной памяти компьютера и вторичной дисковой памяти.


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

  1. ^ Пропавшие (незафиксированные) изменения. Эта ситуация может возникнуть, возникнуть в том случае, когда две транзакции одновременно выполняют изменения в одной и той же записи. Например, два оператора работают на приеме заказов. Первый оператор принял заказ на 30 мониторов, в то время как на складе хранилось 40 мониторов. Получив подтверждение на заказ от покупателя, оператором был выставлен счет на это количество товара и оформлена покупка (обновление записи о количестве товара на складе – 10). В это же время второй оператор принимает заказ на 20 мониторов, принимая во внимание начальное их количество на складе – 40 штук, и также оформляет покупку (также выполняет команду обновить для количества товара на складе- 10). Таким образом, было продано 50 мониторов, в то время как фактически их количество – 40, и на складе существует положительный остаток в 10 ед. База данных находится в несогласованном состоянии, по той причине, что изменения, сделанные операторами были проигнорированы.

  2. ^ Проблемы промежуточных данных. Рассмотрим эту же ситуацию. Первый оператор ведет переговоры с заказчиком и указывает в заказе 30 мониторов, однако перед окончательным выставлением счета он намеревается уточнить некоторые характеристики товара. На диске уже зафиксированы изменения в остатках товара на складе, произведенные первым оператором (остаток – 10 ед. товара). В это время второй оператор работает над формированием собственного заказа на 20 ед. товара, и последние данные по остаткам товара не позволяют ему этот заказ сформировать; приложение второго оператора оканчивает работу. После уточнения характеристик покупаемого товара, первый заказчик отказывается от покупки 30 мониторов, и приложение первого оператора выполняет откат транзакции, возвращая нас к исходному значению товара на складе в 40 ед. Такая ситуация сложилась по той причине, что в процессе выполнения второй транзакции был открыт доступ к данным, которые сформировала первая транзакция.

  3. ^ Проблема несогласованных данных. Представим себе, что, начиная работать почти одновременно, оба оператора получают информацию о наличие на складе 40 ед. товара. Первый оператор завершает переговоры со своим клиентом и продает ему 30 ед. товара; транзакция завершается оператором COMMIT. Состояние базы данных расценивается как непротиворечивое. Пока второй оператор согласовывал условия заказа, он получает новое состояние склада, которое уже успело измениться. База данных находится в непротиворечивом состоянии, однако второй оператор считает, что нарушена целостность выполнения его транзакции. Это состояние возникло по той причине, что транзакция первого оператора смогла изменить кортеж с данными, который уже был прочитан второй транзакцией.

  4. ^ Проблемы строк - признаков. Предположим, что необходимо подготовить два отчета за анализируемый период: стандартный и расширенный. В то время когда приложение печати начинает формировать первый отчет, оператор принимает еще один заказ, укладывающийся в указанный период. Это приводит к тому, что к моменту формирования расширенного отчета в базе данных появились новые данные. Полученные отчеты в рамках одной транзакции содержат противоречивые данные. Это вызвано тем, что, хотя базы данных находилась в согласованном состоянии, приложения печати работали некорректно.


^ Сериализация транзакций.

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

^ Сериализация транзакций - это механизм выполнения транзакций по некоторому сериальному плану. Обеспечение такого механизма является основной функцией компонента СУБД, ответственного за управление транзакциями.


Данная дисциплина опирается на следующие правила:

  1. В процессе выполнения транзакции программа «видит» только согласованные состояния базы данных; пользователь никогда не может получить доступ к незафиксированным изменениям в данных, достигнутым в результате действия другой программы;

  2. Если две транзакции А и В выполняются параллельно, то СУБД полагает, что результат будет такой же, как если бы: - транзакция А выполнялась бы первой, а за ней - выполнялась другая транзакция В, т.е. последовательно.


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


W - W - транзакция 2 пытается изменить объект, измененный незаконченной транзакцией 1;

R - W - транзакция 2 пытается изменить объект 1, прочитанный незаконченной транзакцией 1;

W - R - транзакция 2 пытается прочитать объект, измененный не законченной транзакцией 1.


Существующие практические методы сериализации основываются на учете этих конфликтов.


^ Методы сериализации транзакций.

Существует два базовых подхода к сериализации транзакций: подход, метод, основанный на синхронизационных захватах (блокировках) объектов базы данных, и подход, основанный на использовании временных меток. Для каждого из этих подходов могут существовать пессимистические и оптимистические варианты решения; первые отличаются тем, что применяются в тех ситуациях, когда конфликты возникают часто и распознаются и разрешаются немедленно при их возникновении; вторые - основываются на том, что результаты всех операций на объектами базы данных сохраняются в рабочей памяти транзакций. Рассмотрим некоторые методы сериализации транзакций с учетом их пессимистических разновидностей.


^ Синхронизационные блокировки.

Этот метод считается наиболее распространенным для централизованных СУБД, в том числе для систем архитектуры «клиент-сервер», и основан на соблюдении двухфазного протокола синхронизационных блокировок (захватов) объектов. Суть этого протокола состоит в том, что перед выполнением любой операции в транзакции Т над объектом базы данных А, от имени транзакции Т запрашивается синхронизационный захват объекта А в соответствующем режиме.

Основными режимами синхронизационных захватов (блокировок) являются:

  • совместный (взаимный) режим - S (Shared), означающий разделяемый захват объекта и требуемый для выполнения операции чтения объекта;

  • монопольный захват - X (eXclusive), означающий монопольный захват объекта и требуемый для выполнения операций занесения, удаления и модификации.


Захваты объектов несколькими транзакциями по чтению совместимы, т.е. нескольким транзакциям разрешено одновременное чтение одного и того же объекта; захват объектов одной транзакцией по чтению не совместим с захватом другой транзакцией того же объекта по записи; захваты одного объекта разными транзакциями по записи не совместимы (рис.3).





X

S

-

да

да

X

нет

нет

S

нет

да


Рис.3


“-” соответствует состоянию объекта, для которого не установлен никакой захват; транзакция, запросившая синхронизационный захват объекта базы данных, уже захваченный другой транзакцией, блокируется до тех пор, пока захват этого объекта не будет снят.

“нет” - конфликтные ситуации, рассмотренные ранее.


На основании X- и S- блокировок может быть основан протокол доступа к данным:

  1. Транзакция, предназначенная для извлечения объекта базы данных, должна осуществить наложение S- блокировки на выбранный объект базы данных.

  2. Транзакция, предназначенная для обновления объекта базы данных, должна осуществить наложение X-блокировки на объект базы данных.

  3. Если запрашиваемая блокировка со стороны второй транзакции отвергается из-за конфликта с некоторой другой блокировкой со стороны первой транзакции, то вторая транзакция переходи в режим ожидания.

  4. X-блокировки не снимаются до конца выполнения транзакции (или до выполнения операторов COMMIT, ROLLBACK).


Для обеспечения сериализации транзакций синхронизационные захваты объектов, произведенные по инициативе транзакции, можно снимать только после ее завершения. Это требование порождает двухфазный протокол синхронизационных захватов - 2 PL (Two-Phase Locks). В соответствии с этим протоколом выполнение транзакции разбивается на две фазы: накопление захватов и освобождение захватов (после фиксации или отката).


Рассмотрим пример выполнения транзакции с использованием механизма блокировок: Выполняются две транзакции Т1 и Т2, объектом изменения определен кортеж р некоторой таблицы базы данных.


Т1 Т2

t1 Обновление кортежа р

(X-блокировка)

Извлечение кортежа р t2

(S-блокировка) S-X несовместимы

ожидание t3

ожидание t4 COMMIT

(снятие X-блокировки)

Извлечение кортеж р t5

(S-блокировка)


(Пример восстановлен не точно!)


Таким образом, механизм блокировок разрешает проблемы, связанные с доступом нескольких пользователей к одним и тем же данным. Однако его применение существенно замедляет выполнение самой транзакции, что вызвано необходимостью ожидания освобождения занятых данных. Здесь возникает вопрос, что считать объектом для синхронизационного захвата: страницу данных, файл, отношение кортеж? Чем крупнее объект синхронизационного захвата, тем меньше синхронизационных захватов будет задерживаться в системе, тем меньше накладные расходы. Но при такой ситуации появляется вероятность увеличения числа конфликтов транзакций и тем самым уменьшается допускаемая степень их параллельного выполнения. Если СУБД реализована таким образом, что может захватывать для выполнения транзакции отдельные строки, то скорость обработки существенно повысится. Блокировка на уровне строк позволяет достигнуть максимальной производительности за счет того, что объект (запись) является минимальной структурной единицей базы данных.


^ Тупиковые ситуации (dead-locks).

Одним из наиболее чувствительных недостатков метода сериализации транзакций на основе синхронизационных захватов является возникновение тупиков (взаимных блокировок) (dead - locks) между транзакциями. При возникновении подобной ситуации две или более транзакций находятся во взаимном ожидании освобождения блокировок, удерживаемых каждой из них. Рассмотрим пример возникновения тупика: пусть транзакции Т1и Т2 установили монопольные захваты, соответственно, объектов А1 и А2, после этого транзакция Т1 требуется совместный захват А2, а транзакции Т2 - совместный захват А1. Ни одна транзакция не может продолжиться, монопольные захваты не смогут быть сняты, следовательно, совместные захваты не будут удовлетворены. Поскольку тупики возможны, и никакого естественного выхода из них не может быть, то необходимо такие ситуации обнаруживать и искусственно устранять.

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

При использовании метода предупреждения тупиков СУБД заранее определяет ситуации, в которых транзакции могут вызывать появление этой нежелательной ошибки, и предотвращает их возникновение. Один из возможных подходов предупреждения тупиковых ситуаций состоит в установлении порядка выполнения транзакций на основе использования временных меток. Например, известный метод «Ожидание-отмена» требует, чтобы новые транзакции ожидали завершения старых; в противном случае, транзакция отменяется и перезапускается стой же самой временной меткой. Рано или поздно, эта транзакция станет самой старой из активных транзакций, и поэтому не сможет быть отменена.

Второй подход к обработке тупиковых ситуаций носит название метода выявления взаимных блокировок. В этом случае СУБД допускает появление подобных ситуаций в системе, однако затем распознает и появление и организует выход из сложившейся тупиковой ситуации. Этот метод более прост в реализации, и поэтому нашел практическое применение.

Основой обнаружения тупиковых ситуаций является построение (или постоянное поддержание) графа ожидания транзакций (wait-for-graph – WFG). Граф ожидания транзакций - это ориентированный двудольный граф, вершинами которого являются транзакции и объекты захвата, т.е. граф отражает зависимость транзакций друг от друга. Транзакция Тi зависит от транзакции Тj, если транзакция Тj заблокировала элемент данных, необходимый для продолжения работы транзакции Тi. Граф ожидания строится следующим образом:

-для каждой выполняющейся транзакции создается отдельная вершина;

-отдельное направленное ребро (дуга) Тi Tj создается для каждого случая, когда транзакция Ti ожидает освобождения элемента, заблокированного транзакцией Tj .

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





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

В случае нахождения тупиковой ситуации необходимо обеспечить возможность продолжения работы хотя бы для части транзакции, попавшей в тупик. Разрушение тупика начинается с выбора в цикле транзакции - жертвы, т.е. транзакции, которой решено пожертвовать, чтобы обеспечить возможность продолжения работы других транзакций. Критерием выбора является минимизация стоимости транзакции; стоимость определяется на основе многофакторной оценки, в которую входят с разными весами время выполнения, число накопленных захватов, приоритет.

После выбора транзакции - жертвы производится ее откат, что обеспечивает продолжение работы другим транзакциям. Такое насильственное устранение тупиковых ситуаций является нарушением принципа изолированности.


^ Метод временных меток.

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

Основная идея метода состоит в следующем: если транзакция Т1 началась раньше транзакции Т2, то система обеспечивает такой режим выполнения, как если бы Т1 была целиком выполнена да начала Т2.

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


^ Уровни изолированности пользователей.

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

Уровни изолированности пользователей связаны с проблемами, которые возникают при параллельном выполнении транзакций и которые были рассмотрены ранее. Существуют 4 уровня изолированности пользователей.

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

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

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

Самый низкий уровень изолированности называют уровнем неподтвержденного, или «грязного» чтения. При этом уровне изолированности текущая транзакция видит промежуточные и несогласованные данные, и также ей доступны строки-призраки. Однако даже на этом уровне изолированности СУБД предотвращает попавшие обновления.

В SQL2 существует оператор выбора уровня изолированности выполнения транзакции. В разных коммерческих СУБД могут быть реализованы не все уровни изолированности, это необходимо уточнять в технической документации.


^ Мониторы транзакций.

Мониторы транзакций - Transaction Processing Monitor (TPM) - программные системы (относится к категории программного обеспечения промежуточного слоя middlware), обеспечивающие эффективное управление информационно-вычислительными ресурсами в распределенной среде. они представляют собой гибкую открытую среду для разработки и управления мобильными приложениями, ориентированными на оперативную обработку распределенных транзакций. В числе важнейших характеристик мониторов транзакций - маштабируемость, поддержка функциональной полноты и целостности приложений, достижение максимальной производительности обработки данных в гетерогенной среде.


Рекомендуемая литература:

  1. Дейт К. Дж. Введение в системы баз данных.: Пер. с англ. - 6-е изд. - К.: Диалектика,1999. – 784 с.

  2. Кагаловский М.Р. Энциклопедия технологий баз данных. – М.: Финансы и статистика, 2002. – 800с.

  3. Конолли Т., Бегг К., и др. Базы данных: проектирование, реализация и сопровождение. Теория и практика, 2-е изд.: Пер. с англ.: Уч. пос. – м,: Издательский дом «Вильямс», 2000. – 1120 с.

  4. Системы управления базами данных. Журнал издательского дома "Открытые системы", 1995 -2001 гг.


^ Ключевые слова:

транзакция

атомарность

изолированность

согласованность

долговечность

фиксация транзакции

откат транзакции

откладываемые ограничения

немедленно проверяемые ограничения

сериализация

сериальный план

метод синхронизационных захватов

метод временных меток

синхронизационные блокировки

совместный захват

монопольный захват

двухфазный протокол синхронизационных захватов

режим ожидания

тупиковая ситуация

взаимные блокировки

граф ожидания транзакции

протокол о намерениях

уровень изолированности пользователей

мониторы транзакций



 Н.Алтухова, 2004 www.inf-man.ru




Скачать 179,76 Kb.
оставить комментарий
Дата19.10.2011
Размер179,76 Kb.
ТипЛекция, Образовательные материалы
Добавить документ в свой блог или на сайт

Ваша оценка этого документа будет первой.
Ваша оценка:
Разместите кнопку на своём сайте или блоге:
rudocs.exdat.com

Загрузка...
База данных защищена авторским правом ©exdat 2000-2017
При копировании материала укажите ссылку
обратиться к администрации
Анализ
Справочники
Сценарии
Рефераты
Курсовые работы
Авторефераты
Программы
Методички
Документы
Понятия

опубликовать
Загрузка...
Документы

наверх