AlwaysOn实现只读路由
1.配置只读路由
①配置A副本的只读路由属性(ReadOnly代表‘只读意向’)
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO1' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
②配置A副本的只读路由URL
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO1' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'tcp://WIN-14VNU7CGQO1.fnst.com:1433'));
③配置B副本的只读路由属性
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO2' WITH (SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY));
④配置B副本的只读路由URL
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO2' WITH (SECONDARY_ROLE (READ_ONLY_ROUTING_URL = N'tcp://WIN-14VNU7CGQO2.fnst.com:1433'));
⑤配置A副本作为主副本时候的只读路由表
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO1' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('WIN-14VNU7CGQO2','WIN-14VNU7CGQO1')));
⑥配置B副本作为主副本时候的只读路由表
ALTER AVAILABILITY GROUP [testAG]
MODIFY REPLICA ON N'WIN-14VNU7CGQO2' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('WIN-14VNU7CGQO1','WIN-14VNU7CGQO2')));
配置完成后:使用 SELECT * FROM sys.availability_read_only_routing_lists 查看路由表

确认一下应该是下面的形式 :
A B
A A
B A
B B
为什么这么配置请分析如下过程
1.正常运行时候,A作为主副本,B作为辅助副本,客户端连接字符串指定数据源是侦听器地址
2.此时发送只读请求
3.侦听器收到只读数据请求,有主副本A来处理,主副本A发现是ReadOnly,就查询路由表,发现第一条符合,就把只读请求交给辅助副本B来处理
4.此时主副本A失效了,那么由AlwaysOn的高可用可知,会让辅助B作为了主副本,等原来的主副本A恢复之后,让A成为新的辅助副本(当然这些对客户端是透明的)
5.副本A恢复之后,再发送一条只读请求
6.此时侦听器使用主副本B来处理这个请求,如果不像上面的设置方法,就找不到B到A的路由,也就不能实现所谓的高可用
2.配置的确认
例如:有一个可用组testAG,其中有两个副本A和B,其中主副本为A,辅助副本为B,并且在AlwaysOn可用组内设定了Listener

A和B的配置如下:

3.测试只读路由
客户端程序中指定连接字符串:connectStr = "Data Source=tcp:193.160.26.30,1433;Initial Catalog=test;Integrated Security=True;ApplicationIntent=ReadOnly;MultiSubnetFailover=True";
重要参数说明:
DataSource:tcp:193.160.26.30,1433 这个填写的是侦听器的地址
ApplicationIntent=ReadOnly 说明这个连接是一个只读意向的连接,这样的情况下,请求发送到主副本A上,主副本发现是只读的请求会先产看只读路由表,然后通过
主副本A转发到辅助副本B上
会出现的问题: 如果客户端这时候的连接字符串指定了ApplicationIntent=ReadOnly,它只表明这是一个只读意向的请求,但是不能保证请求一点是只读的,如果是写请求
就会出现失败的情况。所以在进行写操作的时候不能设置这个选项。
测试程序如下:

主副本: 192.168.24.28
辅助副本:192.168.24.32
侦听器:192.168.24.30:1433
代码如下:
namespace AlwaysonTest
{
public partial class Form1 : Form
{ public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
} private void btnInsert_Click(object sender, EventArgs e)
{ Thread t = new Thread(Write);
t.IsBackground = true;
t.Start(); } private void btnReadData_Click(object sender, EventArgs e)
{ Thread t = new Thread(Read);
t.IsBackground = true;
t.Start();
} public void Write()
{
string name = System.DateTime.Now.ToString();
//插入数据的时候,连接字符串不指定ReadOnly
string connectStrW = "Data Source=tcp:193.160.26.30,1433;Initial Catalog=test;Integrated Security=True;MultiSubnetFailover=True"; int count = Convert.ToInt32(textBox4.Text); using (SqlConnection conn = new SqlConnection(connectStrW))
{
for (var i = ; i <= count; i++)
{
conn.Open();//打开数据库
//创建数据库命令
SqlCommand cmd = conn.CreateCommand();
//创建查询语句 在写的操作过程中,写之前先读操作,测试不加ReadOnly时候只读路由有没有效果
cmd.CommandText = "select count(*) from test1";
int x = (int)cmd.ExecuteScalar();
//创建查询语句 Thread.Sleep();
cmd.CommandText = "Insert into test1 values" + '(' + '\'' + name + '\'' + ')';
cmd.ExecuteNonQuery();
textBox1.Text = (x + i).ToString();
conn.Close();
}
} } public void Read()
{ //查询数据的时候,连接字符串指定ReadOnly
string connectStr = "Data Source=tcp:193.160.26.30,1433;Initial Catalog=test;Integrated Security=True;ApplicationIntent=ReadOnly;MultiSubnetFailover=True"; int count = Convert.ToInt32(textBox4.Text); for (var j = ; j <= count; j++)
{
Thread.Sleep();
using (SqlConnection conn = new SqlConnection(connectStr))
{
conn.Open();//打开数据库
//创建数据库命令
SqlCommand cmd = conn.CreateCommand();
//创建查询语句
cmd.CommandText = "select count(*) from test1";
int x = (int)cmd.ExecuteScalar();
textBox2.Text = x.ToString();
conn.Close();
}
} } }
}
检测结果:
开始之前,打开Sql Server Profiler进行数据的分析。
如下图所示,为了排除干扰,发现程序执行前是没有数据的读写的。

