Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap batch updates on a transaction #16

Open
fcoury opened this issue Jul 16, 2022 · 3 comments
Open

Wrap batch updates on a transaction #16

fcoury opened this issue Jul 16, 2022 · 3 comments
Labels
enhancement New feature or request

Comments

@fcoury
Copy link
Owner

fcoury commented Jul 16, 2022

When you send an update command with multiple clauses, it should be atomic and if one of the updates don't work, all updates should be rolled back.

@fcoury
Copy link
Owner Author

fcoury commented Jul 16, 2022

Apparently mongodb doesn't work this way -- seems like the updates are atomic per document. You can see that the update to the last item of this collection wasn't applied at all, the name was not changed, even though the error was on the counter field.

test> db.trx.insertMany([
  {x: 1, name: 'John', counter: 1}, 
  {x: 2, name: 'Alex', counter: 2}, 
  {x: 3, name: 'Kate', counter: 'Str'}
])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("62d304384ca23db6dd87d2c4"),
    '1': ObjectId("62d304384ca23db6dd87d2c5"),
    '2': ObjectId("62d304384ca23db6dd87d2c6")
  }
}
test> db.trx.updateMany({}, { $set: {name: 'Old'}, $inc: {counter: 1} })
MongoServerError: Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('62d304384ca23db6dd87d2c6')} has the field 'counter' of non-numeric type string
test> db.trx.find()
[
  {
    _id: ObjectId("62d304384ca23db6dd87d2c4"),
    x: 1,
    name: 'Old',
    counter: 2
  },
  {
    _id: ObjectId("62d304384ca23db6dd87d2c5"),
    x: 2,
    name: 'Old',
    counter: 3
  },
  {
    _id: ObjectId("62d304384ca23db6dd87d2c6"),
    x: 3,
    name: 'Kate',
    counter: 'Str'
  }
]
test> 

@fcoury
Copy link
Owner Author

fcoury commented Jul 16, 2022

We might need to have a streaming update:

  1. retrieve all the matching rows for the query part of the update
  2. get next row
  3. run all the updates for the row wrapped on a transaction
  4. if an error occurs rollback and continue

@fcoury
Copy link
Owner Author

fcoury commented Jul 16, 2022

OK, this keeps getting more interesting:

test> db.trx.insertMany([
  {x: 1, name: 'John', counter: 1}, 
  {x: 2, name: 'Alex', counter: 'Str'}, 
  {x: 3, name: 'Kate', counter: 3}
])
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("62d305c44ca23db6dd87d2c7"),
    '1': ObjectId("62d305c44ca23db6dd87d2c8"),
    '2': ObjectId("62d305c44ca23db6dd87d2c9")
  }
}
test> db.trx.updateMany({}, { $set: {name: 'Old'}, $inc: {counter: 1} })
MongoServerError: Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('62d305c44ca23db6dd87d2c8')} has the field 'counter' of non-numeric type string
test> db.trx.find()
[
  {
    _id: ObjectId("62d305c44ca23db6dd87d2c7"),
    x: 1,
    name: 'Old',
    counter: 2
  },
  {
    _id: ObjectId("62d305c44ca23db6dd87d2c8"),
    x: 2,
    name: 'Alex',
    counter: 'Str'
  },
  {
    _id: ObjectId("62d305c44ca23db6dd87d2c9"),
    x: 3,
    name: 'Kate',
    counter: 3
  }
]

So, here's how this should take place:

  1. retrieve all the matching rows for the query part of the update
  2. get next row
  3. run all the updates for the row wrapped on a transaction
  4. if an error occurs rollback and abort further updates

@fcoury fcoury added the enhancement New feature or request label Jul 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant