ПОДОЛАННЯ КОНФЛІКТІВ

Досі ми припускали, що з програмою працює один користувач У цьому випадку обробка даних виконується без конфліктів Вони виникають в многопользовательском режимі, коли декілька користувачів одночасно намагаються оновити запису однієї і тієї ж DBF-таблиці інформаційної бази даних При цьому виявляється, що DBF-таблиця доступна тільки користувачеві, перший отримав до неї доступ У цьому випадку говорять, що ставсязахоплення таблиціПри одиничних записах час захоплення таблиці нетривало, і якщо програми інших користувачів можуть чекати звільнення таблиці, то конфлікт через деякий час буде вичерпано Якщо ж програми не містять коди, що забезпечує режим очікування, то при спробі оновлення захопленої таблиці станеться завершальна виконання помилка, супроводжувана, наприклад, таким повідомленням:

жз3апісать ()

{D: \ ПPOБAERT (20)}: Обєкт заблокований: Журнал розрахунків Журнал заробітної плати Щоб промоделювати таку ситуацію, напишемо наступний код:

процедура Виконати () / / Повязана з кнопкою Пуск обробки Проба

перем сСотр_2, співр, ЖЗ, рез, прапор ОчістітьОкноСообщеній ()

сСотр_2 = СоздатьОбект (СправочнікСотруднікі_2)

/ / Шукаємо у всьому довіднику співробітника з кодом 301 сСотр_2НайтіПоКоду (301,0)

співр = сСотр_2ТекущійЕлемент ()

ЖЗ = СоздатьОбект (ЖурналРасчетовЗарплата_2)

/ / Відкриваємо вибірку розрахунків обєкта, зареєстрованих в поточному періоді жзВибратьПеріодПоОбекту (співр)

поки жзПолучітьЗапісь () = 1 цикл

/ / Пропускаємо фіксовані та виправлені розрахунки якщо жзФіксірована + жзІсправлена ​​про 0 тоді

продовжити КонецЕсли

рез = жзРезультат

/ / Починаємо нескінченний цикл

/ / Щоб цикл перервати, потрібно натиснути клавішу Esc

/ / У цьому циклі час від часу захоплюється ЖЗ прапор = 1

поки прапор = 1 цикл

/ / Значення реквізиту Результат не змінюється жзУстановітьРеквізіт (Результат, різ) жз3апісать ()

конецЦікла / / Поки прапор = 1 конецЦікла / / Поки жзПолучітьЗапісь () = 1

КонецПроцедури / / Виконати

Ця програма ніяких змін в ЖЗ не виробляє, але час від часу, виконуючи оператор

жз3апісать ()

захоплює журнал розрахунків Зарплата_2

Нехай 1С: Підприємство відкриють два користувача (у цьому експерименті число користувачів при бажанні можна зробити і великим) Перший запустить наведену програму, а другий ту ж програму, але замість оператора

/ / Шукаємо у всьому довіднику співробітника з кодом 301 сСотр_2НайтіПоКоду (301,0)

що має оператор

/ / Шукаємо у всьому довіднику співробітника з кодом 302 сСотр_2НайтіПоКоду (302, 0)

Тобто в ЖЗ ми будемо оновлювати результат інший запису, що відповідає обєкту з кодом 302

Тоді якщо співробітники з кодами 301 і 302 в довіднику Сотруднікі_2 є і якщо в поточному періоді ЖЗ кожен з цих співробітників має нефіксованої і невиправлені розрахунок, то неминуче в роботі одного з користувачів виникне завершальна помилка виконання і наведене вище повідомлення про цю помилку

Якщо ж у цьому експерименті замість операторів

жзУстановітьРеквізіт (Результат, різ) жз3апісать ()

записати оператор жзРезультат = рез

то помилка виникне відразу у двох користувачів (оскільки маємо справу з нескінченним циклом) Повідомлення, яке вони зможуть спостерігати, буде таким:

жзРезультат = рез

