Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save anonymous/b7cf5bd0e306f48fef4cd68e782d5da8 to your computer and use it in GitHub Desktop.
Save anonymous/b7cf5bd0e306f48fef4cd68e782d5da8 to your computer and use it in GitHub Desktop.
Таблица 15 сервер транзакций

Таблица 15 сервер транзакций


Таблица 15 сервер транзакций



Транзакции в MS SQL Server
SQL Server: Управление транзакциями
Таблица для транзакций


























Many types of operations are recorded in the transaction log. Здравствуйте, Sinclair, Вы писали: Меняются сразу несколько страниц, все нужно записать. Вот здесь есть пример. А разве он не сделает page split крайней страницы в момент её заполнения? И нет и да. Протестировал как раз перед тем, как написать пост. Тестировал на м, но уверен в аналогичном поведении как минимум с го. Да — логически операция одна — page split, но она оптимизированна для вставки в конец. Нет — при выделении страницы в конце индекса он выделяет новую страницу и пишет туда только новую запись. При разделении в середине он делит страницу пополам и добавляет запись на одну из поделенных страниц. Но на самом деле в журнал пишется информация не просто о выделении новой страницы, а именно о том, что произошел page split. И там есть несколько логических операций, одна из которых применяется только для разделения страниц в середине индекса. Это удаление записей на старой странице. Каждая запись в логе о модификации строки содержит в себе физический адрес записи page id, slot id. Поэтому без логгирования операций со страницами никак не обойтись. Собственно, журналирование изменения адреса перенесенных на новую страницу данных и есть основной фактор в данном случае. Чем больше записей было на разделенной странице, тем больше места потребуется в журнале. Вот об этом я и говорил. Спасибо, моя уверенность в SQL Server team восстановлена. Это же бывает достаточно редко. Точнее — мы имеем o log n операций в худшем случае. А поскольку при вставке в середину таблицы страница делится пополам, то это повышает фрагментацию. Насколько я понимаю, SQL Server использует read-ahead поэтому порядок страниц может влиять на скорость их загрузки, кроме того если индекс подошёл для index seek, там будет именно последовательное чтение страниц и любая фрагментация его замедлит. Ведь в b-tree все leaf-страницы одинаковые — что "в середине", что "с краю". На этот вопрос уже ответили. Здравствуйте, Somescout, Вы писали: В случае index seek как раз не будет последовательного чтения страниц. Там будет случайное чтение от root page до leaf page со всеми необходимыми остановками. На эту операцию фрагментация фактически не влияет. Index seek выполняется когда предикат индекса совпадает с предикатом запроса, то есть index a и where a between x and y в этом случае находится первая страница диапазона и читается до последней. Кстати, index scan будет работать точно также, правда при этом обрабатываются и не соответствующие условию строки входящие в диапазон. И во всех случаях влияние фрагментации будет зависеть от длинны диапазона и размера одной строки. По сути это уже этакий range scan. Я думал, ты говоришь о поиске по равенству. Может показаться, что ситуация складывается идеальная, использование значений с монотонным возрастанием позволяет снизить фрагментированность индекса за счет отсутствия разбиения страниц, что в конечном итоге снижает стоимость обслуживания, а так же положительно сказывается на производительности всей системы. Это справедливо, но не во всех случаях. Дело в том, что СУБД гарантирует монотонную генерацию значений, но не дает никаких гарантий относительно последовательности вставки этих данных в таблицу. Количество таких ситуаций будет определяться нагрузкой на систему. Для анализа решил провести эксперимент. В цикле из итераций в потоках соединениях вставляется запись в пять разных таблиц: Таблица с identity dbo. Таблица с newid dbo. Таблица с newsequentialid dbo. Таблица c sequence dbo. Простая таблица c identity dbo. TSimple , в которую последовательно вставляется записей в одном потоке, для сравнения фрагментированности индексов. Поле, на котором генерируются значения, является первичным ключом с кластерным индексом. Структура create table dbo. TIdentity id int identity 1,1 not null primary key , dt datetime2 default sysdatetime , st varchar go create table dbo. TNewid id uniqueidentifier not null default newid primary key , dt datetime2 default sysdatetime , st varchar go create table dbo. TNewsequentialid id uniqueidentifier not null default newsequentialid primary key , dt datetime2 default sysdatetime , st varchar go create sequence dbo. CountBy as int start with 1 increment by 1; go create table dbo. TSequence id int not null default next value for dbo. CountBy primary key , dt datetime2 default sysdatetime , st varchar go create table dbo. TSimple id int identity 1,1 not null primary key , dt datetime2 default sysdatetime , st varchar go Второй момент, на котором хотелось бы остановиться в эксперименте — это суммарное время выполнения операции. Выше Sinclair высказал интересную мысль, использование рандомных значений, например newid для типа данных uniquidentifier позволяет повысить конкуренцию за счет того, что в таком индексе блокируются разные ресурсы, в отличие от вставки последовательных значений, где процессы борются за доступ к последней странице. Проверял на SQL Server Standard Edition с помощью приложения SqlQueryStress. Суммарное время выполнения операции dbo. При этом фрагменитрованность индекса для такого случая самая высокая. Возможно, преимущества по конкуренции и присутствуют, но много времени занимает разбиение страниц и протоколирование в лог. Основывается он на соотношении seek и lookup операций между кластерным и некластерным индексом. В целом можно рассмотреть в качестве подспорья. Так как если вставка строк в таблицу и обновление индекса проводятся очень часто, фрагментация и деление страниц съест всю пользу от наиболее оптимального с точки зрения запросов ключа а дефрагментировать многогигабайтный индекс долго. По хорошему надо как-то отследить какие именно данные вставлялись в таблицу и из требуемых индексов выбрать тот, который будет монотонно изменяться. Альтернатива только задать fillfactor, но на кластерном индексе это автоматом снижает эффективность Index Lookups. Либо можно попробовать partition table, но я пока этого не пробовал делать, надо изучать. На самом деле теория не учитывает не только монотонность, но и ширину, уникальность и изменчивость данных. Подход ориентируется на статистику использования индексов, которая возникает при эксплуатации БД. Это не призыв к действию, а информация для боле детального анализа и изучения, на что стоит обратить внимание. Здравствуйте, Olaf, Вы писали: Я уже начинаю думать, что оптимальным вариантом будет партиционирование таблицы на актуальную и архивную части. Для строк, у которых размер значительно меньше размера страницы, такого беспредела с фрагментацией быть не должно. Ну, по крайней мере, в теории К сожалению, ms sql под рукой нет, будет классно если проверишь у себя. Например, с st varchar Здравствуйте, Sinix, Вы писали: Например, с st varchar Результат для varchar Фрагментация для TNewsequentialid и TIdentity уменьшилась в два раза. А вот для последовательности показатель улучшился, но не намного. Подозреваю нужно указать конкретное значение для кэша, например , чтобы снизить количество обращений к системным таблицам. Вроде как напрашивается ответ — уменьшилась длина записи, сократилось количество страниц необходимое для хранения данных а фактически уменьшилось время для вставки записи , что соответственно снизило количество ситуаций, в которых записи вставляются не по порядку. В общем чую но обосновать не могу — матчасть надо освежать , что вставки по-прежнему утыкаются в конец страницы и приводят к куче лишних page split. Переместить Удалить Выделить ветку. TSimple id int identity 1,1 not null primary key , dt datetime2 default sysdatetime , st varchar go.


