MySQL имеет специальный тип MyISAM таблицы, который не поддерживает транзакции. Есть ли у Oracle что-то вроде этого? Я хотел бы создать базу данных для записи (для ведения журнала), которая должна быть очень быстрой (будет хранить много данных) и не требует транзакций.Как использовать Oracle без транзакций?
ответ
Сделки являются ключевыми для операций базы данных SQL. Они, безусловно, имеют фундаментальное значение в Oracle. Невозможно постоянно писать таблицы Oracle без выдачи коммита, и вот! есть транзакция.
Oracle позволяет нам указывать таблицы как NOLOGGING, которые не генерируют журнал повтора. Это предназначено только для массовой загрузки (с использованием подсказки INSERT /*+ APPEND */
), с советами по переключению на LOGGING и как можно скорее отвести назад. Поскольку данные, которые не регистрируются, не подлежат восстановлению. И если вы не хотите его восстанавливать, зачем писать это в первую очередь?
Альтернативный подход заключается в том, чтобы перезаписывать записи в памяти, а затем использовать объемные вставки для их записи. Это довольно быстро.
Вот простая таблица регистрации и доказательство концепции упаковки:
create table log_table
(ts timestamp(6)
, short_text varchar(128)
, long_text varchar2(4000)
)
/
create or replace package fast_log is
procedure init;
procedure flush;
procedure write (p_short log_table.short_text%type
, p_long log_table.long_text%type);
end fast_log;
/
Журнал запись хранится в коллекции PL/SQL, который представляет собой структуру в памяти сессионного объемом. Процедура INIT() инициализирует буфер. Процедура FLUSH() записывает содержимое буфера в LOG_TABLE. Процедура WRITE() вставляет запись в буфер, и если в буфере есть необходимое количество записей, вызывается FLUSH().
create or replace package body fast_log is
type log_buffer is table of log_table%rowtype;
session_log log_buffer;
write_limit constant pls_integer := 1000;
write_count pls_integer;
procedure init
is
begin
session_log := log_buffer();
session_log.extend(write_limit);
write_count := 0;
end init;
procedure flush
is
begin
dbms_output.put_line('FLUSH::'||to_char(systimestamp,'HH24:MI:SS.FF6')||'::'||to_char(write_count));
forall i in 1..write_count
insert into log_table
values session_log(i);
init;
end flush;
procedure write (p_short log_table.short_text%type
, p_long log_table.long_text%type)
is
pragma autonomous_transaction;
begin
write_count := write_count+1;
session_log(write_count).ts := systimestamp;
session_log(write_count).short_text := p_short;
session_log(write_count).long_text := p_long;
if write_count = write_limit
then
flush;
end if;
commit;
end write;
begin
init;
end fast_log;
/
Запись в журнал таблицы использует AUTONOMOUS_TRANSACTION прагму, поэтому COMMIT происходит без воздействия на окружающую транзакции вызвавшего флеш.
Вызов DBMS_OUTPUT.PUT_LINE() предназначен для облегчения отслеживания прогресса. Итак, давайте посмотрим, как быстро он идет ....
SQL> begin
2 fast_log.flush;
3 for r in 1..3456 loop
4 fast_log.write('SOME TEXT', 'blah blah blah '||to_char(r));
5 end loop;
6 fast_log.flush;
7 end;
8/
FLUSH::12:32:22.640000::0
FLUSH::12:32:22.671000::1000
FLUSH::12:32:22.718000::1000
FLUSH::12:32:22.749000::1000
FLUSH::12:32:22.781000::456
PL/SQL procedure successfully completed.
SQL>
Хммм, 3456 записи в 0,12 секунды, что это не так уж и плохо. Основная проблема с этим подходом заключается в необходимости сбросить буфер, чтобы округлить свободные записи; это боль, например. в конце сеанса. Если что-то заставляет сервер терпеть крах, незапланированные записи теряются. Другая проблема с занятием в памяти заключается в том, что она потребляет память (durrrr), поэтому мы не можем сделать кеш слишком большим.
Для сравнения я добавил процедуру к пакету, который вставляет одну запись непосредственно в LOG_TABLE каждый раз, когда он вызывается, снова используя автономные транзакции:
procedure write_each (p_short log_table.short_text%type
, p_long log_table.long_text%type)
is
pragma autonomous_transaction;
begin
insert into log_table values (systimestamp, p_short, p_long);
commit;
end write_each;
Вот его тайминги:
SQL> begin
2 fast_log.flush;
3 for r in 1..3456 loop
4 fast_log.write_each('SOME TEXT', 'blah blah blah '||to_char(r));
5 end loop;
6 fast_log.flush;
7 end;
8/
FLUSH::12:32:44.157000::0
FLUSH::12:32:44.610000::0
PL/SQL procedure successfully completed.
SQL>
Часы настенные часы, как известно, ненадежны, но пакетный подход в 2-3 раза быстрее, чем один рекорд. Тем не менее, я мог выполнить более трех тысяч дискретных транзакций менее чем за полсекунды, на (далеко от верхнего уровня) ноутбуке. Итак, возникает вопрос: насколько узким местом является регистрация?
Во избежание недоразумений:
@JulesLt отправил свой ответ, когда я работал на моем PoC. Хотя в наших взглядах есть сходство, я считаю, что различия в предлагаемом обходном пути заслуживают публикации этого.
«? Что время для write_each без автономного, но один совершить в конце Моих таймингов предложить это не имеет значения - что наполнитель вставки является большой победой»
Мои тайминги предлагают нечто иное. Замена COMMIT на запись одним COMMIT в конце примерно половину истекшего времени. Еще медленнее, чем объемный подход, но не почти так же.
Главное здесь бенчмаркинг. Мое доказательство концепции работает примерно в шесть раз быстрее, чем тест Жюля (у меня в таблице один индекс). Существуют всевозможные причины, почему это может быть: спецификация машины, версия базы данных (я использую Oracle 11gR1), структуру таблицы и т. Д. Другими словами, YMMV.
Итак, учение: сначала решите, что правильно делать для вашего приложения, а затем сравните это для своей среды. Учитывайте только другой подход, если в вашем тесте указывается серьезная проблема с производительностью. Предупреждение Кнута о premature optimization применяется.
Проголосовали - если бы я больше беспокоился о производительности, чем о целостности, я бы пошел с магазином и флешем. Какое время для write_each без автономной, но одной фиксации в конце? Мои тайминги предполагают, что это неважно, - что нагрузка на вставку является большой победой. – JulesLt
Что бы я сделал для аналогичного случая, было бы записать журналы в файл (добавление к файлу, вероятно, самый быстрый способ хранения ваших журналов), а затем включить пакетную вставку этих журналов в БД при помощи регулярные отрезки. Если, конечно, вставка непосредственно в БД достаточно быстра ... но вам нужно будет проверить ...
Файл-приложение будет быстрее для одного потока. Если у вас есть несколько потоков, пытающихся добавить в один и тот же файл, вы получите спор. Либо есть один файл в потоке, либо вы будете быстрее в БД, где он привязан к нескольким потокам, передавая данные в один поток/процесс, который записывает в файл. –
Ближайшим может быть создание табличного пространства NOLOGGING и использование опции NOLOGGING для создания таблицы внутри нее - хотя это может применяться только для массовых операций (например, INSERT/* + APPEND */hint).
Это удаляет REDO за счет потери целостности и данных, если БД спускается.
Я не знаю, что на самом деле это будет «быстрее», и вы также должны рассмотреть возможность параллелизма (если у вас много процессов, пытающихся записать в одну и ту же таблицу, вам может быть лучше использовать транзакции, которые пишут ожидающие обновления в повторить журналы, чем пытаться обновить таблицу «real»).
Я еще не исследовал NOLOGGING - я редко попадал в точку, где узким местом приложения была скорость INSERT - когда у меня есть, это была стоимость обновления индексов, а не таблицы, которая была проблемой ,
Я только что проверил быструю проверку и на моей довольно недостаточно развитой БД разработки (с включенным REDO). Используя автономную транзакцию для каждой строки - поэтому каждая строка запускает новую транзакцию и заканчивается фиксацией, я могу записать/зафиксировать более 1000 строк в таблицу индексированных журналов за 1 секунду против примерно 0,755 секунд, делая 1000 вставок без фиксации.
Выполнение вставки из 1000 строк одним ударом с использованием массовой операции - это небольшая часть секунды, поэтому, если вы можете увеличить объем журналов, сделайте это.
Некоторые другие соображения: Может ли внешняя таблица выполнить задание - то есть записать в файл журнала, который затем монтируется в качестве внешней таблицы в Oracle, когда/если вам нужно его прочитать?
Это похоже на решение проблемы при поиске.
Вы сравнили производительность? Oracle достаточно быстро для вас, как есть? Управление транзакциями встроено в то, как работает Oracle и пытается обойти его, похоже, что вы создаете работу для себя.
Вы, кажется, идентифицировали управление транзакциями как проблему, не зная, есть ли проблемы. Что произойдет позже, когда у вас будет несколько авторов на столе? Или читатели блокируют писателей?
Мой опыт в том, что ведение журнала лучше всего делать с плоским файлом. Мое мнение состоит в том, что журналы обычно не особенно важны - ДОЛЖНО что-то пошло не так, и в это время они становятся критическими. Из-за этого я не хочу осуществлять транзакционное управление моим протоколированием. Если мне нужно отменить транзакцию, потому что есть проблема, я действительно не хочу откатывать данные регистрации, потому что это то, что я собираюсь использовать, чтобы помочь определить, в чем проблема. Кроме того, как вы регистрируетесь, что есть проблема с подключением к базе данных, если журнал хранится в базе данных, с которой невозможно подключиться?
Делитесь и наслаждайтесь.
Если я не могу подключиться к базе данных, я бы ожидал, что DBA будет искать в файле alert.log или DB -генерированный файл .TRC для подсказок, а не в отладочном выходе разработчика. – APC
ПРАГМА AUTONOMOUS_TRANSACTION
Это позволит вам войти и совершить свой журнал, не влияя на окружающую сделки (сделок). Регистрация является одним из немногих приемлемых вариантов использования автономных транзакций. Он делает то, что он говорит, позволяет вам написать функцию/процедуру pl/sql, которая может выполнять свою работу, не влияя на транзакцию, в которой она может или не может участвовать. Она «автономна».
au · ton · o · mous 1. (страны или региона) Имея самоуправления. 2. Действуя независимо или имея на это право: «автономный комитет школьного совета».
AUTONOMOUS_TRANSACTION Прагма изменяет способ подпрограммы работает в рамках транзакции. Подпрограмма , отмеченная этой прагмой, может выполнять операции SQL и совершать или откатывать эти операции, не совершая или откатывая данные в основной транзакции .
CREATE OR REPLACE FUNCTION FNC_LOG(p_log_text varchar2(4000))
RETURN NUMBER
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
-- Your brief code goes here (don't abuse the evil feature that is autonomous transactions).
END;
«который должен быть очень быстрым»
Существует компромисс (иногда) между быстрой и возмещена.
В Oracle восстанавливаемость достигается посредством файла журнала повтора. Evey время, которое вы совершили, в журнале «log writer» делает синхронный вызов для записи выдающихся изменений в файл. Синхронно, я имею в виду, что он ожидает, что файловая система подтвердит, что запись была успешной, прежде чем сказать, что фиксация прошла успешно.
Если вы делаете большое количество протоколирования (особенно из-за множества сеансов одновременно), каждая строка в файле журнала выполняется независимо (ag автономная транзакция), то это может быть узким местом.
Если вам не нужен этот уровень восстановления (т. Е. Вы можете позволить себе потерять последние несколько строк ваших данных журнала из ваших журналов в случае серьезного сбоя), посмотрите на вариант фиксации NOWAIT.
Если вы не можете позволить себе потерять что-либо, тогда ваш лучший выбор - ДЕЙСТВИТЕЛЬНО быстрое хранение (это может быть кеш с резервной батареей).
Другой вариант, если вам нужно очень высокую производительность, чтобы рассмотреть TimesTen In-Memory базы данных Oracle в: http://www.oracle.com/technology/products/timesten/index.html
- 1. Как Oracle обнаруживает блокировки транзакций?
- 2. Операция транзакции транзакций Oracle?
- 3. Использование транзакций в Oracle
- 4. Блокировка таблицы транзакций Oracle
- 5. Запросы транзакций Oracle, таймер Asp.net
- 6. Как вы читаете журнал транзакций Oracle
- 7. Использовать websphere MQ как координатор транзакций XA
- 8. Как использовать петли plsql без установки oracle
- 9. Как использовать несколько, вложенных, транзакций?
- 10. CGContextDrawImage без анимации транзакций
- 11. Сохранение ActiveRecord без транзакций
- 12. Вызов транзакций MSDTC и Oracle после отмены?
- 13. Как Wordpress может работать без транзакций?
- 14. Распространение транзакций Oracle между C++ и Java
- 15. Суммарная сумма Oracle на основе транзакций использования
- 16. Oracle: фиксация ожидающих транзакций на медленной таблице
- 17. Переход без транзакций с Hibernate
- 18. Entity Framework 5 без транзакций
- 19. Как повысить PDO SQLite вставки без транзакций?
- 20. Как можно иметь взаимоблокировки без транзакций?
- 21. Зачем использовать сессионные компоненты без состояния для демаркации транзакций
- 22. транзакций Scope в Oracle с ASP.NET
- 23. Получить недействительно без активных транзакций
- 24. Удаление строк без регистрации транзакций?
- 25. Обработка транзакций MySQL без mysqli
- 26. Использование транзакций PDO без ATTR_PERSISTENT?
- 27. Как использовать консультантов транзакций с аннотациями?
- 28. Playframework2: Как использовать множественную базу данных транзакций?
- 29. Как использовать autwire для класса транзакций? Файл
- 30. Как использовать столбец пользователя для транзакций?
Нет, и только для записи __should__ базы данных использовать транзакции. Это управление транзакциями, которое позволяет ему roolback при ошибке, чтобы обеспечить согласованность данных. –
Вопрос, похоже, основан на ошибочном предположении, что с транзакциями в Oracle есть что-то не так. Возможно, они являются потенциальным узким местом в MySQL, я не знаю, но в Oracle я бы предположил, что это не так, и нет никаких оснований их избегать. –
@MarkBaker, @JeffreyKemp - Я работал с некоторыми фреймворками регистрации (* cough * log4plsql * cough *), чья неэффективная реализация оказала огромное влияние на производительность операций. Поэтому я считаю, что регистрация за короткий промежуток времени большого количества действий - настоящая проблема. Хотя я согласен, что 01 задает неправильный вопрос. – APC