{D: \ ПPOБAERT (21)}: Запис заблокована

Причому помилка буде не завершальній, а інформаційної та повідомлення про неї буде відтворюватися аж до переривання обробки, виконуваного клавішею Esc Після переривання однією з обробок блокування буде знята і залишилася обробка продовжить обчислення

У чистому вигляді на практиці така ситуація може виникнути лише при наявності в програмі помилки, що приводить до нескінченного циклу Але описані користувальницькі конфлікти будуть відбуватися і в правильно написаної (з позиції одного користувача) програмі при інтенсивних модифікаціях таблиць бази даних

Щоб продемонструвати метод усунення такої помилки, продовжимо розпочатий приклад, модифікувавши у ньому нескінченний цикл Покипрапор = 1, ввівши в нього керуючу конструкцію Спроба

/ / Починаємо нескінченний цикл

/ / Щоб цикл перервати, потрібно натиснути клавішу Esc

/ / У цьому циклі час від часу захоплюється ЖЗ прапор = 1

поки прапор = 1 цикл / / Цей цикл підлягає модифікації

/ / Значення реквізиту Результат не змінюється жзУстановітьРеквізіт (Результат, різ)

/ / Початок додається коду

/ / Вводимо в циклі Поки флагПопиткі 1 керуючу конструкцію Спроба

/ / Цикл перерветься після вдалого виконання методу Записати флагПопиткі = 1

поки флагПопиткі = 1 цикл

спроба / / Керуюча конструкція Спроба жз3апісать () / / Цей оператор зі старого коду флагПопиткі = 0

Повідомити (Запис виконана”)

виняток

Повідомити (Очікую звільнення таблиці“) конецПопиткі

конецЦікла / / Поки флагПопиткі = 1

/ / Кінець додається коду конецЦікла / / Поки прапор = 1

Внесемо відповідні зміни до обробки двох наших користувачів і запустимо їх процедури Виконати Зовнішній цикл раніше буде нескінченним, але завдяки керуючої конструкції Спроба завершальних помилок з причини блокування DBF-таблиці відбуватися не буде і відповідні її записи будуть оновлюватися Додані виклики вбудованої процедури Повідомити привнесуть у вікно повідомлень (в многопользовательском режимі) наступний код:

Запис виконана

Запис виконана

Очікую звільнення таблиці Очікую звільнення таблиці Запис виконана

Продемонстрований метод подолання конфліктів за допомогою керуючої конструкції Спроба потрібно застосовувати кожен раз, коли є загроза користувальницьких конфліктів на грунті захоплення DBF-таблиць Зокрема, при роботі така загроза існує при вживанні методів, що виконують модифікацію ЖЗ, а саме: ВиполнітьРасчет, Розрахувати, ВвестіРасчет, ЗапісатьРасчет, ВвестіПерерасчет, Записати, ФіксіроватьЗапісь, ОсвободітьЗапісь, Виправити, ОтменітьІсправленіе і УдалітьЗапісь

З урахуванням сказаного процедура РасчетОбекта, яка розраховує записи співробітника, що викликається з процедури РасчетЗП (розд 7171), повинна бути вдосконалена наступним чином:

/ / Оновлена ​​процедура РасчетОбекта

/ / Розраховує всі записи обєкта ЖЗ крім розрахунку з ВР НачСальдо_2

/ / Оскільки процедура присутній в модулі форми списку ЖЗ,

/ / То всі методи ЖР викликаються без префікса процедура РасчетОбекта (співр)

перем прапор, СОТР2, флагПопиткі

/ / Прапор буде дорівнювати одиниці, якщо у співробітника є розрахунок з ВР Оклад_2 прапор = 0

СОТР2 = співр / / Запамятовуємо для виведення повідомлення

/ / Відкриваємо вибірку розрахунків обєкта, зареєстрованих в поточному періоді ВибратьПеріодПоОбекту (співр)

поки ПолучітьЗапісь () = 1 цикл

якщо відРасч = ВідРасчетаНДФЛ_2 тоді прапор = 1

КонецЕсли

/ / Фіксовані та виправлені записи розраховувати немає сенсу якщо Фіксована + Виправлена ​​= 0 тоді

/ / Початок додається коду

/ / Вводимо в циклі Поки флагПопиткі = 1 керуючу конструкцію Спроба

/ / Цикл перерветься після вдалого виконання методу Розрахувати флагПопиткі = 1

поки флагПопиткі = 1 цикл

спроба / / Керуюча конструкція Спроба Розрахувати () / / Цей оператор зі старого коду флагПопиткі = 0

Стан (Виконано розрахунок співробітника + сотрНаіменованіе) виняток

Стан (Очікую звільнення таблиці“)

конецПопиткі

конецЦікла / / Поки флагПопиткі = 1

/ / Кінець додається коду

КонецЕсли конецЦікла / / Поки якщо прапор = 0 тоді

Повідомити (Оформіть табель співробітнику + сотр2Наіменованіе) КонецЕсли

КонецПроцедури / / РасчетОбекта

Аналогічні зміни мають бути внесені і в інші процедури модуля форми списку ЖЗ Зарплата_2, а також в модулі форм створених нами документів і довідників, хоча ступінь їх конфліктності в порівнянні з ЖЗ істотно нижче

Питання надійності виконання зумовлених процедур модуля документа ОбработкаПроведенія і ОбработкаУдаленияПроведения обговорюється в наступному розділі Тут же зауважимо, що в періоди розрахунку зарплати, тривалість яких в силу організаційних причин невелика (трохи більше тижня), ці процедури (особливо ОбработкаПроведенія), що викликаються в створюють розрахунки ЖЗ документах, інтенсивно модифікують базу даних і, отже, мають підвищену

конфліктністю

822 ТРАНЗАКЦІЇ

Транзакція це механізм оновлення таблиць бази даних, що забезпечує при відсутності зовнішніх впливів отримання очікуваного результату У разі неможливості поновлення таблиць відповідно до встановленими правилами транзакцію можна скасувати, не проводячи яких модифікацій даних (Під зовнішніми впливами розуміються фактори, що виникають не в результаті виконання програми, а з інших причин, наприклад при збоях в енергопостачанні, вірусній атаці та ін)

Якщо мова йде про одиничному оновленні бази даних, наприклад в результаті виконання методу Записати, то гарантії отримання очікуваного результату нам дає керуюча конструкція Спроба При пакетному оновленні бази даних, наприклад в результаті проведення документа, що породжує численні розрахунки ЖЗ, потрібно застосовувати транзакцію

Треба сказати, що в модулі документа в зумовлених процедурах ОбработкаПроведенія і ОбработкаУдаленияПроведения 1С виконує передбачені в цих процедурах дії, вживаючи транзакцію Тому додавати в них свої транзакції немає необхідності

Відомо, що транзакції блокують використовувані в них DBF-файли, тому необхідно максимально сприяти їх успішного завершення Зокрема,

зумовлені процедури ОбработкаПроведенія і ОбработкаУдаленияПроведения не слід включати призупиняють до відгуку користувача процедури Питання, Попередження, функції, викликають діалог введення даних, наприклад ВвестіЗначеніе, та інші відкривають діалоги команди

У розвязуваних нами завданнях, окрім згаданих процесів проведення документів, транзакцію можна було б застосувати при розрахунку зарплати обєкта, записавши код процедури РасчетОбекта наступним чином:

/ / Ще один варіант процедури РасчетОбекта, на цей раз використовує транзакцію процедура РасчетОбекта (співр)

перем прапор, СОТР2

/ / Прапор буде дорівнювати одиниці, якщо у співробітника є розрахунок з ВР Оклад_2 прапор = 0

СОТР2 = співр / / Запамятовуємо для виведення повідомлення