Как настроить работу онлайн-касс через драйвер Штрих-М?


Если это так, то статься на MSDN https: У меня откатились все мои N инсертов, хотя я сделал COMMIT TRAN, а лишь потом ROLLBACK tran. По идее транзакция должна была завершиться и на откат ничего не должно было пойти В этом случае, при возникновении ошибки на 2м шаге, исполнение не продолжится, а по-возможности перейдёт в блок CATCH , где можно принудительно вызвать ROLLBACK. В этом случае при возникновении ошибок определённого рода, не любых на 2-м UPDATE выполнение команд будет прервано и произойдёт автоматический откат изменений. ROLLBACK может происходить автоматически, при закрытии соединения, если для данного соединения есть незавершенные транзакции. SqlServer сделает откат такой транзакции, при разрыве соединения. Запросив затем данные из таблицы в новом соединении, мы увидим, что она пустая. Несмотря на ошибку дело дойдёт и до commit соответственно отката не будет и до select после него. В частности она не откатывает транзакцию при генерации пользовательских исключений в том числе сгенерированных в DML-триггерах. Поэтому полезнее может быть целенаправленный вызов rollback. Часто применяется в catch блоке, при оборачивании транзакции в try В этом случае SqlServer позволяет программисту самому решить будет ли откат полезен при той или иной ошибке, или нет. Далее пара примеров, когда откат может быть полезен в catch и когда вреден. Допустим теперь, что произошёл вызов процедуры и началась вставка данных. Если логикой приложения продиктовано, что либо сущность вставляется целиком, либо вообще не вставляется - тогда в catch делается rollback как в данном примере. Но возможны ситуации, когда ошибки, возникшие в результате выполнения каких-то отдельных запросов, не являются серьёзным основанием для отката всех совершенных действий. Например, если у нас не две связанных таблицы, а импорт данных в несколько независимых таблиц, и мы не хотим откатывать ту часть данных, что была уже успешно внесена. Тогда в catch можно попытаться сделать commit не любая ошибка сделает это возможным, о том как это сделать корректно - в следующем примере. Делать откат, или нет - зависит от семантики данных и логики приложения. Транзакции для изменения данных достаточно привычны, но иногда в транзакции нуждается и чтение. Для таких транзакций необдуманно вызванный rollback может оказать медвежью услугу. Пусть есть процедура, которая в repeatable read или snapshot транзакции читает данные:. В процедуре происходит следующее. В ней заполняется фильтрующая таблица Orders чтобы потом дать пользователю только то, что ему разрешено видеть. Затем некоторая проверка на основании Orders и других данных. Если проверка проходит, то данные отдаются, если нет - генерируется ошибка. Предположим, что эта проверка не была успешной. Должен ли в catch произойти rollback? Ведь мы только читаем данные и ничего не изменяем кроме временной таблицы Orders. Более того, таблица Orders создана до входа в транзакцию, а заполнялась в транзакции. Вследствие чего, если бы мы стали делать rollback начал бы происходить откат вставленных в неё данных, а это дольше, чем commit и простое уничтожение Orders при выходе из процедуры. Публикуя ответ вы принимаете условия политики конфиденциальности и соглашение. Stack Overflow на русском Вопросы Метки Участники. Чтобы изменить список, зарегистрируйтесь или войдите. Тур Начните с этой страницы, чтобы быстро ознакомиться с сайтом Справка Подробные ответы на любые возможные вопросы Мета Обсудить принципы работы и политику сайта О нас Узнать больше о компании Stack Overflow Бизнес Узнать больше о поиске разработчиков или рекламе на сайте. Stack Overflow на русском — сайт вопросов и ответов для программистов. Это не займёт больше минуты: Вот как это работает: Любой может задать вопрос Любой может ответить Лучшие ответы получают голоса и поднимаются наверх. Как правильно работать с транзакциями в MS SQL Server? Запустил 3 запрос на обновление 3-ех разных таблиц и обернул в Begin Tran и Commit Tran. На втором запросе получил ошибку, но данные в первой таблице не откатились. Разве не должен был быть откат? Еще не понял вот такого поведения: Сначала делаю N раз вот этот запрос: BEGIN TRAN INSERT INTO ttt VALUES GETDATE --Транзакцию специально не закомитил Затем отдельно делаю: COMMIT TRAN Затем ROLLBACK tran У меня откатились все мои N инсертов, хотя я сделал COMMIT TRAN, а лишь потом ROLLBACK tran. Если три обновления в одной общей транзакции - должен, каждое в своей транзакции - нет. Откат при rollback происходит, либо если не было commit - при завершении соединения. Мне казалось, что он автоматически вызываться должен Да, если нужен откат, то нужно явно вызвать rollback. Однако, если если не было commit и rollback не был вызван, то откат произойдёт автоматически при закрытии соединения. Мне всегда казалось, что BEGIN TRAN серия запросов COMMIN TRAN гарантируют, что если будет косяк, то будет откат В случае конструкции BEGIN TRAN UPDATE 1 UPDATE 2 --error UPDATE 3 COMMIT TRAN при выполнении команд не в блоке TRY Если нужно при ошибке делать откат, то тут могут быть два варианта. Первый - это исполнение команд в блоке TRY BEGIN TRY BEGIN TRAN UPDATE 1 UPDATE 2 --error UPDATE 3 COMMIT TRAN END TRY BEGIN CATCH ROLLBACK TRAN END CATCH В этом случае, при возникновении ошибки на 2м шаге, исполнение не продолжится, а по-возможности перейдёт в блок CATCH , где можно принудительно вызвать ROLLBACK. В некоторых случаях используется и то и другое. Ниже чуть подробнее об автоматическом и управляемом откате. Автоматический ROLLBACK ROLLBACK может происходить автоматически, при закрытии соединения, если для данного соединения есть незавершенные транзакции. Изменение данных в транзакции. Пусть есть процедура, которая в транзакции делает вставку данных в две связанных таблицы: Users t using select uid, info. UID when matched then update set t. LastName when not matched then insert UID, FirstName, LastName values s. UserContacts t using select id, ct. UserContactTypes ct on ct. ContactTypeID when not matched by source then delete when matched then update set t. ContactInfo when not matched then insert UserID, ContactTypeID, ContactInfo values s. Чтение данных в транзакции. Пусть есть процедура, которая в repeatable read или snapshot транзакции читает данные: OrderPermissions userID op join dbo. Orders ord on ord. Orders ord join Orders o on o. Invoices inv join Orders o on o. Shipment sh join Orders o on o. Просто, не вижу этого в примерах. Зарегистрируйтесь или войдите StackExchange. Отправить без регистрации Имя. Stack Overflow на русском лучше работает с включенным JavaScript. MathOverflow Mathematics Cross Validated stats Theoretical Computer Science Physics Chemistry Biology Computer Science Philosophy more Meta Stack Exchange Stack Apps Area 51 Stack Overflow Talent.


Гост технологическая инструкция 3.1105
Сколько идет поезддо тюмени
План работы с группой риска классного руководителя
Vpn l2tp android
Александр арт нейл
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment