SQL2000发布和复制的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL2000发布和复制的问题相关的知识,希望对你有一定的参考价值。
在数据库 表 结构相同的情况下:
我有4台服务器 A B C 三台要实时或者定时着将数据汇总到 D 服务器上,
快照复制应该不行吧... 是用合并复制呢?还是事物复制呢?应当如何操作?
有具体操作说明的话我会加分的....
Microsoft SQL Server 2000复制的概念:在数据库之间对数据和数据库对象进行复制和分发并进行同步以确保其一致性的一组技术。
使用复制可以将数据分发到不同位置,通过局域网、使用拨号连接、通过 Internet 分发给远程或移动用户。复制还能够使用户提高应用程序性能,根据数据的使用方式物理分隔数据(例如,将联机事务处理 (OLTP) 和决策支持系统分开),或者跨越多个服务器分布数据库处理。
SQL复制的基本元素包括:
发布服务器、订阅服务器、分发服务器、发布、项目。
发布服务器
发布服务器是提供数据以便复制到其它服务器的服务器。发布服务器可以具有一个或多个发布,每个发布代表一组逻辑相关的数据。除了指定其中哪些数据需要复制之外,发布服务器还检测事务复制期间发生更改的数据并维护有关此站点上所有发布的信息。
分发服务器
分发服务器是作为分发数据库宿主并存储历史数据和/或事务以及元数据的服务器。分发服务器的角色根据执行的复制类型而不同。有关更多信息,请参见复制类型。
远程分发服务器是独立于发布服务器并配置为复制的分发服务器的服务器。本地分发服务器是既配置为复制的发布服务器又配置为复制的分发服务器的服务器。
订阅服务器
订阅服务器是接收复制数据的服务器。订阅服务器订阅的是发布而不是发布中分离的项目;并且订阅服务器只订阅其需要的发布,而不是发布服务器上所有可用的发布。根据复制的类型和所选择的复制选项,订阅服务器还可以将数据更改传播回发布服务器或将数据重新发布到其它订阅服务器。
发布
发布是一个数据库中的一个或多个项目的集合。这种多个项目的分组使得指定逻辑相关的一组数据和数据库对象以一起复制变得更容易。
项目
项目是指定要复制的数据表、数据分区或数据库对象。项目可以是完整的表、某几列(使用垂直筛选)、某几行(使用水平筛选)、存储过程或视图定义、存储过程的执行、视图、索引视图或用户定义函数。
订阅
订阅是对数据或数据库对象的复本的请求。订阅定义将接收的发布和接收的时间、地点。订阅的同步或数据分发可以由发布服务器(强制订阅)或订阅服务器(请求订阅)请求。发布可以支持强制订阅和请求订阅的混合。
SQL复制的工作原理
SQL SERVER 主要采用出版物、订阅的方式来处理复制。源数据所在的服务器是出版服务器,负责发表数据。出版服务器把要发表的数据的所有改变情况的拷贝复制到分发服务器分发服务器包含有一个分发数据库,可接收数据的所有改变,并保存这些改变,再把这些改变分发给订阅服务器。
SQL SERVER复制技术类型,三种复制技术,分别是
1、快照复制
2、事务复制
3、合并复制
下介绍实现复制的步骤。(以快照复制为例)
准备工作:
1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户。
--我的电脑
--控制面板
--管理工具
--计算机管理
--用户和组
--右键用户
--新建用户
--建立一个隶属于administrator组的登陆windows的用户
2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作:
我的电脑--D:\ 新建一个目录,名为: PUB
--右键这个新建的目录
--属性--共享
--选择“共享该文件夹”
--通过“权限”按纽来设置具体的用户权限,保证第一步中创建的用户具有对该文件夹的所有权限
--确定
3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置)
开始--程序--管理工具--服务
--右键SQLSERVERAGENT
--属性--登陆--选择“此账户”
--输入或者选择第一步中创建的windows登录用户名
--“密码”中输入该用户的密码
4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置)
企业管理器
--右键SQL实例--属性
--安全性--身份验证
--选择“SQL Server 和 Windows”
--确定
5.在发布服务器和订阅服务器上互相注册
企业管理器
--右键SQL Server组
--新建SQL Server注册。..
--下一步--可用的服务器中,输入你要注册的远程服务器名--添加
--下一步--连接使用,选择第二个“SQL Server身份验证”
--下一步--输入用户名和密码
--下一步--选择SQL Server组,也可以创建一个新组
--下一步--完成
6.对于只能用IP,不能用计算机名的,为其注册服务器别名
(在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP)
开始--程序--Microsoft SQL Server--客户端网络实用工具
--别名--添加
--网络库选择“tcp/ip”--服务器别名输入SQL服务器名
--连接参数--服务器名称中输入SQL服务器ip地址
--如果你修改了SQL的端口,取消选择“动态决定端口”,并输入对应的端口号
正式开始:
1.配置发布服务器
a. 选中指定 〔服务器〕 节点
b. 从 〔工具〕 下拉菜单的 〔复制〕 子菜单中选择 〔发布、订阅服务器和分发〕 命令
c. 系统弹出一个对话框点 〔下一步〕 然后看着提示操作
--直到“指定快照文件夹”
--在“快照文件夹”中输入准备工作中创建的目录: \\《服务器名》\pub
一〔下一步〕 直操作到完成。
d. 当完成了出版服务器的设置以后系统会为该服务器的树形结构中添加一个复制监视器同时也生成一个分发数据库(distribution)
2.创建发布
a. 选中指定的服务器
b. 从 〔工具〕 菜单的 〔复制〕 子菜单中选择 〔创建和管理发布〕 命令。此时系统会弹出一个对话框
c. 选择要创建发布的数据库,然后单击 〔创建发布〕
d. 在 〔创建发布向导〕 的提示对话框中单击 〔下一步〕 系统就会弹出一个对话框。对话
框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个
大家可以去看看帮助)
e. 单击 〔下一步〕 系统要求指定可以订阅该发布的数据库服务器类型,SQLSERVER允许在
不同的数据库如 ORACLE或ACCESS之间进行数据复制。但是在这里我们选择运行
“SQL SERVER 2000”的数据库服务器
f. 单击 〔下一步〕 ,选择要发布的对象(如表,视图,存储过程,一般是表)
g. 然后 〔下一步〕 直到操作完成。当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库。
---------------------------------------------------------------------------
3.设计订阅
a. 选中指定的订阅服务器
b. 从 〔工具〕 下拉菜单中选择 〔复制〕 子菜单的 〔请求订阅〕
c. 按照提示单击 〔下一步〕 操作直到系统会提示检查SQL SERVER代理服务的运行状态,执行
复制操作的前提条件是SQL SERVER代理服务必须已经启动。
d. 单击 〔完成〕 完成订阅操作。
----------------------------------------------------------------------------
完成上面的步骤其实复制也就是成功了。但是如何来知道复制是否成功了呢?
这里可以通过这种方法来快速看是否成功。
展开出版服务器下面的复制——发布内容——右键发布内容——属性——击活——状态然后点立即运行代理程序接着点代理程序属性击活调度
把调度设置为每一天发生,每一分钟,在0:00:00和23:59:59之间。
接下来就是判断复制是否成功了,打开C:\Program Files\Microsoft SQL Server\MSSQL\REPLDATA\unc\XIAOWANGZI_database_database下面,观察是否有一些以时间做为文件名的文件夹(几乎一分中产生一个)。
Firestore 为 noSQL 和 Flutter 复制 SQL 连接
【中文标题】Firestore 为 noSQL 和 Flutter 复制 SQL 连接【英文标题】:Firestore replicating a SQL Join for noSQL and Flutter 【发布时间】:2019-07-06 02:38:59 【问题描述】:我意识到在使用 FireStore 等 NoSql 文档数据库复制连接方面存在许多问题,但是我无法找到将 Dart/Flutter 与 FireStore 结合使用的彻底解决方案。
我做了一些研究,我觉得在下面的例子中我会寻找一个“多对多”的关系(如果这是错误的,请纠正我)因为将来可能需要查看所有配置文件作为所有连接。
在 firebase 中,我有两个根级集合(配置文件和连接):
profile
> documentKey(Auto Generated)
> name = "John Smith"
> uid = "xyc4567"
> documentKey(Auto Generated)
> name = "Jane Doe"
> uid = "abc1234"
> documentKey(Auto Generated)
> name = "Kate Dee"
> uid = "efg8910"
connection
> documentKey(Auto Generated)
> type = "friend"
> profileuid = "abc1234"
> uid = "xyc4567"
> documentKey(Auto Generated)
> type = "family"
> profileuid = "abc1234"
> uid = "efg8910"
对于此示例,假设用户 John Smith (uid: xyc4567) 连接到 Jane Doe (uid: abc1234) 和 Kate Dee (uid: efg8910) 时创建了“连接”文档。
这是我要复制的关系 SQL,以显示 John Smith 已连接的配置文件列表:
Select * FROM profile, connection
WHERE profile.uid = connection.profileuid
AND profile.uid = "xyc4567"
在颤振我的颤振应用程序中,我有一个 fireStore 查询起点:
stream: Firestore.instance.collection('profile')
.where('uid', isEqualTo: "xyc4567").snapshots(),
显然它只从一个集合返回。我如何以多对多关系加入集合?
【问题讨论】:
【参考方案1】:很遗憾,Cloud Firestore 和其他 NoSQL 数据库中都没有 JOIN
子句。在 Firestore 中,查询很浅。这意味着他们只能从运行查询的集合中获取项目。无法在单个查询中从两个***集合中获取文档。 Firestore 不支持一次性跨不同集合进行查询。单个查询只能使用单个集合中文档的属性。
所以我能想到的最简单的解决方案是查询数据库以从profile
集合中获取用户的uid
。获得该 ID 后,进行另一个数据库调用(在回调中),并使用以下查询从 connection
集合中获取您需要的相应数据:
stream: Firestore.instance.collection('connection').where('uid', isEqualTo: "xyc4567").snapshots(),
另一种解决方案是在每个用户下创建一个名为connection
的子集合,并在其下添加所有connection
对象。这种做法称为denormalization
,是 Firebase 的常见做法。如果您是 NoQSL 数据库的新手,我建议您观看此视频,Denormalization is normal with the Firebase Database 以便更好地理解。它适用于 Firebase 实时数据库,但同样的规则适用于 Cloud Firestore。
另外,当您复制数据时,需要牢记一件事。与添加数据的方式相同,您需要对其进行维护。换句话说,如果你想更新/删除一个项目,你需要在它存在的每个地方都这样做。
【讨论】:
【参考方案2】:我做了一些这样的事情来连接来自两个集合对象和类别的结果。
我做了两个 StreamBuilders 来显示在一个列表中,在第一个中我得到了类别并放入了一个地图,然后我查询对象并使用 categoryID 从地图中获取类别对象:
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('categoryPath')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> categorySnapshot)
//get data from categories
if (!categorySnapshot.hasData)
return const Text('Loading...');
//put all categories in a map
Map<String, Category> categories = Map();
categorySnapshot.data.documents.forEach((c)
categories[c.documentID] =
Category.fromJson(c.documentID, c.data);
);
//then from objects
return StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('objectsPath')
.where('day', isGreaterThanOrEqualTo: _initialDate)
.where('day', isLessThanOrEqualTo: _finalDate)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> objectsSnapshot)
if (!objectsSnapshot.hasData)
return const Text('Loading...');
final int count =
objectsSnapshot.data.documents.length;
return Expanded(
child: Container(
child: Card(
elevation: 3,
child: ListView.builder(
padding: EdgeInsets.only(top: 0),
itemCount: count,
itemBuilder: (_, int index)
final DocumentSnapshot document =
objectsSnapshot.data.documents[index];
Object object = Object.fromJson(
document.documentID, document.data);
return Column(
children: <Widget>[
Card(
margin: EdgeInsets.only(
left: 0, right: 0, bottom: 1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(0)),
),
elevation: 1,
child: ListTile(
onTap: () ,
title: Text(object.description,
style: TextStyle(fontSize: 20)),
//here is the magic, i get the category name using the map
of the categories and the category id from the object
subtitle: Text(
categories[object.categoryId] !=
null
? categories[
object.categoryId]
.name
: 'Uncategorized',
style: TextStyle(
color: Theme.of(context)
.primaryColor),
),
),
),
],
);
),
),
),
);
我不确定是否是您想要的或是否清楚,但我希望它对您有所帮助。
【讨论】:
【参考方案3】:我认为不应该首选宗派,因为要维护它,您必须对 firestore 进行额外的写入
而不是jorge vieira 是正确的,因为与写入相比,您可以进行双重读取
所以最好读两次而不是写两次数据,而且记住大型项目中每件令人沮丧的事情也是非常不切实际的
【讨论】:
【参考方案4】:假设,您想使用依赖于一些 Future
对象的 Stream
。
Stories
Document ID (Auto Generated) //Suppose, "zddgaXmdadfHs"
> name = "The Lion & the Warthog"
> coverImage = "https://...."
> author = "Furqan Uddin Fahad"
> publisDate = 123836249234
Favorites
Document ID (Auto Generated)
> storyDocID = "zddgaXmdadfHs" //Document ID of a story
> userId = "adZXkdfnhoa" //Document ID of a user
Sql 等效查询应该是这样的
SELECT * FROM Favorites AS f, Stories AS s
WHERE f.storyDocID = s.DocumentID
AND f.userId = user.userId
和这样的 Firestore 查询
final _storeInstance = Firestore.instance;
Stream <List<Favorite>> getFavorites() async*
final user = await _getUser(); //_getUser() Returns Future<User>
yield* _storeInstance
.collection('Favorites')
.where('userId', isEqualTo: user.userId)
.snapshots()
.asyncMap((snapshot) async
final list = snapshot.documents.map((doc) async
final story = await _getStory(doc['storyDocID']);
return Favorite.from(doc, story); //Favorite.from(DocumentSnapshot doc, Story story) returns an instance of Favorite
).toList(); //List<Future<Favorite>>
return await Future.wait(list); //Converts List<Future<Favorite>> to Future<List<Favorite>>
);
Future<Story> _getStory(String storyDocID) async
final docRef = _storeInstance
.collection('Stories')
.document(storyDocID);
final document = await docRef.get();
final story = Story.from(document);
return story;
【讨论】:
以上是关于SQL2000发布和复制的问题的主要内容,如果未能解决你的问题,请参考以下文章
怎样把sql server2000数据库转化为sql server2000的数据库
在Sql2000 sql2005 sql2008 下已能实现事务复制的强制订阅,但请求订阅始终不能实现总有下列错误提示