Может просто при N-ом Update оптимизатор перестает использовать индекс или делает table access full.
Попробуйте использовать первичный ключ при Update.
Если в качестве параметров передается не Number а число в текстовом формате — индекс тоже может не работать.
Здравствуйте, Qt-Coder, Вы писали:
QC>Каждый поток начинает транзацкцию, выполняет update пачкой
Я давно в базах не возился, но смутно помню, что есть такое "lock escalation" — когда субд решает, что делать row lock для "слишком много" отдельных строк в данной транзации — накладно и пытается сделать table lock.
Оно?..
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
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.
Упс... Имел ввиду 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)
Здравствуйте, Qt-Coder, Вы писали:
QC>Подскажите в чем может быть дело? На каком ресурсе оно блокируется?
Кошмар. Столько наговорили, и кроме wildwind-а никого, кто разбирался бы и мог сказать что-то по делу.
Ответ (не столько для автора, который, надеюсь, прочитал ссылку wildwind-а и решил проблему, сколько для тех, кто будет и дальше плодить кривые решения нагуглит этот топик). Причины могут быть разными. Наиболее вероятная, пожалуй — причина в нехватке слотов транзакций в блоке. Если десяток потоков пытаются изменить каждый свою запись в одном и том же блоке — первым, допустим, четырём это удастся, а остальные станут в очередь ждать коммита счастливчиков, и могут дождаться дедлока, когда счастливчики дойдут до обновление блока, заблокированного ждунами ранее. Можно назвать и другие сценарии. При каждом дедлоке подробная информация о нём фиксируется на сервере и доступна DBA для анализа (что и нужно сделать). При этом правильное решение проблемы — внести в архитектуру или программный код исправление, которое сделает сценарий дедлока невозможным. Какое именно — зависит от ситуации. Довольно часто наилучшее решение — вообще выбросить нахрен это множество конкурирующих потоков и воспользоваться более адекватным средством (например, параллельным update-ом).
QC>Как правило сообщение об ошибке выглядит так QC>
QC>ORA-24381: ошибка(и) в массиве DML
QC>ORA-00060: взаимная блокировка при ожидании ресурса
QC>ORA-00060: взаимная блокировка при ожидании ресурса
QC>ORA-00060: взаимная блокировка при ожидании ресурса
QC>ORA-00060: взаимная блокировка при ожидании ресурса
QC>ORA-00060: взаимная блокировка при ожидании ресурса
QC>
QC>ORA-00060 повторяется по количеству заблокированных строк, видимо.
если в самом деле ORA-00060, то "Условие WHERE для каждого потока уникально. То есть нет такого, чтобы 2 потока обновляли одну и ту же пару F1+F2." вранье. оракл блокирует исключительно на уровне строк, если потоки апдейтят разные строки, то вылететь с deadlock у них шансов не было бы.
Здравствуйте, ·, Вы писали:
·>Я давно в базах не возился, но смутно помню, что есть такое "lock escalation" — когда субд решает, что делать row lock для "слишком много" отдельных строк в данной транзации — накладно и пытается сделать table lock. ·>Оно?..
Здравствуйте, Qt-Coder, Вы писали:
QC>Здравствуйте, Буравчик, Вы писали:
Б>>А кто еще обновляет эту таблицу? Например, кто в нее добавляет записи? Б>>Триггеры есть?
QC>В том то и дело что никто, это полностью моя таблица.
QC>Триггеры есть:
Здравствуйте, wildwind, Вы писали:
W>При пакетном выполнении (array DML в терминах Oracle) все запросы выполняются по одному плану, и такого быть не может.
В рамках одного DML. Но разные запуски (потоки) могут использовать разные планы.
Можно проверить наличие нескольких планов по sql_id
Здравствуйте, Qt-Coder, Вы писали: QC>Подскажите в чем может быть дело? На каком ресурсе оно блокируется?
Вроде oracle в таких случаях dump сохраняет, где есть rowid-ы.
QC>Условие WHERE для каждого потока уникально. То есть нет такого, чтобы 2 потока обновляли одну и ту же пару F1+F2.
значит это не взаимоблокировка
QC>Однако периодически прилетает ORA-00600 взаимная блокировка.
QC>Подскажите в чем может быть дело? На каком ресурсе оно блокируется?
ORA-600 это не взаимоблокировка, а внутренняя ошибка. зачастую какой-то баг в оракле или блок попрочен у таблички. там после ora-600 в квадратных скобках идут параметры, вбивай в гугл ошибку и ищи на какую тему твой ora-600. много лет назад помню на металинке была страничка где можно было вбивать параметры, а металинк расказывал в чем дело и что делать.
QC>>Условие WHERE для каждого потока уникально. То есть нет такого, чтобы 2 потока обновляли одну и ту же пару F1+F2.
Gt_>значит это не взаимоблокировка
QC>>Однако периодически прилетает ORA-00600 взаимная блокировка.
QC>>Подскажите в чем может быть дело? На каком ресурсе оно блокируется?
Gt_>ORA-600 это не взаимоблокировка, а внутренняя ошибка. зачастую какой-то баг в оракле или блок попрочен у таблички. там после ora-600 в квадратных скобках идут параметры, вбивай в гугл ошибку и ищи на какую тему твой ora-600. много лет назад помню на металинке была страничка где можно было вбивать параметры, а металинк расказывал в чем дело и что делать.
Gt_>Gt_
Как правило сообщение об ошибке выглядит так
ORA-24381: ошибка(и) в массиве DML
ORA-00060: взаимная блокировка при ожидании ресурса
ORA-00060: взаимная блокировка при ожидании ресурса
ORA-00060: взаимная блокировка при ожидании ресурса
ORA-00060: взаимная блокировка при ожидании ресурса
ORA-00060: взаимная блокировка при ожидании ресурса
ORA-00060 повторяется по количеству заблокированных строк, видимо.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Qt-Coder, Вы писали:
QC>>Каждый поток начинает транзацкцию, выполняет update пачкой ·>Я давно в базах не возился, но смутно помню, что есть такое "lock escalation" — когда субд решает, что делать row lock для "слишком много" отдельных строк в данной транзации — накладно и пытается сделать table lock. ·>Оно?..
Возможно, но тогда бы блочилась вся пачка при update (это примерно 1000 записей), а не несколько строк из пачки.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Qt-Coder, Вы писали:
QC>>Каждый поток начинает транзацкцию, выполняет update пачкой ·>Я давно в базах не возился, но смутно помню, что есть такое "lock escalation" — когда субд решает, что делать row lock для "слишком много" отдельных строк в данной транзации — накладно и пытается сделать table lock. ·>Оно?..
оракл такой фигней по иделогическим причинам не занимается. в оракле енжин блокировки исключительно на уровне строк юзает. табличку разве что вручную можно залочить.
Просто рестартуй транзакцию, со 2 раза скорей всего сработает (ну или пусть клиент повторяет запрос). Подобная ситуация изредка это норма и плата за иллюзию изоляции транзакций.
Здравствуйте, vsb, Вы писали:
vsb>Просто рестартуй транзакцию, со 2 раза скорей всего сработает (ну или пусть клиент повторяет запрос). Подобная ситуация изредка это норма и плата за иллюзию изоляции транзакций.
Именно так и приходится делать, но хотелось бы понять причину.
Здравствуйте, Буравчик, Вы писали:
Б>А кто еще обновляет эту таблицу? Например, кто в нее добавляет записи? Б>Триггеры есть?
В том то и дело что никто, это полностью моя таблица.
Триггеры есть:
На уникальный номер
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
и т.п.
Блокировка будет производиться по обоим условиям или по первому?
Здравствуйте, IZM, Вы писали:
IZM>Может просто при N-ом Update оптимизатор перестает использовать индекс или делает table access full.
При пакетном выполнении (array DML в терминах Oracle) все запросы выполняются по одному плану, и такого быть не может.
IZM>Попробуйте использовать первичный ключ при Update.
Здравствуйте, 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, надеюсь все тут понимают, что это иная история.
S>Ответ (не столько для автора, который, надеюсь, прочитал ссылку wildwind-а и решил проблему, сколько для тех, кто будет и дальше плодить кривые решения нагуглит этот топик). Причины могут быть разными. Наиболее вероятная, пожалуй — причина в нехватке слотов транзакций в блоке. Если десяток потоков пытаются изменить каждый свою запись в одном и том же блоке — первым, допустим, четырём это удастся, а остальные станут в очередь ждать коммита счастливчиков, и могут дождаться дедлока, когда счастливчики дойдут до обновление блока, заблокированного ждунами ранее. Можно назвать и другие сценарии. При каждом дедлоке подробная информация о нём фиксируется на сервере и доступна DBA для анализа (что и нужно сделать). При этом правильное решение проблемы — внести в архитектуру или программный код исправление, которое сделает сценарий дедлока невозможным. Какое именно — зависит от ситуации. Довольно часто наилучшее решение — вообще выбросить нахрен это множество конкурирующих потоков и воспользоваться более адекватным средством (например, параллельным update-ом).
первопричина ORA-24381, причем тут слоты и вообще ORA-60 ?
Здравствуйте, Softwarer, Вы писали:
S>Ответ (не столько для автора, который, надеюсь, прочитал ссылку wildwind-а и решил проблему, сколько для тех, кто будет и дальше плодить кривые решения нагуглит этот топик). Причины могут быть разными. Наиболее вероятная, пожалуй — причина в нехватке слотов транзакций в блоке. Если десяток потоков пытаются изменить каждый свою запись в одном и том же блоке — первым, допустим, четырём это удастся, а остальные станут в очередь ждать коммита счастливчиков, и могут дождаться дедлока, когда счастливчики дойдут до обновление блока, заблокированного ждунами ранее. Можно назвать и другие сценарии. При каждом дедлоке подробная информация о нём фиксируется на сервере и доступна DBA для анализа (что и нужно сделать). При этом правильное решение проблемы — внести в архитектуру или программный код исправление, которое сделает сценарий дедлока невозможным. Какое именно — зависит от ситуации. Довольно часто наилучшее решение — вообще выбросить нахрен это множество конкурирующих потоков и воспользоваться более адекватным средством (например, параллельным update-ом).
Влияет ли INITRANS на данный сценарий?
Версия сервера 11.2.0.4.0
У меня задан INITRANS=10, потоков 6.
Я читал что Начиная с десятой версии Oracle максимальное количество слотов, которое может быть в таблице транзакций стало фиксированным и составляет на данный момент времени 255.
и решение
Как сделать, чтобы подобные ситуации взаимных блокировок не возникали? Рецепт довольно прост. Во-первых, старайтесь не изменять параметры INITRANS и MAXTRANS в сторону уменьшения без острой необходимости. Во-вторых, если параметр был всё же изменён, увеличивайте его до полного исчезновения взаимных блокировок.