Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Блокировка при чтении  [new]
DeBaggio
Member

Откуда:
Сообщений: 17
Доброго времени суток!
Суть проблемы: работает массовая загрузка в несколько потоков из нескольких источников. при этом выполняется примерно следующее:
1) Проверяется существует ли строка (по некоторым полям)
2)
  • Если строка существует, то она апдейтится
  • Если строка не существует, то она добавляется

    Теперь проблема:
    Если 2 потока собираются вставить 1 и ту же запись (т.е. одновременно прочитали, что строка не существует), как реализовать, чтобы строки не дублировались?

    Что пробовалось:
    rowlock при проверке существует ли строка не помог, т.к. если запись не существует, то и ничего не лочится
    sp_getapplock убивает всё приимущество грузить в несколько потоков

    Заранее благодарен!
  • 5 мар 12, 17:23    [12198292]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    Knyazev Alexey
    Member

    Откуда: Екб -> Мск
    Сообщений: 10233
    Блог
    явная блокировка вам поможет, ну и merge...зачем изобретать велик
    5 мар 12, 17:24    [12198306]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    Glory
    Member

    Откуда:
    Сообщений: 104751
    DeBaggio
    Теперь проблема:
    Если 2 потока собираются вставить 1 и ту же запись (т.е. одновременно прочитали, что строка не существует), как реализовать, чтобы строки не дублировались?

    Создать unique constraint для таблицы ?
    5 мар 12, 17:27    [12198324]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    DeBaggio
    Member

    Откуда:
    Сообщений: 17
    Knyazev Alexey
    явная блокировка вам поможет, ну и merge...зачем изобретать велик

    явная блокировка чего?
    5 мар 12, 17:34    [12198387]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    serializable
    Guest
    DeBaggio
    Knyazev Alexey
    явная блокировка вам поможет, ну и merge...зачем изобретать велик

    явная блокировка чего?

    range, см. serializable
    5 мар 12, 17:40    [12198424]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    DeBaggio
    Member

    Откуда:
    Сообщений: 17
    serializable
    range, см. serializable

    К сожалению не помогает, если при селекте написать что-нибудь типа (updlock, serializable) то периодически наблюдаю deadlocks
    5 мар 12, 17:48    [12198506]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    serializable
    Guest
    DeBaggio
    serializable
    range, см. serializable

    К сожалению не помогает, если при селекте написать что-нибудь типа (updlock, serializable) то периодически наблюдаю deadlocks

    1 - не помогает != появляются deadlocks
    2 - нахера updlock? либо xlock, либо ни чего
    3 - есть ли уникальный индекс по полю в котором не должно быть дубликатов?
    5 мар 12, 17:55    [12198570]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    DeBaggio
    Member

    Откуда:
    Сообщений: 17
    serializable
    DeBaggio
    пропущено...

    К сожалению не помогает, если при селекте написать что-нибудь типа (updlock, serializable) то периодически наблюдаю deadlocks

    1 - не помогает != появляются deadlocks
    2 - нахера updlock? либо xlock, либо ни чего
    3 - есть ли уникальный индекс по полю в котором не должно быть дубликатов?


    1 - вы поняли, что я имел ввиду
    2 - xlock чего? если строки не существует, то ничего не блокируется и оба процесса считают, что её нет и начинают вставку.
    3 - нет. выше уже предлагали это сделать. В принципе возможный вариант, только придётся как-то этот эксепшн в приложении обработать
    5 мар 12, 18:04    [12198652]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    Crimean
    Member

    Откуда:
    Сообщений: 13147
    подготовка

    -- drop table a
    create table a ( id int primary key )

    insert into a select 1
    insert into a select 10
    insert into a select 20

    кверя 1

    begin tran

    if not exists( select 1 from a where id = 5 ) print 'ok'

    rollback

    кверя 2 - аналогично квере 1

    выполнять квери построчно по очереди. обе дают ок - ваша проблема
    теперь меняем кверю вот так:

    if not exists( select 1 from a with (xlock, holdlock) where id = 5 ) print 'ok'

    теперь первый вызов сразу дает "ок", а второй - ждет пока не закончится первый
    проверяем через sp_lock

    spid   dbid   ObjId       IndId  Type Resource                         Mode     Status 
    ------ ------ ----------- ------ ---- -------------------------------- -------- ------ 
        52      5           0      0 DB                                    S        GRANT
        52      5   599409696      1 PAG  1:9585                           IX       GRANT
        52      5   599409696      1 KEY  (d08358b1108f)                   RangeX-X GRANT
        52      5   599409696      0 TAB                                   IX       GRANT
    


    и видим причину такого поведения
    5 мар 12, 18:11    [12198691]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    DeBaggio
    Member

    Откуда:
    Сообщений: 17
    Glory, Knyazev Alexey, спасибо! Попробую что-нибудь из предложенного Вами. Возможно ещё timestamp. Выберу, что быстрее или удобнее :)
    5 мар 12, 18:11    [12198693]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    DeBaggio
    Member

    Откуда:
    Сообщений: 17
    Crimean
    подготовка

    -- drop table a
    create table a ( id int primary key )

    insert into a select 1
    insert into a select 10
    insert into a select 20

    кверя 1

    begin tran

    if not exists( select 1 from a where id = 5 ) print 'ok'

    rollback

    кверя 2 - аналогично квере 1

    выполнять квери построчно по очереди. обе дают ок - ваша проблема
    теперь меняем кверю вот так:

    if not exists( select 1 from a with (xlock, holdlock) where id = 5 ) print 'ok'

    теперь первый вызов сразу дает "ок", а второй - ждет пока не закончится первый
    проверяем через sp_lock

    spid   dbid   ObjId       IndId  Type Resource                         Mode     Status 
    ------ ------ ----------- ------ ---- -------------------------------- -------- ------ 
        52      5           0      0 DB                                    S        GRANT
        52      5   599409696      1 PAG  1:9585                           IX       GRANT
        52      5   599409696      1 KEY  (d08358b1108f)                   RangeX-X GRANT
        52      5   599409696      0 TAB                                   IX       GRANT
    


    и видим причину такого поведения


    А не блокируется ли при этом целиком таблица?
    5 мар 12, 18:31    [12198838]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    serializable
    Guest
    DeBaggio
    serializable
    пропущено...

    1 - не помогает != появляются deadlocks
    2 - нахера updlock? либо xlock, либо ни чего
    3 - есть ли уникальный индекс по полю в котором не должно быть дубликатов?


    1 - вы поняли, что я имел ввиду
    2 - xlock чего? если строки не существует, то ничего не блокируется и оба процесса считают, что её нет и начинают вставку.
    3 - нет. выше уже предлагали это сделать. В принципе возможный вариант, только придётся как-то этот эксепшн в приложении обработать

    1 - главное чтоб вы поняли
    2 - я же сказал - range. есть такой тип блокировки - блокировка диапазона ключей (вам выше уже пример показали)
    3 - для блокировка диапазона ключей требуется индекс, не обязательно уникальный, блокируется не конкретная запись а значение ключа, и в случае с не уникальным индексом это может быть больше чем одна запись.
    5 мар 12, 18:52    [12198986]     Ответить | Цитировать Сообщить модератору
     Re: Блокировка при чтении  [new]
    serializable
    Guest
    DeBaggio
    А не блокируется ли при этом целиком таблица?

    не больше чем при любом изменение данных в ней.
    5 мар 12, 18:53    [12198992]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить