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实现只读路由的更多相关文章

  1. SQL 2012 alwayson设置只读路由

    ALTER AVAILABILITY GROUP [sqlmaxiangqianbd]  MODIFY REPLICA ON   N'maxiangqian1' WITH   (SECONDARY_R ...

  2. sql server alwayson 可用性组 只读路由的设置

    昨天晚上学习了[SQL Server 2012实施与管理实战指南]的第三章,于是今天想在前段时间建的那个alwayson 可用性组测试环境上也配置一下只读路由,尝试实现读写分离. 按照书中的方法,执行 ...

  3. SQL Server Alwayson配置两个节点加共享文件夹仲裁见证

    标签:MSSQL/节点和共享文件夹多数 概述 之前讲过多数节点的仲裁配置,多数节点一般3个节点以上的奇数个节点:常见的是使用3个节点节点多了也是浪费因为Alwayson的只读路由只能利用到一个只读副本 ...

  4. SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)

    因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分.而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建. 三篇文章各自的链接: SQL Server ->> ...

  5. 虚IP解决程序连只读服务器故障漂移

    目前公司有一套核心交易数据库配置了AlWaysON,SQL 2012版本, 1主4从, 其从库(8,14, 8.15) 这2台只读的从数据库服务器, 后台程序和wms等很多程序,都是直接配置IP连接这 ...

  6. 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)

    从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://w ...

  7. (转) 从0开始搭建SQL Server AlwaysOn 第三篇(配置AlwaysOn)

    原文地址: http://www.cnblogs.com/lyhabc/p/4682986.html 这一篇是从0开始搭建SQL Server AlwaysOn 的第三篇,这一篇才真正开始搭建Alwa ...

  8. SQL Server AlwaysOn

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/高性能解决方案 概述 环境: 域服务器:windows server 2008 R2 SP1,192.168.2.10 DNS:1 ...

  9. [AlwaysOn Availability Groups]排查:AG配置

    排查AG配置 本文主要用来帮助排查在AG配置时出现的问题,包括,AG功能被禁用,账号配置不正确,数据库镜像endpoint不存在,endpoint不能访问. Section Description A ...

随机推荐

  1. Java中的IP对象以及本地域名解析

    本地域名解析操作步骤: 1.打开C:\WINDOWS\system32\drivers\etc目录 2.找到host文件,用记事本打开 3.添加“空间IP  域名” package WebProgra ...

  2. 备份数据表为insert 脚本

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  3. 将NavigationBar设置透明

    将NavigationBar设置透明(仅将指定视图控制器进行透明处理),步骤如下:1.在视图控制器的头文件中实现UINavigationControllerDelegate,例如:@interface ...

  4. 在CentOS 6.2上安装 MemcacheQ 最新版

    1.      安装 yum install gcc cc make libevent libevent-devel 2.      安装Berkeley DB 下载:http://www.oracl ...

  5. web.xml(spring/spring mvc/hibernate)

    <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" ...

  6. CentOS6.5安装telnet

    原文地址:http://www.cnblogs.com/zhongshengzhen/ 1.检查是否已经安装telnet [root@localhost ~]# rpm -qa | grep teln ...

  7. SQLite 使用教程2 语法

    http://www.runoob.com/sqlite/sqlite-syntax.html SQLite 语法 SQLite 是遵循一套独特的称为语法的规则和准则.本教程列出了所有基本的 SQLi ...

  8. Windows 7 EXE图标丢失修复方法

    有过Win7下的一些EXE文件图标莫名奇妙丢失,但功能却正常的情况吗?这是图标缓存的问题,应该是Win7的bug. 在命令提示符下输入下列命令即可恢复. 以下是代码片段: taskkill /im e ...

  9. javascript 递归之阶乘

    阶乘,即5! = 5*4*3*2*1, 先看传统的做法,利用while循环实现: function factorial(num){ var result = num; if(num<0){ re ...

  10. IPVS

    http://kb.linuxvirtualserver.org/wiki/IPVS_FULLNAT_and_SYNPROXY