SQL Server 2017 came with a couple of enhancements regarding Always On Availability Groups. For example, we can now specify the minimum number of secondary replicas that need to have written the transaction data to their log before the primary replica commits. But the most radical change came with the introduction of “Read-scale availability groups” or the support for Availability Groups without an underlying cluster.
Prior to SQL Server 2017, an Always On Availability Group required WSFC when running on Windows Server and Pacemaker when running on Linux. Over the past years I came across a couple of situations where this condition has proved to be a true blocking factor. The most first scenario that pops to mind is offloading data to multiple distributed servers where you need a readable copy for reporting purposes. This is where Read-Scale Availability groups enter the playground!
Naturally the absence of a cluster comes with a cost. To begin you must realize that clusterless AG’s should not be seen as a high availability or disaster recovery solution. It merely provides a new mechanism to synchronize databases across multiple servers. In traditional availability groups the cluster is responsible for the monitoring of the underlying infrastructure, detecting imminent failures and coordinating automatic failovers. Therefore, only manual failover without data loss and forced failover with data loss is possible when using Read-Scale availability groups.
Read-scale availability groups support read-only routing and thus by extension spreading the read-only workload using round-robin. This makes the technology perfect for the spreading of read-only workload across multiple secondary replica’s. Note though that since there is no cluster, you can only use the primary node’s IP address as a (dummy) listener. The reason for this is that normally the listener is a computer object in AD, maintained by the cluster as a cluster resource. This means that in case of a manual failover, you will need to drop and recreate the listener on your new primary replica. This proves again that Read-scale availability groups should not be seen as a HA or DR solution.
But enough of the theoretical chitchat, it’s time for some action!
For my test I’ve set up two Windows Server 2016 VMs, both aren’t joined to any domain (I was lazy and I didn’t want to set up a domain, I used certificates instead 😊). Using the SQL Server Configuration Manager you must first enable the AG feature on all the instances you want to add to your AG. Since the machines aren’t joined to any cluster, it normally wouldn’t be possible to enable AG. But as you can see below, I managed to enabled AlwaysOn Availability Groups without any issue.
Next, use the following code to create your Read-Scale Availability Group, in my case ‘ClusterlessAG’. Notice the parameter ‘CLUSTER_TYPE’, you must set this to ‘NONE’. With this option you specify you wish to create the AG without an underlying WSFC or Pacemaker. Always set failover mode to manual, automatic failover is not possible since we don’t have a cluster.
Finally, join the secondary replica to the AG using the parameter ‘CLUSTER_TYPE = NONE‘. And now your Read-Scale Availability Group is finished!
Note: Since I used certificates I had to manually prepare the database and join it to the AG.
If you want to enable Read-Only routing you must first create a listener. Use the local IP address of your primary replica. You will not be able to use the listener, but it’s necessary to enable Read-Only routing. As mentioned before, when performing a manual failover, you must drop and recreate the listener using the local IP address of your new primary replica.
Finally create the routing URLs for both instances and specify the routing lists as you would do on a regular AG.
And that’s all there is folks! As you could see, it’s very straightforward to configure a Read-scale Availability Group. The most important thing to remember is that this technology wasn’t designed to be used as high availability or disaster recovery solution. But nevertheless, it’s a fantastic feature when used for its correct purpose!
© 2023 Kohera
Crafted by
© 2022 Kohera
Crafted by
Cookie | Duration | Description |
---|---|---|
ARRAffinity | session | ARRAffinity cookie is set by Azure app service, and allows the service to choose the right instance established by a user to deliver subsequent requests made by that user. |
ARRAffinitySameSite | session | This cookie is set by Windows Azure cloud, and is used for load balancing to make sure the visitor page requests are routed to the same server in any browsing session. |
cookielawinfo-checkbox-advertisement | 1 year | Set by the GDPR Cookie Consent plugin, this cookie records the user consent for the cookies in the "Advertisement" category. |
cookielawinfo-checkbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checkbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
CookieLawInfoConsent | 1 year | CookieYes sets this cookie to record the default button state of the corresponding category and the status of CCPA. It works only in coordination with the primary cookie. |
elementor | never | The website's WordPress theme uses this cookie. It allows the website owner to implement or change the website's content in real-time. |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Cookie | Duration | Description |
---|---|---|
__cf_bm | 30 minutes | Cloudflare set the cookie to support Cloudflare Bot Management. |
pll_language | 1 year | Polylang sets this cookie to remember the language the user selects when returning to the website and get the language information when unavailable in another way. |
Cookie | Duration | Description |
---|---|---|
_ga | 1 year 1 month 4 days | Google Analytics sets this cookie to calculate visitor, session and campaign data and track site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognise unique visitors. |
_ga_* | 1 year 1 month 4 days | Google Analytics sets this cookie to store and count page views. |
_gat_gtag_UA_* | 1 minute | Google Analytics sets this cookie to store a unique user ID. |
_gid | 1 day | Google Analytics sets this cookie to store information on how visitors use a website while also creating an analytics report of the website's performance. Some of the collected data includes the number of visitors, their source, and the pages they visit anonymously. |
ai_session | 30 minutes | This is a unique anonymous session identifier cookie set by Microsoft Application Insights software to gather statistical usage and telemetry data for apps built on the Azure cloud platform. |
CONSENT | 2 years | YouTube sets this cookie via embedded YouTube videos and registers anonymous statistical data. |
vuid | 1 year 1 month 4 days | Vimeo installs this cookie to collect tracking information by setting a unique ID to embed videos on the website. |
Cookie | Duration | Description |
---|---|---|
ai_user | 1 year | Microsoft Azure sets this cookie as a unique user identifier cookie, enabling counting of the number of users accessing the application over time. |
VISITOR_INFO1_LIVE | 5 months 27 days | YouTube sets this cookie to measure bandwidth, determining whether the user gets the new or old player interface. |
YSC | session | Youtube sets this cookie to track the views of embedded videos on Youtube pages. |
yt-remote-connected-devices | never | YouTube sets this cookie to store the user's video preferences using embedded YouTube videos. |
yt-remote-device-id | never | YouTube sets this cookie to store the user's video preferences using embedded YouTube videos. |
yt.innertube::nextId | never | YouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen. |
yt.innertube::requests | never | YouTube sets this cookie to register a unique ID to store data on what videos from YouTube the user has seen. |
Cookie | Duration | Description |
---|---|---|
WFESessionId | session | No description available. |