【问题标题】:Best way to maintain data integrity between local and remote sql databases维护本地和远程 sql 数据库之间数据完整性的最佳方法
【发布时间】:2012-02-22 19:51:08
【问题描述】:

所以我有,我似乎无法找到答案的常见问题。我试图找出如何构建一个在本地维护数据的数据库的“最佳实践”,然后将该数据同步到在许多客户端之间共享的远程数据库。为了使事情更清楚,这个远程数据库将有许多使用它的客户端。

例如,如果我有一个桌面应用程序,它存储了具有单个项目的待办事项列表(在 SQL 中)。然后我希望能够将该数据发送到具有所有不同客户信息的“主”副本的网络服务。 我并不担心同步问题,我只是想通过客户端表和 Web 服务表的实际架构来考虑

这是我的想法的一个例子:

客户端数据库

list
--list_client_id (primary key, auto-increment)
--list_name

list_item
--list_item_client_id (primary key, auto-increment)
--list_id
--list_item_text

基于 Web 的主数据库 (在多个客户端之间共享)

list
--list_master_id
--list_client_id (primary key, auto-increment)
--list_name
--user_id


list_item
--list_item_master_id (primary key, auto-increment)
--list_item_remote_id
--list_id
--list_item_text
--user_id

这个想法是客户端可以创建包含项目的待办事项列表,并在任何给定时间将其与网络服务同步(即,如果他们失去数据连接,并且直到稍后才能发送信息,那么什么都不会出故障)。 Web 服务会将带有客户 ID 的记录记录为额外字段。 这样,客户端可以说“用新名称更新列表编号 4”,而服务器将其理解为“用新名称更新用户 12 的列表编号 4”。

【问题讨论】:

  • 很大程度上取决于具体的 RDBMS
  • 它是否属于服务器故障?
  • @emaillenin 为什么这属于 ServerFault?我想弄清楚如何设计数据库中的表
  • list_item 中的 list_id 是列表中 list_client_id 的 FK?

标签: sql web-services mobile synchronization


【解决方案1】:

我认为您正在使用的一般概念是正确的方向,但您可能需要特别注意自动增量列的使用。例如,如果客户端是此 ID 的所有者,则服务器上的自动增量是无用的。相反,您可能希望 list.list_master_id 成为自动增量。您提到的其他所有内容都是完全合理的,尽管如果每个用户可能有多个客户端,复杂性可能会增加。那么,单独使用自动增量可能是不够的。相反,您可能需要一个包含客户端标识符的 guid 或数据类型,以防止 id 冲突。

如果没有更多详细信息,很难推测您可能需要考虑哪些其他情况。

【讨论】:

    【解决方案2】:
    SERVER:
    list
    --id
    --name
    --user_id
    --updated_at
    --created_from_device_id
    
    Those 2 tables link all records, might be grouped in one table also.
    list_ids
    --list_id
    --device_id
    --device_record_id
    
    user_ids
    --user_id
    --device_id
    --device_record_id
    
    
    CLIENT (device_id=5)
    list
    --id
    --name
    --user_id
    --updated_at
    

    这将允许您将记录另存为(仅显示相关字段):

    server
     list: id=1, name=shopping, user_id=1234
     user: id=27, name=John Doe
    
     list_ids: list_id=1, device_id=5, device_record_id=999
     user_ids: user_id=27, device_id=5, device_record_id=567
    
    client
     id=999, name=shopping, user_id=567
    

    这样他们完全不知道任何 ID,翻译可以很快完成,您可以只向客户提供他们知道的信息和 ID。

    【讨论】:

      【解决方案3】:

      我正在处理的一个项目也有同样的问题,我的解决方案是在名为 remote_id 的本地表中创建一个额外的可为空字段。本地同步记录到远程数据库时,如果remote_id为null,则表示该行从未同步过,需要返回与远程行id匹配的唯一id。

      Local Table            Remote Table
      
      _id (used locally)
      remote_id ------------- id
      name      ------------- name
      

      在客户端应用程序中,我通过 _id 字段链接表,远程我使用远程 id 字段来获取数据、执行连接等。

      本地示例:

      Local Client Table       Local ClientType Table      Local ClientType
                               _id
                               remote_id  
      _id -------------------- client_id
      remote_id                client_type_id -------------- _id
                                                            remote_id
      name                    name                          name
      

      远程示例:

      Remote Client Table      Remote ClientType Table      Remote ClientType
      id -------------------- client_id
                              client_type_id -------------- id
      name                    name                          name
      

      这种情况,并且代码中没有任何逻辑,会导致数据完整性失败,因为 client_type 表可能与本地或远程表中的真实 id 不匹配,因此每当生成 remote_id 时,它都会返回一个信号给客户端应用程序要求更新本地 _id 字段,这会触发先前在 sqlite 中创建的触发器来更新受影响的表。 http://www.sqlite.org/lang_createtrigger.html

      1-remote_id在服务器中生成

      2- 向客户端返回信号

      3- 客户端更新其 _id 字段并触发更新连接本地 _id 的本地表的触发器

      当然,我还使用 last_updated 字段来帮助同步并避免重复同步。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-29
        • 2020-05-12
        • 2011-06-29
        • 2018-05-09
        • 2018-06-21
        相关资源
        最近更新 更多