|
|
|
ADO Recordset блокирует всю таблицу, нужно блокировать только редактируемую запись.
|
|||
|---|---|---|---|
|
#18+
Я, конечно, поздно вступаю в дискуссию... Вначале её я думал, что вопрос простой, и поэтому помалкивал, в середине (когда к обсуждению вопроса подтянулись силы главного калибра) - казалось, что по существу вопроса всё уже сказано (или вот-вот будет сказано), и встревать в обсуждение со своими банальностями как-то не хотелось... А сейчас (перечитав дискуссию сверху донизу) я вижу, что никто, к моему вящему удивлению, не высказался достаточно полно по существу поставленного изначально вопроса, ответив определённо и убедительно - возможно ли то, что хотел автор, а если нет, то почему. Пытаюсь восполнить этот пробел. Насколько я понял, суть вопроса в том, что автор хочет, чтобы при использовании ADO (Microsoft Jet 4.0 OLE DB Provider) для доступа к MDB и применении client-side курсора при добавлении записи блокировалась только одна запись. Реально в этом случае блокируется страница. Подчеркну, что вопрос не в том, должна ли в конкретном примере здесь возникать блокировка - безусловно должна, учитывая конкретные обстоятельства, а лишь в том, какая у неё должна быть "гранулярность" - запись или страница. На основании некоторого опыта, довольно глубокого изучения материалов MSDN и результатов собственных экспериментов я пришёл к выводу, что это, похоже, невозможно из-за того, что конкретный ADO провайдер - Microsoft Jet 4.0 OLE DB Provider - такого не предусматривает (возможно, всего лишь по недосмотру). Вот почему я пришёл к такому выводу: Свойства объекта Connection - .Mode и .IsolationLevel, а также параметры метода открытия набора записей Open - CursorType и LockType в Microsoft Jet 4.0 влияют на лишь на то, должна или не должна быть блокировка и какая у неё должна быть продолжительность, но никак не затрагивают её детальность ("гранулярность"). Эта самая "гранулярность" (record locking/page locking) в Microsoft Jet 4.0 управляется следующим образом: 1. Меню в MS Access (у меня сейчас русский Access 2000): Сервис/Параметры, вкладка "Другие", параметр "Блокировка записей при открытии БД" 2. Специфическое свойство провайдера Microsoft Jet 4.0 OLE DB Provider для объекта ADODB.Connection: cnn.Properties("Jet OLEDB:Database Locking Mode") Page-level Locking - 0 Row-level Locking - 1 3. Специфическое свойство провайдера Microsoft Jet 4.0 OLE DB Provider для объекта ADODB.Recordset: rst.Properties("Jet OLEDB:Locking Granularity") Page-level locking - 1 Row-level locking - 2 Значение этого свойства принимается во внимание, лишь когда параметр "Jet OLEDB:Database Locking Mode" установлен как Row-level Locking. Следует отметить, что свойства 1) и 2) - это по сути, одно и то же свойство, и из них принимается во внимание то, что что будет включено раньше для конкретного сеанса (а последующие настройки будут игнорироваться). То есть, если мы откроем базу через программу MS Access, то в силу вступит настройка из меню, и она будет наследоваться всеми последующими соединениями (в том числе и из других программ). И наоборот. По умолчанию ADO Connection к БД Access открывается как .CursorLocation = adUseServer, и при этом свойство набора записей "Jet OLEDB:Locking Granularity" можно прочитать и настроить, как хочется. В этом случае в обсуждаемом примере (если все вышеназванные свойства настроены как надо) блокируется только одна добавляемая запись независимо от иных настроек - я проверял. Засада здесь вот в чём. Как только мы выполняем строку .CursorLocation = adUseClient, так из свойств объекта Recordset волшебным образом пропадает само свойство "Jet OLEDB:Locking Granularity"! То есть сlient-side курсоры для Microsoft Jet 4.0 OLE DB Provider вообще не поддерживают управление этой самой "гранулярностью"! Естественно, что с этого момента при добавлении записи блокироваться начинают страницами. Это меня окончательно убедило в том, что "this behaviour is by design", как пишут в MS Knowledge Base. Кстати, вот ещё что хотелось бы отметить. В этой теме неоднократно встречается код типа: Код: plaintext 1. Так вот, различные провайдеры ADO поддерживают не все комбинации параметров, и в определённых случаях создают в таких случаях набор записей не с "заказанными" параметрами, а "ближайшими" по их разумению к ним. В частности, в этом конкретном случае вместо набора записей типа adOpenKeyset будет создан набор записей adOpenStatic. Вообще, в случае .CursorLocation = adUseClient Microsoft Jet 4.0 OLE DB Provider ВСЕГДА создаёт набор записей с adOpenStatic, какое бы значение CursorType вы не указали. Кроме того, в этом случае бесполезно указывать вид блокировки adLockPessimistic - он будет заменён на adLockOptimistic. Отсюда вывод: желательно проверять, когда создаём recordset или connection, какой НА САМОМ ДЕЛЕ объект мы получили. Каждый ADO-провайдер себя ведёт здесь по своему, и даже один и тот же провайдер в зависимости от обстоятельств может вернуть не тот тип набора записей, на который мы рассчитывали, а другой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.03.2004, 18:16 |
|
||
|
ADO Recordset блокирует всю таблицу, нужно блокировать только редактируемую запись.
|
|||
|---|---|---|---|
|
#18+
Хочу уточнить у корифеев принципиальнцую возможность следующего: Для двух подключений Microsoft Jet 4.0 OLE DB Provider для объекта ADODB.Connection Код: plaintext 1. 2. 3. 4. 5. У меня такой фокус не проходит ни при каких параметрах подключения и рекордсета. Считал, что, при включенной транзакции, даже при Row-level Locking = 1 блокируется вся страница. ЗЫ: Видала я транзакции без блокировок, но что бы блокировки без транзакций... (с) Алиса в стране Акцесс. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2004, 17:28 |
|
||
|
ADO Recordset блокирует всю таблицу, нужно блокировать только редактируемую запись.
|
|||
|---|---|---|---|
|
#18+
Вы знаете, ещё немного поэкспериментировав и в очередной раз помусолив MSDN (из-за скудости информации там приходится читать ну прям буквально между строк!), я пришёл к неутешительному выводу: похоже (при использовании Microsoft Jet 4.0 OLE DB Provider), что никакая комбинация параметров НЕ ГАРАНТИРУЕТ блокировок на уровне записи, и если Jet считает, что нужно использовать страничную блокировку, то он таки её будет использовать, несмотря на твои указания. Максимум, что можно сколь-нибудь точно выяснить - это при каких обстоятельствах блокировки на уровне записей НЕ БУДЕТ. Честно говоря, мне не удалось добиться добавления записи в таблицу при наличии висящей транзакции, в которой ранее в ту же таблицу была добавлена запись, и склоняюсь к мысли, что это невозможно... Хотелось бы, чтобы меня переубедили. Более того, мне даже не удалось воспроизвести результаты моих прежних экспериментов, в которых добавление записи в таблицу не блокировало соседние записи. Все настройки, которые требуются для row-level locking, наличествуют, но что-то в окружении изменилось, и Jet упорно использует page-level locking... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.03.2004, 21:36 |
|
||
|
|

start [/forum/topic.php?fid=45&msg=32459872&tid=1675750]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
154ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
38ms |
get tp. blocked users: |
1ms |
| others: | 242ms |
| total: | 477ms |

| 0 / 0 |
