Назад в раздел
InfoCity
ЭТА ГЛАВА БУДЕТ ОБСУЖДАТЬ АСПЕКТЫ ЯЗЫКА SQL которые имеют отношение
к базе данных как к единому целому, включая использование многочисле-
ных имен для объектов данных, размещение запоминаемых данных, восста-
новлние и сохранение изменений в базе данных а также координирование
одновременных действий многочисленных пользователей. Этот материал
даст вам возможность конфигурации вашей базы данных, отмены действия
ошибок, и определения как действия одного пользователя в базе данных
будут влиять на действия других пользователей.
Каждый раз, когда вы ссылаетесь в команде к базовой таблице или
представлению не являющимися вашей собственностью, вы должны устано-
вить в ней префикс имени владельца, так что бы SQL знала где ее ис-
кать. Так как это со временем становится неудобным, большинство реали-
заций SQL позволяют вам создавать синонимы для таблиц ( что не являет-
ся стандартом ANSI ) Синоним - это альтернативное имя, наподобии проз-
вища, для таблицы. Когда вы создаете синоним, вы становитесь его собс-
твенником, так что нет никакой необходимости, чтобы он предшествовал
другому пользовательскому идентификатору доступа( имени пользователя )
Если вы имеете по крайней мере одну привилегию в одном или более
столбцах таблицы; вы можете создать для них синоним. ( Некоторое отно-
шение к этому может иметь специальная привилегия для создания синони-
мов.)
Adrian может создать синоним с именем Clients, для таблицы с именем
Diane.Customers, с помощью команды CREATE SYNONYM следующим образом:
CREATE SYNONYM Clients FOR Diane.Customers;
Теперь, Adrian может использовать таблицу с именем Clients в команде
точно так же как ее использует Diane.Customers. Синоним Clients - это
собственность, используемая исключительно для Adrian.
Префикс (прозвище) пользователя - это фактически часть имени любой
таблицы. Всякий раз, когда вы не указываете ваше собственное имя поль-
зователя вместе с именем вашей собственной таблицы, SQL сам заполняет
для вас это место. Следовательно, два одинаковых имени таблицы но свя-
занные с различными владельцами, становятся не идентичными и следова-
тельно не приводят к какому-нибудь беспорядку (по крайней мере в SQL).
Это означает что два пользователя могут создать две полностью несвя-
занные таблицы с одинаковыми именами, но это также будет означать, что
один пользователь может создать представление основанное на имени дру-
гого пользователя стоящем после имени таблицы. Это иногда делается
когда представление, рассматривается как сама таблица - например, если
представление просто использует CHECK OPTION как заменитель ограниче-
ния CHECK в базовой таблице( смотрите Главу 22 для подробностей ). Вы
можете также создавать ваши собственные синонимы, имена которых будут
такими же что и первоначальные имена таблиц. Например, Adrian может
определить Customers, как свой синоним для таблицы Diane.Customers :
CREATE SYNONYM Customers FOR Diane.Customers;
С точки зрения SQL, теперь имеются два разных имени одной таблицы:
Diane.Customers и Adrian.Customers. Однако, каждый из этих пользовате-
лей может ссылаться к этой таблице просто как к Customers, SQL как го-
ворилось выше сам добавит к ней недостающие имена пользователей.
Если вы планируете иметь таблицу Заказчиков используемую большим
числом пользователей, лучше всего что бы они ссылались к ней с помощью
одного и того же имени. Это даст вам возможность, например, использо-
вать это имя в вашем внутреннем общении без ограничений. Чтобы создать
единое имя для всех пользователей, вы создаете общий синоним. Напри-
мер, если все пользователи будут вызывать таблицу Заказчиков с именем
Customers, вы можете ввести
CREATE PUBLIC SYNONYM Customers FOR Customers;
Мы пронимаем, что таблица Заказчиков это ваша собственность, поэтому
никакого префикса имени пользователя в этой команды не указывается. В
основном, общие синонимы создаются владельцами объектов или привилеги-
рованными пользователями, типа DBA. Пользователям кроме того, должны
еще быть предоставлены привилегии в таблице Заказчиков чтобы они могли
иметь к ней доступ. Даже если имя является общим, сама таблица общей
не является. Общие синонимы становятся собственными с помощью команды
PUBLIC, а не с помощью их создателей.
Общие и другие синонимы могут удаляться командой DROP SYNONYM. Сино-
нимы удаляются их владельцами, кроме общих синонимов, которые удаляют-
ся соответствующими привилегированными личностями, обычно DBA. Чтобы
удалить например синоним Clients, когда вместо него уже появился общий
синоним Customers, Adrian может ввести
DROP SYNONYM Clients;
Сама таблица Заказчиков, естественно, становится не эффективной.
Таблицы и другие объекты данных сохраняются в базе данных и находят-
ся там связанными с определенными пользователями которые ими владеют.
В некотором смысле, вы могли бы сказать, что они сохраняются в " имен-
ной области пользователя ", хотя это никак не отражает их физического
расположения, но зато, как и большинство вещей в SQL, находятся в
строгой логической конструкции. Однако, на самом деле, объекты данных
сохраняться, в физическом смысле, и количество памяти которое может
использоваться определенным объектом или пользователем, в данное вре-
мя, имеют свой предел.
В конце концов, никакой компьютер не имеет прямого доступа к беско-
нечному числу аппаратных средств ( диску, ленте, или внутренней памя-
ти) для хранения данных. Кроме того, эффективность SQL расширится если
логическая структура данных будет отображаться неким физическим спосо-
бом при котором эти команды получать преимущество.
В больших SQL системах, база данных будет разделена на области, так
называемые Области Базы Данных или Разделы.
Это области сохраняемой информации, которые размещены так, чтобы ин-
формация внутри них находилась близко друг к другу для выполнения ко-
манд; то-есть программа не должна искать где-то далеко информацию,
сгруппированную в одиночной области базы данных. Хотя ее физические
возможности зависят от аппаратного оборудования, целесообразно чтобы
команда работала в этих областях внутри самой SQL. Системы которые ис-
пользуют области базы данных ( в дальнейшем называемых - DBS (Data Ba-
se Spaces)), позволяют вам с помощью команд SQL обрабатывать эти об-
ласти как объекты.
DBS создаются командами CREATE DBSPACE (СОЗДАТЬ DBS), ACQUIRE DBSPA-
CE(ПОЛУЧИТЬ DBS) или CREATE TABLESPACE (СОЗДАТЬ ТАБЛИЧНУЮ ОБЛАСТЬ), в
зависимости от используемой реализации. Одна DBS может вмещать любое
число пользователей, и отдельный пользователь может иметь доступ к
многим DBS. Привилегия создавать таблицы, хотя и может быть передана
по всей базу данных, часто передается в конкретной DBS. Мы можем соз-
дать DBS с именем Sampletables, следующей командой:
CREATE DBSPACE Sampletables
( pctindex 10,
pctfree 25);
Параметр pctindex определяет какой процент DBS должен быть оставлен,
чтобы сохранять в нем индексы таблиц. Pctfree - это процент DBS кото-
рый оставлен чтобы позволить таблицам расширять размеры их строк ( AL-
TER TABLE может добавлять столбцы или увеличивать размер столбцов, де-
лая каждую строку длиннее. Это - расширение памяти отводимой для это-
го). Имеются также другие параметры которые вы также можете опреде-
лять, и которые меняются от программы к программе. Большинство прог-
рамм автоматически будут обеспечивать значения по умолчанию, поэтому
вы можете создавать DBS не определяя эти параметры. DBS может иметь
или определенное ограничение размера, или ей может быть позволено рас-
ти неограниченно вместе с таблицами. Если DBS создалась, пользователям
предоставляются права создавать в ней объекты. Вы можете например пре-
доставить Diane право создать таблицу Sampletables с помощью следующей
команды:
GRANT RESOURCE ON Sampletables TO Diane;
Это даст вам возможность более конкретно определять место хранения
данных. Первый DBS назначаемый данному пользователю - обычно тот, где
все объекты этого пользователя создаются по умолчанию. Пользователи
имеющие доступ к многочисленым DBS могут определить, где они хотят
разместить определенный объект. При разделении вашей базы данных на
DBSы, вы должны иметь в виду типы операций, которые вы будете часто
выполнять. Таблицы которые, как вам уже известно, будут часто объеди-
няться, или которые имеют одну таблицу ссылающуюся на другую во внеш-
нем ключе, должны находиться вместе в одной DBS.
Например, вы могли бы сообщить при назначении типовых таблиц, что
таблица Порядков будет часто объединяться с одной или обеими из двух
других таблиц,, так как таблица Порядков использует значения из обеих
этих таблиц. При прочих равных условиях, эти три таблицы должны вхо-
дить в ту же самую область DBS, независимо от того, кто их владелец.
Возможное присутствие ограничения внешнего ключа в таблице Порядков,
просто приведет к более строгому совместному использованию области
DBS.
Визуально, среда базы данных, это картина которая постоянно отобра-
жает для существующих пользователей, постоянно вводимые и изменяемые
данные, допуская, что если система правильно разработана, она будет
функционировать без сбоев. Однако реально, благодаря человеческим или
компьютерным сбоям, ошибки время от времени случаются, и поэтому хоро-
шие компьютерные программы стали применять способы отмены действий
вызвавших такие ошибки. Команда SQL, которая воздействует на содержа-
ние или структуру базы данных - например команда модификации DML или
команда DROP TABLE, - не обязательно будет необратимой. Вы можете оп-
ределить после окончания ее действия, останутся ли изменения сделанные
данной командой или группой команд постоянными в базы данных, или они
будут полностью проигнорированы. С этой целью, команды обрабатываются
группами, называемыми - транзакциями. Транзакция начинается всякий
раз, когда вы начинаете сеанс с SQL. Все команды которые вы введете
будут частью этой транзакции, пока вы не завершите их вводом команды
COMMIT WORK или команды ROLLBACK WORK. COMMIT может сделать все изме-
нения постоянными с помощью транзакции, а ROLLBACK может откатить их
братно или отменить. Новая транзакция начинается после каждой команды
COMMIT или ROLLBACK. Этот процесс известен как диалоговая обработка
запросов или транзакция. Синтаксис, чтобы оставить все ваши изменения
постоянными во время регистрации, или во время последнего COMMIT или
ROLLBACK
COMMIT WORK;
Синтаксис отмены изменения -
ROLLBACK WORK;
В большинстве реализаций, вы можете установить параметр, называемый
AUTOCOMMIT. Он будет автоматически запоминать все действия которые бу-
дут выполняться. Действия которые приведут к ошибке, всегда будут ав-
томатически "прокручены" обратно. Если это предусмотрено в вашей сис-
теме, для фиксации всех ваших действий, вы можете использовать эту
возможность с помощью команды типа:
SET AUTOCOMMIT ON;
Вы можете вернуться к обычной диалоговой обработке запросов с по-
мощью такой команды:
SET AUTOCOMMIT OFF;
Имеется возможность установки AUTOCOMMIT которую система выполнит
автоматически при регистрации. Если сеанс пользователя завершается
аварийно - например, произошел сбой системы или выполнена перезагрузка
пользователя, - то текущая транзакция выполнит автоматический откат
изменений. Это - одна из причин, по которой вы можете управлять выпо-
нением вашей диалоговой обработки запросов, разделив ваши команды на
большое количество различных транзакций. Одиночная транзакция не долж-
на содержать много несвязанных команд; фактически, она может состоять
из единственной команды. Транзакции которые включают всю группу несвя-
занных изменений не оставляют вам фактически никакого выбора сохранить
или отклонить целую группу, если вы хотите отменить только одно опре-
деленное изменение. Хорошим правилом которому надо следовать, это де-
лать ваши транзакции состоящими из одной команды или нескольких близко
связанных команд. Например, предположим вы хотите удалить продавца Mo-
tika из базы данных. Прежде, чем вы удалите его из таблицы Продавцов,
вы сначала должны сделать что-нибудь с его порядками и его заказчика-
ми. ( Если используются ограничения внешнего ключа, и ваша система,
следуя ANSI, ограничивает изменение родительского ключа, у вас не бу-
дет выбора делать или не делать этого. Это будет сделано обязательно.)
Одно из логических решений, будет состоять в том, чтобы установить
поле snum в его порядках в NULL, в следствии чего ни один продавец не
получит комиссионные в этих порядках, пока комиссионые не будут пре-
доставлены заказчикам для Peel. Затем вы можете удалить их из таблицы
Продавцов:
UPDATE Orders
SET snum = NULL
WHERE snum = 1004;
UPDATE Cudomers
SET snum = 1001
WHERE snum = 1004;
DELETE FROM Salespeople
WHERE snum = 1004;
Если у вас проблема с удалением Motika ( возможно имеется другой
внешний ключ ссылающийся на него о котором вы не знали и не учитывали
), вы могли бы отменить все изменения которые вы сделали, до тех пор
пока проблема не будет определена и решена.
Более того, это должна быть группа команд, чтобы обрабатывать ее как
одиночную транзакцию. Вы можете предусмотреть это с помощью команды
COMMIT, и завершить ее с помощью команды COMMIT или ROLLBACK.
SQL часто используется в многопользовательских средах - в средах,
где сразу много пользователей могут выполнять действия в базе данных
одновременно. Это создает потенциальную возможность конфликта между
различными выполняемыми действиями. Например, предположим что вы вы-
полняете команду в таблице Продавцов :
UPDATE Salespeople
SET comm = comm * 2
WHERE sname LIKE 'R%';
и в это же время, Diane вводит такой запрос:
SELECT city, AVG (comm)
FROM Salespeople
GROUP BY city;
Может ли усредненное значение(AVG) Diane отазить изменения которые
вы делаете в таблице? Не важно, будет это сделано или нет, а важно что
бы были отражены или все или ни одно из значений комиссионных (comm)
для которых выполнялись изменения. Любой промежуточный результат явля-
ется случайным или непредсказуемым, для порядка в котором значения бы-
ли изменены физически. Вывод запроса, не должен быть случайным и неп-
редсказуемым. Посмотрим на это с другой стороны. Предположим, что вы
находите ошибку и прокручиваете обратно все ваши модификации уже после
того, как Diane получила их результаты в виде вывода. В этом случае
Diane получит ряд усредненых значений основанных на тех изменениях ко-
торые были позже отменены, не зная что ее информации неточна. Обработ-
ка одновременных транзакций называется - параллелизмом или совпадени-
ем, и имеет номера возможных проблем которые могут при этом возникать.
Имеются следующие примеры:
* Модификация может быть сделана без учета другой модификации. Напри-
мер, продавец должен сделать запрос к таблице инвентаризации, чтобы
найти десять фрагментов пунктов торговцев акциями, и упорядочить
шесть из их для заказчика. Прежде, чем это изменение было сделано,
другой продавец делает запрос к таблице и упорядочивает семь из тех
же фразментов для своего заказчика. ПРИМЕЧАНИЕ: Термин "упорядо-
чить", аналогичен общепринятому - "заказать", что в принципе более
соответствует логике запроса, потому что с точки зрения пользовате-
ля, он именно "заказывает" информацию в базе данных, которая упоря-
дочивает эту информацию в соответствии с "заказом".
* Изменения в базе данных могут быть прокручены обратно уже после то-
го, как их действия уже были закончены. Например если Вы отменили
вашу ошибку уже после того, как Diane получила свой вывод.
* Одно действие может воздействовать частично на результат другого
действия. Например когда Diane получает среднее от значений в то
время как вы выполняете модификацию этих значений. Хотя это не
всегда проблематично, в большинстве случаев действие такое же как
если бы агрегаты должны были отразить состояние базы данных в пунк-
те относительной стабильности. Например в ревизионных книгах, долж-
на быть возможность вернуться назад и найти это существующее усред-
ненное значение для Diane в некоторой временной точке, и оставить
его без изменений которые можно было бы сделаны начиная уже с этого
места. Это будет невозможно сделать, если модификация была выполне-
на во время вычисления функции.
* Тупик. Два пользователя могут попытаться выполнить действия которые
конфликтуют друг с другом. Например, если два пользователя попробу-
ют изменить и значение внешнего ключа и значение родительского клю-
ча одновременно.
Имеется много сложнейших сценариев которые нужно было бы последова-
тельно просматривать, если бы одновременные транзакции были неуправля-
емыми. К счастью, SQL обеспечивает вас средством управления паралле-
лизмом для точного указания места получения результата. Что ANSI ука-
зывает для управления параллелизмом -это что все одновременные команды
будут выполняться по принципу - ни одна команда не должна быть выдана,
пока предыдущая не будет завершена (включая команды COMMIT или ROLL-
BACK ).
Более точно, нужно просто не позволить таблице быть доступной более
чем для одной транзакции в данный момент времени. Однако в большинстве
ситуаций, необходимость иметь базу данных доступную сразу многим поль-
зователям, приводит к некоторому компромису в управлении параллелиз-
мом. Некоторые реализации SQL предлагают пользователям выбор, позволяя
им самим находить золотую середину между согласованностью данных и
доступностью к базе данных. Этот выбор доступен пользователю, DBA, или
тому и другому.
На самом деле они осуществляют это управление вне SQL, даже если и
воздействуют на процесс работы самой SQL.
Механизм используемый SQL для управления параллелизмом операций, на-
зывается - блокировкой. Блокировки задерживают определенные операции в
базе данных, пока другие операции или транзакции не завершены. Задер-
жанные операции выстраиваюится в очередь и выполняются только когда
блокировка снята ( некоторые инструменты блокировок дают вам возмож-
ность указывать NOWAIT, которая будет отклонять команду вместо того
чтобы поставить ее в очередь, позволяя вам делать что-нибудь другое).
Блокировки в многопользовательских системах необходимы. Следователь-
но, должен быть некий тип схемы блокировки по умолчанию, который мог
бы применяться ко всем командам в базе данных. Такая схема по умолча-
нию, может быть определена для всей базы данных, или в качестве пара-
метра в команде CREATE DBSPACE или команде ALTER DBSPACE, и таким об-
разом использовать их по разному в различных DBS. Кроме того, системы
обычно обеспечиваются неким типом обнаружителя зависания, который мо-
жет обнаруживать ситуации, где две операции имеют блокировки, блокиру-
ющие друг друга. В этом случае, одна из команд будет прокручена обрат-
но и получит сброс блокировки. Так как терминология и специфика схем
блокировок меняются от программы к программе, мы можем смоделировать
наши рассуждения на примере программы базы данных DB2 фирмы IBM. IBM -
лидер в этой области (как впрочим и во многих других ), и поэтому та-
кой подход наиболее удобен. С другой стороны, некоторые реализации мо-
гут иметь значительные различия в синтаксисе и в функциях, но в основ-
ном их действия должно быть очень похожими.
Имеется два базовых типа блокировок:
- распределяемые блокировки и
- специальльные блокировки.
Распределяемые ( или S-блокировки ) могут быть установлены более чем
однимо пользователя в данный момент времени. Это дает возможность лю-
бому числу пользователей обращаться к данным, но не изменять их.
Специальные блокировки ( или X-блокировки ) не позволяют никому во-
обще, кроме владельца этой блокировки обращаться к данным. Специальные
блокировки используются для команд которые изменяют содержание или
структуру таблицы. Они действуют до конца транзакции.
Общие блокировки используются для запросов. Насколько они продолжи-
тельны зависит фактически от уровня изоляции.
Что такое уровень изоляции блокировки? Это - то, что определяет,
сколько таблиц будет блокировано. В DB2, имеется три уровня изоляции,
два из которых можно применить и к распределеным и к специальным бло-
кировкам, а третий, ограниченный, чтобы использовать эти блокировки
совместно. Они управляются командами поданными извне SQL, так что мы
можем обсуждать не указывая их точного синтаксиса. Точный синтаксис
команд связанных с блокировками различен для различных реализаций.
Следующее обсуждение полезно прежде всего на концептуальном уровне.
Уровень изоляции - повторное чтение - гарантирует, что внутри данной
транзакции, все записи извлеченные с помощью запросов, не могут быть
изменены. Поскольку записи модифицируемые в транзакции являются субъ-
ектами специальной блокировки, пока транзакция не завершена, они не
могут быть изменены в любом случае. С другой стороны для запросов,
повторное чтение означает, что вы можете решить заранее, какие строки
вы хотите заблокировать и выполнить запрос который их выберет. Выпол-
няя запроса, вы гарантированы, что никакие изменения не будут сделаны
в этих строках, до тех пор пока вы не завершите текущую транзакцию.
В то время как повторное чтение защищает пользователя, который по-
местил блокировку, она может в то же время значительно снизить произ-
водительность.
Уровень указатель стабильности - предохраняет каждую запись от изме-
нений, на время когда она читается или от чтения на время ее измене-
ния. Последний случай это специальная блокировка, и применяется пока
изменение не завершено или пока оно не отменено( т.е. на время отката
изменения ). Следовательно, когда вы модифицируете группу записей ис-
пользующих указатель стабильности, эти записи будут заблокированы пока
транзакция не закончится, что аналогично действию производимому уров-
нем повторное чтение. Различиие между этими двумя уровнями в их воз-
действии на запросы. В случае уровня указатель стабильности, строки
таблицы которые в данное время не используются запросом, могут быть
изменены. Третий уровень изоляции DB2 - это уровень только чтение.
Только чтение фиксирует фрагмент данных; хотя на самом деле он блоки-
рует всю таблицу. Следовательно, он не может использоваться с команда-
ми модификации. Любое содержание таблицы как единое целое, в момент
выполнения команды, будет отражено в выводе запроса.
Это не обязательно так как в случае с уровнем указатель стабильнос-
ти. Блокировка только чтение, гарантирует что ваш вывод будет внутрен-
не согласован, если конечно нет необходимости во второй блокировке, не
связывающей большую часть таблицы с уровнем повторное чтение. Блоки-
ровка только чтение удобна тогда, когда вы делаете отчеты, которые
должны быть внутренне согласованны, и позволять доступ к большинству
или ко всем строкам таблицы, не связывая базу данных.
Некоторые реализации выполняют блокировку страницы вместо блокировки
строки. Это может быть либо возможностю для вашего управления либо
нечто заложенным уже в конструкцию системы.
Страница - это блок накопления памяти, обычно равный 1024 байт.
Страница может состоять из одной или более строк таблицы, возможно
сопровождаемых индексами и другой периферийной информацией, а может
состоять даже из нескольких строк другой таблицы. Если вы блокируете
страницы вместо строк, все данные в этих страницах будут блокированы
точно также как и в индивидуальных строках, согласно уровням изоляции
описаным выше.
Основным преимуществом такого подхода является эффективность. Когда
SQL не следит за блокированность и разблокированностью строк индивиду-
ально, он работает быстрее. С другой стороны, язык SQL был разработан
так чтобы максимизировать свои возможности, и произвольно блокирует
строки которые необязательно было блокировать.
Похожая возможность, доступная в некоторых системах - это блокировка
областей DBS. Области базы данных имеют тенденцию быть больше чем
страница, так что этот подход удовлетворяет и достоинству увиличения
производительности и недостатку блокирования страниц.
Вообще то лучше отключать блокировку низкого уровня если вам кажется
что появились значительные проблемы с эффективностью.
Ключевые определения, с которыми вы познакомились в этой главе:
* Синонимы, или как создавать новые имена для объектов данных.
* Области базы даных (DBS), или как распределяется доступная память в
базе данных.
* Транзакция, или как сохранять или восстанавливать изменения в базе
данных.
* Управление Параллелизмом, или как SQL предохраняет от конфликта од-
ной команды с другой.
Синонимы - это объекты, в том смысле, что они имеют имена и (иногда)
владельцев, но естественно они не могут существовать без таблицы, чье
имя они замещают. Они могут быть общими и следовательно доступными
каждому кто имеет доступ к объекту, или они могут принадлежать опреде-
ленному пользователю.
Области DBS или просто DBS - это подразделы базы данных, которые
распределены для пользователей. Связанные таблицы, ( например таблицы,
которые будут часто объединяться,) лучше хранить в общей для них DBS.
СOMMIT и ROLLBACK - это команды, используемые для выполнения измене-
ний в базе данных, в то время когда предыдущая команда COMMIT или ко-
манда ROLLBACK, начинают сеанс и оставляют изменения , или игнорируют
их как группу.
Средство Управление Параллелизмом - определяет в какой степени од-
новременно поданные команды будут мешать друг другу. Оно является
адаптируемым средством, находящим компромис между производительностью
базы данных и изоляцией действующих команд.
1. Создайте область базы данных с именем Myspace которая выделяет 15
процентов своей области для индексов, и 40 процентов на расширение
строк.
2. Вы получили право SELECT в таблице Порядков продавца Diane. Введите
команду так чтобы вы могли ссылаться к этой таблице как к "Orders"
не используя имя "Diane" в качестве префикса.
3. Если произойдет сбой питания, что случится с всеми изменениями сде-
ланными во время текущей транзакции ?
4. Если вы не можете видеть строку из-за ее блокировки, какой это тип
блокировки ?
5. Если вы хотите получить общее, максимальное, и усредненое значения
сумм приобретений для всех порядков, и не хотите при этом запрещать
другим пользоваться таблицей, какой уровень изоляции будет этому
соответствовать ?
|
|
|
|