Як подолати відсутність транзакцій у MongoDB?


139

Я знаю, що тут є подібні запитання, але вони або кажуть мені перейти до звичайних систем RDBMS, якщо мені потрібні транзакції, або використовувати атомні операції або двофазну фіксацію . Друге рішення видається найкращим вибором. Третє, я не хочу слідувати, тому що, здається, багато речей можуть піти не так, і я не можу перевірити це в усіх аспектах. Мені важко переробити проект на виконання атомних операцій. Я не знаю, чи походить це з моєї обмеженої точки зору (я працював лише з базами даних SQL до цих пір), чи це насправді неможливо зробити.

Ми хотіли б провести тест MongoDB в нашій компанії. Ми обрали порівняно простий проект - SMS-шлюз. Це дозволяє нашому програмному забезпеченню відправляти SMS-повідомлення в стільникову мережу, а шлюз виконує брудну роботу: фактично спілкується з провайдерами за допомогою різних протоколів зв'язку. Шлюз також керує оплатою повідомлень. Кожен клієнт, який подає заявку на послугу, повинен придбати кілька кредитів. Система автоматично зменшує баланс користувача при надсиланні повідомлення та відмовляє у доступі, якщо баланс недостатній. Оскільки ми також є клієнтами сторонніх постачальників SMS, ми можемо також мати свої баланси з ними. Ми також повинні їх слідкувати.

Я почав замислюватися над тим, як я можу зберігати потрібні дані в MongoDB, якщо скорочую деяку складність (зовнішня виставлення рахунків, відправлення SMS у чергу). Виходячи зі світу SQL, я створив би окрему таблицю для користувачів, іншу для SMS-повідомлень та одну для зберігання транзакцій щодо балансу користувачів. Скажімо, я створюю окремі колекції для всіх тих, хто в MongoDB.

Уявіть завдання надсилання SMS із наступними кроками в цій спрощеній системі:

  1. перевірити, чи є у користувача достатній баланс; заборонити доступ, якщо кредиту не вистачає

  2. надіслати та зберігати повідомлення у колекції SMS із деталями та вартістю (у системі живого повідомлення повідомлення матиме statusатрибут, а завдання підбере його для доставки та встановить ціну SMS відповідно до його поточного стану)

  3. зменшити залишок користувачів на вартість відправленого повідомлення

  4. введіть транзакцію у збір транзакцій

Тепер у чому проблема? MongoDB може робити атомні оновлення лише на одному документі. У попередньому потоці може статися так, що якась помилка виповзає і повідомлення зберігається в базі даних, але баланс користувача не оновлюється та / або транзакція не реєструється.

Я придумав дві ідеї:

  • Створіть єдину колекцію для користувачів і зберігайте баланс як поле, пов’язані з користувачем транзакції та повідомлення як допоміжні документи в документі користувача. Оскільки ми можемо оновлювати документи атомним шляхом, це фактично вирішує проблему транзакцій. Недоліки: якщо користувач надсилає багато SMS-повідомлень, розмір документа може стати великим, а ліміт документа в 4 МБ може бути досягнутий. Можливо, я можу створювати документи з історії в таких сценаріях, але я не думаю, що це було б гарною ідеєю. Крім того, я не знаю, наскільки швидкою була б система, якщо я підсилюю все більше і більше даних до одного і того ж великого документа.

  • Створіть одну колекцію для користувачів та одну для транзакцій. Можливі два види транзакцій: покупка кредиту із зміною позитивного балансу та повідомлення, надіслане із зміною балансу. Транзакція може мати субдокумент; наприклад, у повідомленнях, що надсилаються, дані SMS можуть бути вбудовані в транзакцію. Недоліки: я не зберігаю поточний баланс користувача, тому мені доводиться обчислювати його кожен раз, коли користувач намагається надіслати повідомлення, щоб повідомити, чи може повідомлення пройти чи ні. Я боюся, що цей обчислення може стати повільним у міру зростання кількості збережених транзакцій.

Я трохи заплутався, який метод вибрати. Є інші рішення? В Інтернеті я не міг знайти жодної найкращої практики щодо вирішення подібних проблем. Я думаю, що багато програмістів, які намагаються ознайомитися зі світом NoSQL, на початку стикаються з подібними проблемами.


61
Пробачте, якщо я помиляюся, але виглядає так, ніби цей проект буде використовувати сховище даних NoSQL незалежно від того, отримає це користь від цього чи ні. NoSQL не є альтернативою SQL як "модному" вибору, але коли технологія реляційних RDBMS не відповідає проблемному простору і нереляційна сховище даних. Багато ваших запитань: "Якби це був SQL, то ...", і це дзвонить мені попереджувальні дзвони. Усі NoSQL виникли з необхідності вирішити проблему, яку SQL не міг, а потім їх було дещо узагальнено для полегшення використання, а потім, звичайно, смуга починає котитися.
PurplePilot

4
Я знаю, що цей проект не є найкращим для випробування NoSQL. Однак я побоююся, якщо ми почнемо використовувати його в інших проектах (скажімо, програмне забезпечення для управління колекціями бібліотек, оскільки ми перебуваємо в управлінні колекціями) і раптом з’являється якийсь запит, в якому потрібні транзакції (і насправді це є, уявіть, що книги переноситься з однієї колекції в іншу) ми повинні знати, як можна подолати проблему. Можливо, я просто обмежений і вважаю, що завжди потрібна транзакція. Але це може бути спосіб якось їх подолати.
NagyI

3
Я погоджуюся з PurplePilot, ви повинні вибрати технологію, яка відповідає рішенню, а не намагатися прищепити рішення, яке не підходить до проблеми. Моделювання даних для баз даних графіків - це зовсім інша парадигма, ніж дизайн RDBMS, і ви повинні забути все, що знаєте, і вивчити новий спосіб мислення.

9
Я розумію, що я повинен використовувати відповідний інструмент для виконання завдання. Однак для мене - коли я читаю відповіді, як це - здається, що NoSQL не підходить ні для чого, де дані є критичними. Це добре для Facebook чи Twitter, де, якщо деякі коментарі втрачаються, світ продовжується, але все, що вище, не має справи. Якщо це правда, я не розумію, чому інші турбуються про будівництво, наприклад. веб-магазин з MongoDB: kylebanker.com/blog/2010/04/30/mongodb-and-ecommerce У ньому навіть зазначається, що більшість транзакцій можна подолати за допомогою атомних операцій. Що я шукаю - це як.
NagyI

2
Ви кажете, "схоже, що NoSQL не корисний ні для чого, де дані є критичними", це неправда, де це не добре (можливо) - транзакційна обробка транзакційних типів ACID. Також NoSQL призначені для розподілених сховищ даних, зберігання яких типу SQL може бути дуже складно досягти, коли ви потрапляєте в сценарії реплікації головного ведомого. У NoSQL є стратегії для можливої ​​узгодженості та забезпечення лише використання останнього набору даних, але не ACID.
PurplePilot

Відповіді:


23

Станом на 4.0, MongoDB матиме багатодокументні транзакції ACID. План полягає в тому, щоб спочатку ввімкнути тих, хто знаходиться в наборі реплік, а потім - стрижених кластерів. Операції в MongoDB будуть відчувати себе так, як розробники транзакцій знайомі з реляційних баз даних - вони будуть мульти-операторами, з подібною семантикою та синтаксисом (як start_transactionі commit_transaction). Важливо, що зміни в MongoDB, які дозволяють здійснювати транзакції, не впливають на ефективність робочих навантажень, які не потребують їх.

Детальніше дивіться тут .

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


1
Операції надійшли! 4,0 GA'ed. mongodb.com/blog/post/…
Григорій Мельник

У транзакціях MongoDB все ще є обмеження на розмір транзакції 16 Мб, нещодавно у мене був випадок використання, коли мені потрібно помістити записи 50k з файлу в mongoDB, тому для підтримки атомної властивості я думав використовувати транзакції, але оскільки записи 50k json перевищити цю межу, вона видає помилку "Загальний розмір всіх операцій транзакцій повинен бути меншим 16793600. Фактичний розмір - 16793817". Для отримання детальної інформації ви можете ознайомитись з офіційним квитком jira, відкритим на mongoDB jira.mongodb.org/browse/SERVER-36330
Gautam Malik

MongoDB 4.2 (зараз у бета-версії, RC4) підтримує великі транзакції. Представляючи транзакції в декількох записах oplog, ви зможете записати більше 16 МБ даних в одну транзакцію ACID (за умови існуючого максимального часу виконання за замовчуванням 60 секунд). Ви можете спробувати їх зараз - mongodb.com/download-center/community
Григорій Мельник

MongoDB 4.2 тепер GA з повною підтримкою розподілених транзакцій. mongodb.com/blog/post/…
Григорій Мельник

83

Життя без угод

Операції підтримують властивості ACID, але хоча транзакцій у них немає, у MongoDBнас є атомні операції. Ну атомні операції означають, що коли ви працюєте над одним документом, ця робота буде завершена, перш ніж хтось побачить документ. Вони побачать усі внесені нами зміни або жодну з них. І за допомогою атомних операцій ви часто можете виконати те саме, що ми зробили б, використовуючи транзакції в реляційній базі даних. А причина полягає в тому, що у реляційній базі даних нам потрібно внести зміни в декілька таблиць. Зазвичай таблиці, які потрібно з'єднати, і ми хочемо зробити це все відразу. І для цього, оскільки існує декілька таблиць, нам доведеться розпочати транзакцію та виконати всі ці оновлення, а потім закінчити транзакцію. Але зMongoDB, ми збираємося вставляти дані, оскільки ми будемо попередньо приєднати їх до документів, і це ці багаті документи, які мають ієрархію. Ми часто можемо здійснити те саме. Наприклад, у прикладі блогу, якщо ми хотіли переконатися, що ми оновили публікацію блогу атомним шляхом, ми можемо це зробити, оскільки ми можемо оновлювати всю публікацію блогу одночасно. Де як би це була купа реляційних таблиць, нам, мабуть, доведеться відкрити транзакцію, щоб ми могли оновити колекцію публікацій та колекцію коментарів.

То які наші підходи ми можемо застосувати, MongoDBщоб подолати брак транзакцій?

  • реструктуризація - реструктуруйте код, щоб ми працювали в рамках одного документа та користувалися атомними операціями, які ми пропонуємо в цьому документі. І якщо ми це робимо, то зазвичай ми все налаштовані.
  • впровадити в програмне забезпечення - ми можемо реалізувати блокування в програмному забезпеченні, створивши критичний розділ. Ми можемо створити тест, протестувати і встановити, використовуючи пошук і модифікацію. Ми можемо побудувати семафори, якщо потрібно. І певним чином, таким чином все-таки працює більший світ. Якщо ми подумаємо про це, якщо одному банку потрібно передати гроші в інший банк, вони не живуть в одній реляційній системі. І у кожного вони часто мають свої реляційні бази даних. І вони повинні бути в змозі координувати цю операцію, навіть якщо ми не можемо починати транзакції та закінчувати транзакції через ці системи баз даних, лише в одній системі в одному банку. Тож, безумовно, існують способи у вирішенні проблеми.
  • терпіти - остаточний підхід, який часто працює в сучасних веб-додатках та інших додатках, які забирають величезну кількість даних, - це просто терпіти трохи невідповідності. Наприклад, якщо ми говоримо про канал друзів у Facebook, не має значення, чи всі бачать одночасно оновлення вашої стіни. Якщо добре, якщо одна людина на кілька секунд відстає, і вони наздоганяють. У багатьох проектах системи часто не важливо, щоб все було повністю узгоджено і щоб усі мали ідеально послідовний і однаковий погляд на базу даних. Тож ми могли би просто терпіти трохи непослідовність, яка є дещо тимчасовою.

Update, findAndModify, $addToSet( В межах поновлення) і $push( в межах поновлення) операції виконують атомарний в одному документі.


2
Мені подобається, як це відповідає, замість того, щоб продовжувати розпитувати, чи варто повертатися до реляційної БД. Дякую @xameeramir!
DonnyTian

3
критичний розділ коду не буде працювати, якщо у вас більше 1 сервера, доведеться користуватися послугою зовнішнього розподіленого блокування
Олександр Міллз

@AlexanderMills Чи можете ви, будь ласка, детальніше розповісти?
Замер

Здається, тут є стенограма відео: youtube.com/watch?v=_Iz5xLZr8Lw
Фріц

Я думаю, що це здається прекрасним, поки ми не обмежимось тим, що працюватиме на одній колекції. Але ми не можемо помістити все в один документ через різні причини (розмір документа або якщо ви використовуєте посилання). Я думаю, тоді нам можуть знадобитися транзакції.
користувач2488286

24

Перевірте це , Tokutek. Вони розробляють плагін для Mongo, який обіцяє не тільки транзакції, але й підвищення продуктивності.


@Giovanni Bitliner. Токутек з тих пір придбав Percona, і на посиланні, яке ви надали, я не бачу посилання на будь-яку інформацію про те, що сталося з часу публікації. Чи знаєте ви, що сталося з їх зусиллями? Я надіслав електронну адресу на цій сторінці, щоб дізнатися це.
Тайлер Коллер

Що вам конкретно потрібно? Якщо вам потрібна технологія потоку, застосована до Mongodb, спробуйте github.com/Tokutek/mongo , якщо вам потрібна версія mysql, можливо, вони додали її до своєї стандартної версії Mysql, яку вони зазвичай надають
Giovanni Bitliner

Як я можу інтегрувати текутек з nodejs.
Маной Саньєєва

11

Доведіть до речі: якщо цілісність транзакцій є обов'язковою, тоді не використовуйте MongoDB, а використовуйте лише компоненти в системі, що підтримує транзакції. Вкрай важко побудувати щось над компонентом, щоб забезпечити подібні ACID функціональні можливості для компонентів, що не відповідають стандартам ACID. Залежно від окремих випадків використання певним чином може мати сенс розділяти дії на транзакційні та не транзакційні дії ...


1
Я думаю, ви маєте на увазі, що NoSQL може бути використаний як база даних, що застосовується з класичними RDBMS. Мені не подобається ідея змішувати NoSQL і SQL в одному проекті. Це підвищує складність і, можливо, вводить і деякі нетривіальні проблеми.
NagyI

1
Рішення NoSQL рідко використовуються поодинці. Магазини документів (монго і кушетка), мабуть, є єдиним винятком цього правила.
Каролі Хорват

7

Тепер у чому проблема? MongoDB може робити атомні оновлення лише на одному документі. У попередньому потоці може статися так, що якась помилка виповзає і повідомлення зберігається в базі даних, але баланс користувача не зменшується та / або транзакція не записується.

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

Справжня проблема тут полягає в тому, що користувач може скористатися умовами перегонів та надіслати більше повідомлень, ніж дозволяє його баланс. Це стосується і RDBMS, якщо ви не здійснюєте надсилання SMS всередині транзакції з блокуванням поля балансу (що було б великим місцем). Як можливе рішення для MongoDB було б використовувати findAndModifyспочатку зменшити баланс і перевірити його, якщо це негативно забороняє надсилати та повертати суму (приріст атома). Якщо позитивно, продовжуйте надсилати, і якщо це не поверне суму. Колекцію історії балансу також можна підтримувати, щоб допомогти виправити / перевірити поле балансу.


Дякую за цю чудову відповідь! Я знаю, що якщо я використовую транзакційні сховища, дані можуть бути пошкоджені через систему SMS, залежно від того, я не маю контролю. Однак у Mongo є ймовірність, що помилка даних може статися і всередині компанії. Скажімо, код змінює баланс користувача за допомогою findAndModify, баланс стає негативним, але перш ніж я можу виправити помилку, виникає помилка, і програмі потрібно перезапустити. Я думаю, ви маєте на увазі, що я повинен реалізувати щось подібне до двофазної фіксації на основі збору транзакцій і робити регулярну перевірку виправлень у базі даних.
NagyI

9
Неправда, транзакційні магазини відмовляться, якщо ви не зробите остаточного зобов'язання.
Каролі Хорват

9
Крім того, ви не надсилаєте SMS і потім входите в БД, це просто неправильно. Спочатку зберігайте все в БД і виконайте остаточну фіксацію, після чого ви можете відправити повідомлення. У цей момент щось все-таки може вийти з ладу, тому вам потрібна робота з кроном, щоб перевірити, чи повідомлення було надіслано, якщо не спробувати надіслати. Можливо, для цього було б краще виділити спеціальну чергу повідомлень. Але вся справа зводиться до того, чи можете ви надсилати SMS-повідомлення транзакційним способом ...
Каролі Хорват

@NagyI так, саме це я мав на увазі. Треба торгувати вигодами угод для простоти масштабування. В основному заявка повинна очікувати, що будь-які два документи в різних колекціях можуть знаходитись у несуперечливому стані та бути готовими впоратися з цим. @yi_H він відкине, але стан більше не буде фактичним (інформація про повідомлення буде втрачена). Це не набагато краще, ніж просто мати часткові дані (як-от зменшення балансу, але немає інформації про повідомлення або навпаки).
pingw33n

Я бачу. Це насправді непросте обмеження. Можливо, я повинен дізнатися більше про те, як системи RDBMS роблять транзакції. Чи можете ви порекомендувати якийсь онлайн-матеріал чи книгу, де я можу прочитати про них?
NagyI

6

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

Отже, якщо ви дійсно хочете пілотного проекту для MongoDB, виберіть той, який простий у цьому відношенні.


Дякую за пояснення. Сумно це чути. Мені подобається простота NoSQL і використання JSON. Ми шукаємо альтернативу ORM, але схоже, що ми повинні її дотримуватися деякий час.
NagyI

Чи можете ви навести якісь вагомі причини, чому MongoDB для цієї задачі кращий, ніж SQL? Пілотний проект звучить трохи нерозумно.
Каролі Горват

Я не сказав, що MongoDB кращий за SQL. Ми просто хочемо знати, чи краще це від SQL + ORM. Але тепер стає зрозумілішим, що вони не є конкурентоспроможними в таких проектах.
NagyI

6

Операції відсутні в MongoDB з поважних причин. Це одна з тих речей, які роблять MongoDB швидше.

У вашому випадку, якщо транзакція є обов'язковою, монго здається не дуже підходящим.

Може бути RDMBS + MongoDB, але це додасть складності та ускладнить управління та підтримку додатків.


1
Зараз існує дистрибуція MongoDB під назвою TokuMX, яка використовує фрактальну технологію, щоб забезпечити 50-кратне підвищення продуктивності та одночасно надає повну підтримку транзакцій ACID: tokutek.com/tokumx-for-mongodb
OCDev

9
Як транзакція ніколи не може бути "обов'язковою". Як тільки вам коли-небудь знадобиться 1 простий випадок, коли вам потрібно оновити 2 таблиці, монго раптом вже не підходить? Це зовсім не залишає дуже багато випадків використання.
Mr_E

1
@Mr_E згоден, тому MongoDB ніби немов :)
Олександр Міллс

6

Це, мабуть, найкращий блог, який я знайшов щодо здійснення транзакцій, таких як функція для mongodb.!

Синхронізувати прапор: найкраще для простого копіювання даних із головного документа

Черга вакансій: дуже загальне призначення, вирішує 95% випадків. Більшість систем так чи інакше мають мати принаймні одну чергу роботи!

Дві фази: цей метод забезпечує, щоб кожен суб'єкт господарювання завжди мав всю інформацію, необхідну для того, щоб перейти до послідовного стану

Примирення журналу: найміцніша техніка, ідеальна для фінансових систем

Версія: забезпечує ізоляцію та підтримує складні структури

Прочитайте це для отримання додаткової інформації: https://dzone.com/articles/how-implement-robust-and


Будь ласка, включіть відповідні частини пов'язаного ресурсу, необхідні для відповіді на питання у межах вашої відповіді. Так, ваша відповідь дуже сприйнятлива до гниття посилань (тобто, якщо пов’язаний веб-сайт знижується або змінюється, ваша відповідь є потенційно марною).
mech

Дякую @mech за пропозицію
Vaibhav

4

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

  • Вимога:
    Зображення нижче показує 2 дії потрібно виконувати одночасно, але фазу 2 та фазу 3 дії 1 потрібно закінчити перед початком фази 2 дії 2 або навпаки (Фаза може бути запитом REST api, запитом бази даних або виконанням коду javascript ... ). введіть тут опис зображення

  • Як черга допоможе вам
    Черга, переконайтеся, що кожен код блоку між lock()і release()у багатьох функціях не працюватиме одночасно, змушуйте їх ізолювати.

    function action1() {
      phase1();
      queue.lock("action_domain");
      phase2();
      phase3();
      queue.release("action_domain");
    }
    
    function action2() {
      phase1();
      queue.lock("action_domain");
      phase2();
      queue.release("action_domain");
    }
  • Як побудувати чергу
    Я зупинюсь лише на тому, як уникнути участі в перегонах під час створення черги на заднім сайті. Якщо ви не знаєте основної ідеї черги, заходьте сюди .
    Код нижче показує лише концепцію, яку потрібно реалізувати правильно.

    function lock() {
      if(isRunning()) {
        addIsolateCodeToQueue(); //use callback, delegate, function pointer... depend on your language
      } else {
        setStateToRunning();
        pickOneAndExecute();
      }
    }
    
    function release() {
      setStateToRelease();
      pickOneAndExecute();
    }

Але вам потрібно isRunning() setStateToRelease() setStateToRunning()ізолювати себе, інакше ви знову зіткнетеся з перегоном. Для цього я вибираю Redis з метою кислоти та масштабування. Документ
Redis розповість про свою транзакцію:

Усі команди транзакції серіалізуються та виконуються послідовно. Ніколи не може статися, що запит, виданий іншим клієнтом, подається в середині виконання транзакції Redis. Це гарантує, що команди виконуються як одна окрема операція.

P / s:
Я використовую Redis, оскільки моя служба вже використовує його, ви можете використовувати будь-який інший спосіб підтримки ізоляції для цього.
У action_domainмоєму коді наведено вище, коли вам потрібна лише дія 1 виклику користувача Блокова дія 2 користувача A, не блокуйте іншого користувача. Ідея - це унікальний ключ для блокування кожного користувача.


Ви отримали б більше грошей, якби ваш результат уже був вищим. Ось як думають більшість тут. Ваша відповідь корисна в контексті запитання. Я підтримав тебе.
Мукус

3

Операції доступні зараз у MongoDB 4.0. Зразок тут

// Runs the txnFunc and retries if TransientTransactionError encountered

function runTransactionWithRetry(txnFunc, session) {
    while (true) {
        try {
            txnFunc(session);  // performs transaction
            break;
        } catch (error) {
            // If transient error, retry the whole transaction
            if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError")  ) {
                print("TransientTransactionError, retrying transaction ...");
                continue;
            } else {
                throw error;
            }
        }
    }
}

// Retries commit if UnknownTransactionCommitResult encountered

function commitWithRetry(session) {
    while (true) {
        try {
            session.commitTransaction(); // Uses write concern set at transaction start.
            print("Transaction committed.");
            break;
        } catch (error) {
            // Can retry commit
            if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult") ) {
                print("UnknownTransactionCommitResult, retrying commit operation ...");
                continue;
            } else {
                print("Error during commit ...");
                throw error;
            }
       }
    }
}

// Updates two collections in a transactions

function updateEmployeeInfo(session) {
    employeesCollection = session.getDatabase("hr").employees;
    eventsCollection = session.getDatabase("reporting").events;

    session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

    try{
        employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
        eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
    } catch (error) {
        print("Caught exception during transaction, aborting.");
        session.abortTransaction();
        throw error;
    }

    commitWithRetry(session);
}

// Start a session.
session = db.getMongo().startSession( { mode: "primary" } );

try{
   runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
   // Do something with error
} finally {
   session.endSession();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.