Здравствуйте, Буравчик, Вы писали:
Б>А кто еще обновляет эту таблицу? Например, кто в нее добавляет записи? Б>Триггеры есть?
В том то и дело что никто, это полностью моя таблица.
Триггеры есть:
На уникальный номер
CREATE OR REPLACE TRIGGER TABLE1_BIFER
BEFORE INSERT ON TABLE1
FOR EACH ROW
BEGIN
SELECT NVL(:NEW.F5, SEQ_TABLE1.NEXTVAL)
INTO :NEW.F5
FROM DUAL ;
END TABLE1_BIFER;
/
и на дату обновления
CREATE OR REPLACE TRIGGER TABLE1_BUFER
BEFORE UPDATE
OF F6
ON TABLE1
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
TMPVAR NUMBER;
BEGIN
:NEW.F7 := SYSDATE;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END TABLE1_BUFER;
/
Здравствуйте, Gt_, Вы писали:
Gt_>если в самом деле ORA-00060, то "Условие WHERE для каждого потока уникально. То есть нет такого, чтобы 2 потока обновляли одну и ту же пару F1+F2." вранье. оракл блокирует исключительно на уровне строк, если потоки апдейтят разные строки, то вылететь с deadlock у них шансов не было бы.
Пара уникальная для потока. Но уникальность пары обеспечена уникальностью второй составляющей F2. Первая составляющая может повторяться.
Например,
1 поток: F1 = 1 AND F2 = 1
2 поток: F1 = 1 AND F2 = 2
3 поток: F1 = 1 AND F2 = 3
и т.п.
Блокировка будет производиться по обоим условиям или по первому?
Gt_>>если в самом деле ORA-00060, то "Условие WHERE для каждого потока уникально. То есть нет такого, чтобы 2 потока обновляли одну и ту же пару F1+F2." вранье. оракл блокирует исключительно на уровне строк, если потоки апдейтят разные строки, то вылететь с deadlock у них шансов не было бы.
QC>Пара уникальная для потока. Но уникальность пары обеспечена уникальностью второй составляющей F2. Первая составляющая может повторяться. QC>Например, QC>1 поток: F1 = 1 AND F2 = 1 QC>2 поток: F1 = 1 AND F2 = 2 QC>3 поток: F1 = 1 AND F2 = 3 QC>и т.п.
QC>Блокировка будет производиться по обоим условиям или по первому?
по обоим конечно же. оракл хранит блокировки в дата блоке, т.е. это атрибут данных. в отличие от mssql или mysql нет нужны экономить память на блокировки. блокирует только то, что необходимо.
у тебя же явно фигня в логике, с начало происходит ORA-24381 и потом уже, как следствие ORA-00060. смотри первопричину — ORA-24381.
Здравствуйте, Qt-Coder, Вы писали:
QC>Здравствуйте, Буравчик, Вы писали:
Б>>А кто еще обновляет эту таблицу? Например, кто в нее добавляет записи? Б>>Триггеры есть?
QC>В том то и дело что никто, это полностью моя таблица.
QC>Триггеры есть:
Может просто при N-ом Update оптимизатор перестает использовать индекс или делает table access full.
Попробуйте использовать первичный ключ при Update.
Если в качестве параметров передается не Number а число в текстовом формате — индекс тоже может не работать.
Упс... Имел ввиду table access full а не Fast full scan.
+ проверить наличие неиндексированных внешних ключей на эту таблицу.
как вариант попробовать Update делать через
UPDATE TABLE1 SET F3=:1, F4=:2 WHERE RowID=(select rowid from TABLE1 where F1=:3 AND F2=:4)
Здравствуйте, IZM, Вы писали:
IZM>Может просто при N-ом Update оптимизатор перестает использовать индекс или делает table access full.
При пакетном выполнении (array DML в терминах Oracle) все запросы выполняются по одному плану, и такого быть не может.
IZM>Попробуйте использовать первичный ключ при Update.
Здравствуйте, wildwind, Вы писали:
W>При пакетном выполнении (array DML в терминах Oracle) все запросы выполняются по одному плану, и такого быть не может.
В рамках одного DML. Но разные запуски (потоки) могут использовать разные планы.
Можно проверить наличие нескольких планов по sql_id
Здравствуйте, wildwind, Вы писали:
W>На этой таблице нет первичного ключа.
Извиняюсь, не сказал сразу, ключ есть, там делается ALTER TABLE .. PRIMARY KEY
ALTER TABLE TABLE1 ADD (
CONSTRAINT TABLE1_PK
PRIMARY KEY
(F3)
USING INDEX TABLE1_PK
ENABLE VALIDATE,
CONSTRAINT TABLE1_F1F2_UNIQUE
UNIQUE (F1, F2)
USING INDEX IND_F1_F2_UNIQUE
ENABLE NOVALIDATE);
Здравствуйте, Qt-Coder, Вы писали:
QC>Здравствуйте, wildwind, Вы писали:
W>>На этой таблице нет первичного ключа. QC>Извиняюсь, не сказал сразу, ключ есть, там делается ALTER TABLE .. PRIMARY KEY
QC>
QC>ALTER TABLE TABLE1 ADD (
QC> CONSTRAINT TABLE1_PK
QC> PRIMARY KEY
QC> (F3)
QC> USING INDEX TABLE1_PK
QC> ENABLE VALIDATE,
QC> CONSTRAINT TABLE1_F1F2_UNIQUE
QC> UNIQUE (F1, F2)
QC> USING INDEX TABLE1_F1F2_UNIQUE
QC> ENABLE NOVALIDATE);
QC>
QC>Может ли здесь быть причина блокировок?
нет. update не умеет лочить индексы, update ставит лишь row level lock. пофигу как эта строка вычитывается, через индекс или как по другому. у тебя разные процессы апдейтят одни и те же строки.
Здравствуйте, Gt_, Вы писали:
Gt_>нет. update не умеет лочить индексы, update ставит лишь row level lock. пофигу как эта строка вычитывается, через индекс или как по другому. у тебя разные процессы апдейтят одни и те же строки.
Это было бы слишком просто. Это я конечно проверил в первую очередь. Но это невозможно чисто математически.
Каждый поток берет mod(F2, X) и никак остаток от деления не может быть одинаковым в потоках.
Здравствуйте, Qt-Coder, Вы писали:
QC>Здравствуйте, Gt_, Вы писали:
Gt_>>нет. update не умеет лочить индексы, update ставит лишь row level lock. пофигу как эта строка вычитывается, через индекс или как по другому. у тебя разные процессы апдейтят одни и те же строки.
QC>Это было бы слишком просто. Это я конечно проверил в первую очередь. Но это невозможно чисто математически. QC>Каждый поток берет mod(F2, X) и никак остаток от деления не может быть одинаковым в потоках.
ты выдумаваешь, полагаясь на фантазии. с начала у тебя происходит ORA-24381, потом апдейты совершенно не по тем предикатам, по каким ты думаешь.
Здравствуйте, wildwind, Вы писали:
W>Ничего себе уточнение. Значит параллельно апдейтится первичный ключ, а доступ идет по другому ключу?
Нет, я напутал с колонками. F3 (первичный ключ) не апдейтится, то что я написал как пример апдейта, относится к другому полю.
Во-первых, там описывается конкретный сценарий, отличный от сценария ТС.
Во-вторых, там ничего напрямую не говорится о блокировках на индексы.
С точки зрения блокировок, таблицы и индексы почти никак не различаются, механизм работает одинаково.
Блокировки на индексах можно легко увидеть в системных вьюхах, если смоделировать ожидание на блокировке.
W>С точки зрения блокировок, таблицы и индексы почти никак не различаются, механизм работает одинаково. W>Блокировки на индексах можно легко увидеть в системных вьюхах, если смоделировать ожидание на блокировке.
ну удиви меня, расскажи что за тип блокировки ставит DML на индекс ?
лок на индекс может поставить DDL, надеюсь все тут понимают, что это иная история.
Здравствуйте, Qt-Coder, Вы писали:
QC>Подскажите в чем может быть дело? На каком ресурсе оно блокируется?
Кошмар. Столько наговорили, и кроме wildwind-а никого, кто разбирался бы и мог сказать что-то по делу.
Ответ (не столько для автора, который, надеюсь, прочитал ссылку wildwind-а и решил проблему, сколько для тех, кто будет и дальше плодить кривые решения нагуглит этот топик). Причины могут быть разными. Наиболее вероятная, пожалуй — причина в нехватке слотов транзакций в блоке. Если десяток потоков пытаются изменить каждый свою запись в одном и том же блоке — первым, допустим, четырём это удастся, а остальные станут в очередь ждать коммита счастливчиков, и могут дождаться дедлока, когда счастливчики дойдут до обновление блока, заблокированного ждунами ранее. Можно назвать и другие сценарии. При каждом дедлоке подробная информация о нём фиксируется на сервере и доступна DBA для анализа (что и нужно сделать). При этом правильное решение проблемы — внести в архитектуру или программный код исправление, которое сделает сценарий дедлока невозможным. Какое именно — зависит от ситуации. Довольно часто наилучшее решение — вообще выбросить нахрен это множество конкурирующих потоков и воспользоваться более адекватным средством (например, параллельным update-ом).