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

add full-rollback option for production migrations #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Mikulas
Copy link
Contributor

@Mikulas Mikulas commented Jul 17, 2015

Usecase: running migrations during deploy should not alter the database at all. It is however handy to only rollback the last migration during development, so the original behaviour is retained.

Side effect: migrations are committed at once, not per single migration.
Also affects original continue mode, not just full rollback mode.
Original behaviour could have caused (very edge case) transient problems during deploy if one of the migrations introduced an back incompatible error fixed in another migration queued for execution and an application query was run in that time.

Review on Reviewable

@hrach
Copy link
Member

hrach commented Jul 17, 2015

I see it practically useless since alter of database commits the transaction automatically (edit: and immidiately). But I may be missing some point, since I don't get it all.

@JanTvrdik
Copy link
Member

Why not make rollbacking all migrations a default behavior?

@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 17, 2015

It is however handy to only rollback the last migration during development, so the original behaviour is retained.

Also because rolling schema changes is not supported in mysql. I feel safer introducing it as a opt-in feature.

@hrach
Copy link
Member

hrach commented Jul 17, 2015

Yes, of course Postgre is about sth another. Personally, I am ok with switch, but I see two important facts:

  • migrations & deployment are two different things, assumption, that migrations in productions are connected with deployment is very likely, but they are still two different things.
  • we emphasize the difference between mysql & postgresql.


} else if ($mode === self::MODE_CONTINUE) {
// commit migrations not including the failing one
$this->driver->commitTransaction();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably wrong. It migrations contains more sqls and only the last one is wrong (throws exception), all previous queries are commited, aren't they?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've retained original transactions that wrap single file. This should only affect the new outer one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are actually right; this won't work with mysql (because it has terrible support for nested transactions). I will have to rewrite this for other than postgres driver which I initially had in mind when implementing this.

@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 17, 2015

migrations & deployment are two different things, assumption, that migrations in productions are connected with deployment is very likely, but they are still two different things.

Not sure I get your point. I'm just saying this full rollback would mostly be useful for deployment, but there is no implied connection.

we emphasize the difference between mysql & postgresql.

Fair enough. I'm having troubles correcting tests for mysql anyway, so what if I enabled this mode for postgres only? Throwing during args parsing if driver is mysql and full-rollback is on.

@hrach
Copy link
Member

hrach commented Jul 17, 2015

Not sure I get your point. I'm just saying this full rollback would mostly be useful for deployment, but there is no implied connection.

Sorry, I was under impression that '--production' switch in symfony commands will force this option.

@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 17, 2015

Ok I believe I'm done. Tests should be passing now; hhvm errored on packagist timeout or something.

@hrach
Copy link
Member

hrach commented Jul 17, 2015

I rerun the hhvm buil, we will see :)

@Mikulas Mikulas force-pushed the full-rollback branch 4 times, most recently from ea75d6b to 084163a Compare July 19, 2015 16:17
@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 19, 2015

Packagist:
rage_4

@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 19, 2015

So the tests work now, this pull request seems to introduce no regression. Neither did c184cf1 but it broke hhvm build https://travis-ci.org/nextras/migrations/jobs/71658822

@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 19, 2015

Turns out 084163a is not required and the same problem can be fixed by #20

Usecase: running migrations during deploy should not alter the database
at all. It’s handy to only rollback the last migration during
development, so the original behaviour is retained.

Side effect: migrations are committed at once, not per single migration.
Also affects original continue mode, not just full rollback mode.
Original behaviour could have caused transient problems during deploy.
@Mikulas
Copy link
Contributor Author

Mikulas commented Jul 19, 2015

I took the liberty on rebasing this on #21 so the tests are passing. (Original ref is 5f61fdc)

@hrach
Copy link
Member

hrach commented Jul 19, 2015

@Mikulas feel free to rebase again :)
@JanTvrdik, please review it and merge! I'm ok with this. :)

@hrach
Copy link
Member

hrach commented Jul 19, 2015

@Mikulas one other thing: probably you could try to enhace our doc to mention it :))

@hrach
Copy link
Member

hrach commented Aug 1, 2015

Btw, http://www.postgresql.org/docs/9.5/static/transaction-iso.html

Important: Some PostgreSQL data types and functions have special rules regarding transactional behavior. In particular, changes made to a sequence (and therefore the counter of a column declared using serial) are immediately visible to all other transactions and are not rolled back if the transaction that made the changes aborts. See Section 9.16 and Section 8.1.4.

@Mikulas
Copy link
Contributor Author

Mikulas commented Aug 1, 2015

If I remember the doc correctly, that should only mean that incrementing the sequence is immediately published so no two transactions try to insert two same values. Sequence provides unique values that are not necessarily–contrary to the name–in sequence.

Edit: yeah found it:

http://www.postgresql.org/docs/9.5/static/functions-sequence.html
Important: To avoid blocking concurrent transactions that obtain numbers from the same sequence, a nextval operation is never rolled back; that is, once a value has been fetched it is considered used, even if the transaction that did the nextval later aborts. This means that aborted transactions might leave unused "holes" in the sequence of assigned values.

You are correct that setval might break transactions. It's documented behaviour though so no developer should be surprised if it's not rolled back.

@hrach
Copy link
Member

hrach commented Aug 1, 2015

Well, this is vailid also for setval, so the rollback will never be 100% reliable for all possible migrations.

@Mikulas
Copy link
Contributor Author

Mikulas commented Aug 1, 2015

Yep I agree, but it's documented, so whoever uses the function should know it'll break. Using setval in migrations seems like bad practice anyway.

Anyway, I still have to write failing tests for mysql and then fix the code. Current implementation relies on nesting transactions which is apparently something mysql can't handle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants