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

Disable automatic write protection on replicas #42450

Merged
merged 1 commit into from
Jun 16, 2021

Conversation

HParker
Copy link
Contributor

@HParker HParker commented Jun 10, 2021

This allows users to use write protection if they want, but no longer treats it as a catch all. Write protection is not accurate enough to classify all cases correctly. Instead users should configure their replicas to not allow writes and rely on the database erroring if the query is not allowed.

Alternative solution for: #42432
Fixes: #42432

@HParker HParker marked this pull request as ready for review June 10, 2021 23:36
@ghiculescu
Copy link
Member

I am in favor of this. Is there any other reason for rails to know if the db is a replica? If not, I imagine you can remove a fair bit more code.

@zzak zzak requested a review from eileencodes June 11, 2021 01:03
@eileencodes
Copy link
Member

Is there any other reason for rails to know if the db is a replica? If not, I imagine you can remove a fair bit more code.

Yes, we need to know a configuration is a replica so that we don't run rake tasks against it. I don't think offhand there is any other code to remove since we're not dropping replica support, just dropping the automatic prevent_writes from it.

prevent_writes was designed for the case where you're sending read queries to your primary and want to make sure they behave similarly to a replica. For example if you're using the auto switcher middleware you dont want your GET requests to have any writes in them (without switching to writing) because when it goes to the replica it won't write. To make GET's going to the primary and replica behave the same, we added this functionality.

Copy link
Member

@eileencodes eileencodes left a comment

Choose a reason for hiding this comment

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

Thanks Adam! This also needs a changelog entry.

activerecord/test/cases/base_test.rb Show resolved Hide resolved
@HParker HParker force-pushed the disable-prevent-write-on-replica branch 2 times, most recently from 42cfc1f to eca7582 Compare June 11, 2021 15:21
* Disable automatic write protection on replicas

Write protection no longer automatically enable for replicas.
Now each application controls when to enable automatic write protection.
Copy link
Member

Choose a reason for hiding this comment

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

Do you think it's worth mentioning this on https://edgeguides.rubyonrails.org/active_record_multiple_databases.html too?

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 am reading now, if it was mentioned before we should probably remove it, but I don't know how/if we should mention rails not doing something you maybe didn't know it did at all before.

Copy link
Member

Choose a reason for hiding this comment

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

I had a quick read through and couldn't find any mention of this behaviour. I think AR.while_preventing_writes could be mentioned but it's not really in the scope of this PR.

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 can't find a spot that seems like it needs updating, but it is totally possible I am missing it. Let me know if I missed anything @ghiculescu 🙂

Copy link
Member

Choose a reason for hiding this comment

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

I would add onto the guides and explain that if you want replicas to act like replicas they need to be configured with readonly users

Copy link
Member

Choose a reason for hiding this comment

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

^ that is alluded to, kind of

image

@HParker I'll make a separate PR, because I don't think I'm making much sense here.

Copy link
Contributor Author

@HParker HParker Jun 11, 2021

Choose a reason for hiding this comment

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

Under the setup section we have:

Second, the username for the writers and replicas should be different, and the replica user's permissions should be set to only read and not write.

When using a replica database, you need to add a replica: true entry to the replica in the database.yml. This is because Rails otherwise has no way of knowing which one is a replica and which one is the writer.

https://edgeguides.rubyonrails.org/active_record_multiple_databases.html#setting-up-your-application

Should I expand on that?

Copy link
Member

Choose a reason for hiding this comment

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

@ghiculescu
Copy link
Member

Just noticed this line: https://github.com/rails/rails/blob/eca7582718225ef40a7618293a13924561194aae/activerecord/lib/active_record/connection_handling.rb#L355. Should it also be removed? It gets called by connected_to; the equivalent line in connected_to_many has been removed.

@HParker
Copy link
Contributor Author

HParker commented Jun 11, 2021

Thanks @ghiculescu that line in connection_handling turned up a lot of places I missed ❤️

@HParker HParker force-pushed the disable-prevent-write-on-replica branch 4 times, most recently from 16034e2 to 5d47eb3 Compare June 15, 2021 15:38
@zzak zzak requested a review from eileencodes June 16, 2021 01:59
Copy link
Member

@eileencodes eileencodes left a comment

Choose a reason for hiding this comment

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

I think the CHANGELOG can be clearer - but once that's fixed and the conflicts are resolved this looks good to me 👍🏼

@@ -1,3 +1,10 @@
* Disable automatic write protection on replicas
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Disable automatic write protection on replicas
* Disable automatic write protection on replicas.

@@ -1,3 +1,10 @@
* Disable automatic write protection on replicas

Write protection no longer automatically enable for replicas.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Write protection no longer automatically enable for replicas.
Write protection is no longer automatically enabled for replicas. Write protection should be enabled by the database user settings.

* Disable automatic write protection on replicas

Write protection no longer automatically enable for replicas.
Now each application controls when to enable automatic write protection.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Now each application controls when to enable automatic write protection.

This allows users to use write protection if they want, but no longer treats it as a catch all. Write protection is not accurate enough to classify all cases correctly. Instead users should configure their replicas to not allow writes and rely on the database erroring if the query is not allowed.

Co-authored-by: Alex Ghiculescu <alexghiculescu@gmail.com>
@HParker HParker force-pushed the disable-prevent-write-on-replica branch from 5d47eb3 to 951deec Compare June 16, 2021 11:31
@HParker
Copy link
Contributor Author

HParker commented Jun 16, 2021

Thanks @eileencodes! updated

@eileencodes eileencodes merged commit 25292a3 into rails:main Jun 16, 2021
@@ -1,3 +1,9 @@
* Disable automatic write protection on replicas.

Write protection is no longer automatically enabled for replicas. Write protection should be enabled by the database user settings.
Copy link
Member

Choose a reason for hiding this comment

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

Can we expand with an example what "Write protection should be enabled by the database user settings." means?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea @rafaelfranca, I put together #42529

I am not sure how much detail to add since it is not only database specific, but also configuration specific. Depending on how your primary and replica are setup you might want a totally different configuration. Ideally you would setup a local database user to be very similar to how your production users are setup.

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

Successfully merging this pull request may close these issues.

Blank query can't be executed on a readonly database connection
4 participants