Я использую вторую форму транзакций knex (например, с «транзакцией»). Тем не менее, этот вопрос, вероятно, действителен и для первой формы.
Пример документации показывает это:
// Using trx as a transaction object:
knex.transaction(function(trx) {
const books = [
{title: 'Canterbury Tales'},
{title: 'Moby Dick'},
{title: 'Hamlet'}
];
knex.insert({name: 'Old Books'}, 'id')
.into('catalogues')
.transacting(trx)
.then(function(ids) {
books.forEach((book) => book.catalogue_id = ids[0]);
return knex('books').insert(books).transacting(trx);
})
.then(trx.commit)
.catch(trx.rollback);
})
В транзакции выполняются две команды "вставки". Второй отправляется только после того, как обещание первого выполнено (т. Е. В обратном вызове обещания then).
В приведенном выше примере это необходимо, поскольку вторую команду можно сформулировать только после результат первой команды вернулся.
Однако бывают случаи, когда несколько команд могут быть сформулированы заранее. Таким образом, можно выполнить код, подобный следующему:
promise1 = knex('table1').insert(...).transacting(trx).then(...)
promise2 = knex('table2').insert(...).transacting(trx).then(...)
Use Promise.all to wait for completion and eventually commit or rollback.
Фактически этот код будет выполняться. Knex будет ставить команды в очередь и отправлять их по соединению, назначенному для транзакции, по одной за раз.
Однако , и это суть моего вопроса , эмпирическое доказательство при использовании knex с PostgreSQL, кажется, показывает, что порядок, в котором команды отправляются в базу данных, не поддерживается. Другими словами, порядок, в котором команды были отправлены в knex, не обязательно является порядком, в котором они отправляются в базу данных. Похоже, что единственный способ гарантировать, что команды отправляются в определенном порядке c, - создать цепочку обещаний, в которой каждая команда представляется только после выполнения предыдущей команды.
Может кто-нибудь прокомментировать это ? Это по замыслу? Может ли это быть ошибкой?