/ / Відкриваємо вибірку розрахунків обєкта, зареєстрованих в поточному періоді якщо ВибратьПеріодПоОбекту (співр) = 0 тоді

повернення

КонецЕсли

НачатьТранзакцію () / / Перший доданий оператор .

поки ПолучітьЗапісь () = 1 цикл

якщо відРасч = ВідРасчетаНДФЛ_2 тоді прапор = 1

КонецЕсли

/ / Фіксовані та виправлені записи розраховувати немає сенсу якщо Фіксована + Виправлена ​​= 0 тоді

Розрахувати () КонецЕсли

конецЦікла / / Поки

якщо прапор = 1 тоді / / Транзакція фіксується, якщо проведено Табель ЗафіксіроватьТранзакцію () / / Другий доданий оператор

інакше / /прапор = 0

Скасувати Транзакцію () / / Третій доданий оператор Повідомити (Оформіть табель співробітнику + сотр2Наіменованіе)

КонецЕсли

КонецПроцедури / / РасчетОбекта

У цьому оновленому коді 3 нові (для нас) вбудовані в 1С процедури: НачатьТранзакцію, ЗафіксіроватьТранзакцію і ОтменітьТранзакцію Призначення процедур зрозуміло з їх назв Зупинимося на особливостях їх виконання

По-перше, користувач, який почав транзакцію, захоплює одну або кілька DBF-таблиць, що беруть участь в транзакції, і тим самим Не дає працювати іншим учасникам процесу При тривалому захопленні таблиці чекає процедура може завершитися аварійно, про що користувач отримає відповідне повідомлення, наприклад таке:

поки ПолучітьЗапісь () = 1 цикл

{ЖурналРасчетовЗарплата_2ФормаФормаСпискаФормаМодуль(250)}:Таблица: CJ4287

Помилка звернення до даних при транзакції, виконуваної іншим користувачем

Якщо захоплення нетривалий, то після завершення транзакції чекає користувач благополучно продовжить обчислення

По-друге, оновлення захоплених таблиць під час транзакції не проводиться, але необхідні для поновлення відомості накопичуються в належному вигляді для подальшого використання

Якщо в результаті транзакції отримані правильні результати, то слід викликати процедуру ЗафіксіроватьТранзакцію, яка, власне, і виконує оновлення бази даних і завершує транзакцію Якщо виявлені помилки, то виклик процедури ОтменітьТранзакцію завершить транзакцію, але ніяких модифікацій даних вироблено не буде Про виявлення помилок повинен подбати програміст, вмонтувавши в процедуру з транзакцією відповідний код

У нашому прикладі здійснені виклики всіх трьох процедур, що дещо змінило характер одержуваного результату Так, якщо раніше процедура РасчетОбекта модифікувала результати розрахунків і за відсутності розрахунку з ВР Оклад_2, то тепер в такій ситуації дані не змінюються, оскільки викликається процедура ОтменітьТранзакцію

Якщо порівнювати дві модифікації процедури РасчетОбекта (перша з керуючою конструкцією Спроба, а друга з транзакцією), то перевагу слід, мабуть, віддати першому варіанту На цей рахунок є щонайменше 3 причини Перша в тому, що немає необхідності розглядати розрахунок обєкта як єдине ціле і вживати для нього транзакцію цілком прийнятно, якщо розрахунки будуть виконуватися послідовно відповідно до встановленої черговості, і немає трагедії, якщо між двома вашими розрахунками виконається один-другий розрахунок іншого користувача По-друге, як ми переконалися, при тривалих транзакціях що чекають процедури можуть завершуватися аварійно І нарешті, транзакція може зажадати додаткових ресурсів (просторових, наприклад у вигляді області памяті на диску, і тимчасових), що знижують ефективність виконання програми

Джерело: Бартеньев О В 1С: Підприємство: програмування для всіх Базові обєкти та розрахунки на одній дискеті М: Діалог-МІФІ, 2005 464 с

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*