测试点一: 写操作不加ReadOnly限制,是不是能够在主副本写成功
结果如下图,

结论:因为只有主副本有操作记录,可以说明是在主副本进行写入成功的
测试点二:读操作加上ReadOnly限制,它的处理副本是主副本还是辅助副本(清除上次记录)
结果如下图:

结论:左侧主副本的内容和我们的查询内容无关,右侧辅助副本全部都是我们的查询操作,所以可以证明存在ReadOnly的时候读操作都被辅助副本执行
测试点三:读操作不加ReadOnly限制,它的处理副本是主副本还是辅助副本
Read()操作中连接字符串去掉ApplicationIntent=ReadOnly,并清空上面操作信息,然后执行程序

结论:在不加ReadOnly选项的时候,读操作全部有主副本进行了处理
测试点四:写操作加上ReadOnly限制,能够被主副本进行处理
在Write()中连接字符串中加上ApplicationIntent=ReadOnly,清空上面操作记录,执行程序

结论:上图可以知道,在写操作的时候,如果有ReadOnly会报错
AlwaysOn实现只读路由的更多相关文章
- SQL 2012 alwayson设置只读路由
ALTER AVAILABILITY GROUP [sqlmaxiangqianbd] MODIFY REPLICA ON N'maxiangqian1' WITH (SECONDARY_R ...
- sql server alwayson 可用性组 只读路由的设置
昨天晚上学习了[SQL Server 2012实施与管理实战指南]的第三章,于是今天想在前段时间建的那个alwayson 可用性组测试环境上也配置一下只读路由,尝试实现读写分离. 按照书中的方法,执行 ...
- SQL Server Alwayson配置两个节点加共享文件夹仲裁见证
标签:MSSQL/节点和共享文件夹多数 概述 之前讲过多数节点的仲裁配置,多数节点一般3个节点以上的奇数个节点:常见的是使用3个节点节点多了也是浪费因为Alwayson的只读路由只能利用到一个只读副本 ...
- SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)
因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分.而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建. 三篇文章各自的链接: SQL Server ->> ...
- 虚IP解决程序连只读服务器故障漂移
目前公司有一套核心交易数据库配置了AlWaysON,SQL 2012版本, 1主4从, 其从库(8,14, 8.15) 这2台只读的从数据库服务器, 后台程序和wms等很多程序,都是直接配置IP连接这 ...
- 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://w ...
- (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)
原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...
- SQL Server AlwaysOn
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/高性能解决方案 概述 环境: 域服务器:windows server 2008 R2 SP1,192.168.2.10 DNS:1 ...
- [AlwaysOn Availability Groups]排查:AG配置
排查AG配置 本文主要用来帮助排查在AG配置时出现的问题,包括,AG功能被禁用,账号配置不正确,数据库镜像endpoint不存在,endpoint不能访问. Section Description A ...
随机推荐
- RPI-Wireless-Hotspot
http://elinux.org/RPI-Wireless-Hotspot What does it do? This project configures your Raspberry Pi to ...
- work2
回答问题: 描述在这么多相似的需求面前, 你怎么维护你的设计 (父类/子类/基类, UML, 设计模式, 或者其它方法) 让整个程序的架构不至于崩溃的? 答:诚然,问题给出了很多选项如-a,-v,- ...
- 集合框架Map之entrySet方法的使用
Map的entrySet函数的使用,取得是键和值的映射关系,Entry就是Map接口中的内部接口,类似与我们熟悉的内部类一样,内部类定义在外部类内部,可以直接访问到外部类中的成员 package cn ...
- Android实例-程序界面内截取屏幕(XE8+小米2)
结果: 1.只能截取程序界面内的图片. 2.图片有点不清楚,自己设置清楚度. 实例代码: unit Unit1; interface uses System.SysUtils, System.Type ...
- hdoj 1799 循环多少次?
循环多少次? Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- WinForm中当TextBox重新获得焦点时输入法失效问题
在winform 中,每当TextBox获得焦点时,部分输入法会失效(如智能ABC.五笔98.极品五笔等),需要重新切换输入法才能正常使用. 此时要将Form的ImeMode属性改为:OnHalf(或 ...
- [iOS基础控件 - 3.5] NSBundle, UIImageView和UIButton的区别, 模拟器和文档
1.NSBundle1> 一个NSBundle代表一个文件夹,利用NSBundle能访问对应的文件夹2> 利用mainBundle就可以访问软件资源包中的任何资源3> 模拟器应用程序 ...
- c# sql连接数据库
using System.Data.SqlClient; private static string connectionString ="Data Source=.\\HS;Initial ...
- 第1组UI组件:布局管理器
1 布局管理的来源 为了让UI在不同的手机屏幕上都能运行良好----不同手机屏幕的分辨率/尺寸并不完全相同,如果让程序手动控制每个组件的大小.位置,会给编程带来巨大的麻烦.为了解决这个问题.andro ...
- MySQL中UNION和UNION ALL的使用
在数据库中,UNION和UNION ALL关键字都是将两个结果集合并为一个,但这两者从使用和效率上来说都有所不同. MySQL中的UNION UNION在进行表链接后会筛选掉重复的记录,所以在表链接后 ...