分布式数据库系统:在逻辑上是一个整体,在物理上数据存储在不通的物理节点上.
因为各实例在逻辑上是一个整体,所以各节点要能互相访问(通过通信网络实现逻辑上的一个整体),
在数据库系统内部,各实例通过链接服务器进行通信交互
链接服务器可以访问远程服务器(包括异类数据源),依此实现分布式的命令和事务.
通过sp_addlinkedserver创建链接服务器
通过sp_addlinkedsrvlogin创建本地SQL Server实例上的登录与链接服务器上远程登录之间的映射
通过sp_dropserver删除链接服务器
通过sp_droplinkedsrvlogin删除本地SQL Server实例上的登录与链接服务器上远程登录之间的映射
在删除链接服务器时先删除相关的登录映射再删除链接服务器
以下命令是在本地实例上创建名为remoteLink的链接服务器,远程数据库服务器的IP为192.168.72.128
exec sp_addlinkedserver
@server='remoteLink'
,@provider='SQLNCLI'
,@srvproduct=''
,@datasrc='192.168.72.128'
以下命令为remoteLink链接服务器创建远程登录映射
exec sp_addlinkedsrvlogin
@rmtsrvname = 'remoteLink'
,@useself = 'false'
, @locallogin = null
, @rmtuser = 'sa'
, @rmtpassword = '123456'
以下命令删除链接服务器remoteLink对应的SA账号登录映射
sp_droplinkedsrvlogin 'remoteLink','sa'
以下命令删除链接服务器remoteLink(在删除链接服务器前需要将链接服务器对应的登录映射全部删除)
sp_dropserver 'remoteLink'
在本地实例上引用对远程实例上的对象,必须使用全名称引用:连接服务器.数据库.所有者.对象
以下命令查询链接服务器remoteLink上的DistributedTest数据库里的test表的数据
select * from remoteLink.DistributedTest.dbo.test
可以通过create synonym为连接服务器创建别名
以下命令为链接服务器器remoteLink上的DistributedTest数据库里的test表创建别名remoteLinkTest
create synonym remoteLinkTest for remoteLink.DistributedTest.dbo.test
通过别名完成上面的查询:select * from remoteLinkTest
以下命令删除别名:
drop synonym remoteLinkTest
分布式事务需要操作系统的MSDTC组件的支持.
一下是相关配置步骤:
1.启动Distributed Transaction Coordinator服务
2.配置DTC安全设置:打开"管理工具"-->"组件服务"-->"计算机",在"我的电脑"上点击右键在"MSDTC选项卡"中,点击"安全配置"按钮
3.选中"网络DTC访问"
在"客户端管理"中选中"允许远程客户端","允许远程管理"
在"事务管理通讯"中选中"允许入站","允许出站","不要求进行验证"
选中"启用 XA 事务"
4.确保DTC登录账户为:NT AUTHORITY/NetworkService
5.确保135端口启用(注意防火墙的设置)
6.设置好后重启电脑
注意:相关机器一定要能互相访问
以下命令完成一次分布式事务操作:
set xact_abort on
begin distributed transaction
begin try
update remotelink.distributedtest.dbo.test set code=0
commit transaction
end try
begin catch
rollback transaction
select ERROR_MESSAGE()
end catch
分布式分区视图可以将来自一个或多个SQL Server数据库实例中的数据连接起来.使分布在不通实例上的数据形成一个逻辑整体.
(各成员表通过union all合并数据,如果使用了远程实例,则通过链接服务器引用远程实例)
分区视图的各成员表必须包含一个CHECK约束列(分区列),CHECK约束列作为主键的一部分,则可以通过分区视图进行更新,否则需要创建
对应的触发器完成相应的操作.
注意:分区列必须是表的PRIMARY KEY的一部分,分区列不能是计算列、标识列、默认列或timestamp列.
以下命令创建分区试图的成员表game_doudizhu:
create table game_doudizhu
(
record_id uniqueidentifier not null,
game_id nvarchar(10) not null,
userid int not null,
writetime datetime not null default(getdate()),
constraint pk_game_doudizhu primary key clustered(game_id,writetime) with(ignore_dup_key=off),
constraint ck_game_id check(game_id='doudizhu')
)
以下命令创建分区视图:
create view v_game_record
as
(
select * from game_doudizhu
union all
select * from remotelink.distributedtest.dbo.game_majiang
)
--分别在源服务器和远程服务器上创建测试数据库
create database DistributedTest
go
--在远程数据库实例上创建一下表:
use DistributedTest
go
create table game_majiang
(
record_id uniqueidentifier not null,
game_id nvarchar(10) not null,
userid int not null,
writetime datetime not null default(getdate()),
constraint pk_game_majiang primary key clustered(game_id,writetime) with(ignore_dup_key=off),
constraint ck_game_id check(game_id='majiang')
)
--在本机数据库实例上创建以下表:
use DistributedTest
go
create table game_doudizhu
(
record_id uniqueidentifier not null,
game_id nvarchar(10) not null,
userid int not null,
writetime datetime not null default(getdate()),
constraint pk_game_doudizhu primary key clustered(game_id,writetime) with(ignore_dup_key=off),
constraint ck_game_id check(game_id='doudizhu')
)
go
--在本地数据库上创建远程数据库的链接登录对象
exec sp_addlinkedserver
@server='remoteLink'
,@provider='SQLNCLI'
,@srvproduct=''
,@datasrc='192.168.72.128'
go
exec sp_addlinkedsrvlogin
@rmtsrvname = 'remoteLink'
,@useself = 'false'
, @locallogin = null
, @rmtuser = 'sa'
, @rmtpassword = '123456'
go
--在源数据库使用链接服务器对象查询远程数据库的数据,如果有结果集返回则说明可以在元数据库对远程数据库进行访问
select * from remotelink.distributedtest.dbo.game_majiang
go
--在本机上创建分区视图:
create view v_game_record
as
(
select * from game_doudizhu
union all
select * from remotelink.distributedtest.dbo.game_majiang
)
go
--通过视图插入数据:
insert into v_game_record(record_id,game_id,userid,writetime)
values(NEWID(),'majiang',100,GETDATE())
insert into v_game_record(record_id,game_id,userid,writetime)
select NEWID(),'doudizhu',200,GETDATE()
--通过视图查看数据:
select * from v_game_record
--开启分布式事务插入修改数据:
set xact_abort on
begin distributed transaction
begin try
insert into v_game_record(record_id,game_id,userid,writetime)
values(NEWID(),'majiang',300,GETDATE())
update v_game_record set record_id = newid(),game_id='majiang' where userid= 100
commit transaction
end try
begin catch
rollback transaction
select ERROR_MESSAGE()
end catch