代码之家  ›  专栏  ›  技术社区  ›  gilhad

迁移和两个应用程序在不同的机器上共享数据库的一部分

  •  3
  • gilhad  · 技术社区  · 8 年前

    更好的描述

    问题 :如何组织 ./manage migrate


    • 我必须在客户机上创建django网站,让本地用户登录并在本地做一些事情。
    • 还有一个带有大型django应用程序的服务器,它的用户在服务器上进行操作。

    服务器django应用程序和客户机“justpython”应用程序已经建立了连接和传输数据的协议,完全是从服务器到客户机的。不是所有的表都被传输(因为不是所有的表都需要),有时只有一个表的结构在客户机上被强制执行,有时也是数据。


    不,我必须在客户机上创建本地django网站

    • 它自己的一组用户,一些配置文件(一个连接到本地用户)
    • 共享表(从服务器复制,在客户机上纯只读,有时被共享协议覆盖)

    • 本地身份验证
    • 管理“仅本地”表的内容
    • 将某些数据用于仅显示自此类“服务器副本表”的数据(有些数据将由这些本地表的外键链接)。

    很难保证,那些复制的表不会做任何不正常的事情(只会增加长度,现有记录最多会修改一些布尔列,也许以后会添加更多字段,但不会删除或更改任何字段-无论是结构还是含义))


    我应该如何构造我的“clientdjango应用程序”,使其可维护、与表的服务器副本共存(并与之一起工作)。

    我可以创建我的应用程序与声明一些模型,迁移,复制“服务器模型”迁移 --fake 这一部分然后照常继续,但它将安装在更多的客户机上,并且共享表的结构稍后可能会添加一些我需要阅读的内容—所以另一部分

    有没有一种方法,可以进行一些迁移——默认情况下是假的,这样它就不会真正迁移,但不会以未填充的形式提供(如果那些模型会改变的话)?或者我只需将所有此类迁移命名为“0007\u PLEASE\u false\u ME”,然后每次在每个客户机上手动完成?或者它需要完全不同的访问权限?

    我甚至可以将模型更改请求发送给“服务器”人员,以便将其合并到他们的应用程序中型号.py把它按成“只更新结构”

    我可以把他们的models.py 如果它改变了,我也会。

    我仍然不确定,我的OneToOne用户配置文件将如何在服务器上工作,那里有很多已经建立的用户和无配置文件模型。。。

    Djago版本在服务器和客户端(1.10)上是相同的,所有表都是MyISAM。



    编辑

    1. 修改首先进入服务器(将值填充到表中),然后将表传输到客户机,然后客户机得到SW update,后者使用新特性(因此每次都以旧方式或新方式使用完整的新数据),服务器使用django,客户机使用纯SQL select name,filename, volume from themes where active=1

    2. ... AND plaing_allowed=1

    3. 用于数据库传输的API非常稳定(即使有点慢),通过SSH传输某种形式的TXT/XML数据(很多时候客户端没有其他连接可用)-首先是表描述,然后按顺序更改每一行-传输顺序是这样构造的,在不影响客户工作能力的情况下,这可能随时被打断。客户机上的软件在数据库更新后,所以有(旧客户机,旧数据-工作)(旧客户机,新数据-一起作为以前的版本工作)(新客户机,新数据-作为新版本工作)

    旧客户机simple忽略(不知道)新表/字段,并且缺少一些新函数(也缺少调用此类函数的方法),所以它可以工作,就像根本没有做任何更改一样。


    同样,旧方法(服务器上的django和mysql,客户端上的python和mysql)可以可靠地工作多年。

    并不是每次客户机-服务器连接都是可能的,那么客户机应该在“本地”处理旧数据,直到连接再次可用为止(有时在几个小时之后,有时在几个月之后)。


    我的任务是创建新的django应用程序,该应用程序将在一些(可能是所有)客户机上发布,这基本上为现有模式添加了一些“本地特性”

    • 有一些新的表格来放置一些计划和数据
    • 有一些web界面,用户可以通过web浏览器直接登录到客户端(它本身是apache+django+mysql的小服务器)并在那里计划一些本地事件-这些事件不会在主服务器上反向传播,也不会修改“正式表”,只会读取可用的内容并制作“本地笔记”
    • 这些“本地注释”然后使用客户机上已经存在的API在更多单独的任务上注意到它,这需要“现在和这里”完成-这样的API已经存在,并且由一些过时的应用程序(在用户PC/NB上运行)在本地使用,这些应用程序将被客户机上新的django应用程序的web接口所取代。
    • 我们的目标是能够扩展web界面来使用一些特殊的“本地表”以及读取那些“正式发布”的表,并扩展本地API以允许更多的功能,本地API(在客户端上)只从表中读取数据并对其进行操作,而不修改数据库中的任何内容(本地API的新版本也应在本地表上读取,以获得更多功能)

    我的问题是,如何开发客户端django应用程序,对于一些数据库模式的更新“只是偶尔在后台发生”。

    已经存在的系统(针对不同的标准进行了优化)比新的部分要大得多,因此从头开始重新编写它是不可取的。此外,还有一些“不可更新的部分”,例如,旧的通信方式必须支持无论如何在新的版本,因为一些计算机完全超出我的能力范围依赖它。(但是通信协议是为了扩展而设计的,所以添加更多的信息没有什么大问题)


    更好的描述

    • Master M运行Myslql+Django+Apache并有1个API(M-S)
    • 主表有TA(1..)、TB(1..)、TC(1..)
      1. M-S API传输表架构 (创建类表)用于所有TA和TB表(完整或更改)
      2. 对于TA表
    • Slave现在运行Mysql+旧程序,有2个api
      1. M-S API(用于网络主机)
      2. (基于XML的旧本地通信) 旧应用程序 )
    • 主机(不定期,但足够频繁,如每天1-10倍)联系每个从机,并通过M-S forces数据库更新对其进行更新
    • Slave独立地制作自己的作品(主要是根据表TA中的一些提示播放音乐)(自己规划排列等)
    • 旧应用程序 通过S-localapi,从机停止正在执行的操作并播放适当的消息,然后继续
    • S-localapi是由一些过时的封闭源代码应用程序操作的 旧应用程序 ,应替换为 (见下文)
      • 旧应用程序 在Windows下的用户计算机(完全不同于主计算机和从计算机)上运行,并有硬编码的XML字符串发送到从计算机
    • 来自主设备M的大量信息与从设备S无关(主要是所有授权和用户,因为关于从设备的决定基于不同的标准,并且这里使用的TA表实际上是只读的)
    • 所有这些工作了很多年,经过许多版本的变化,一个是太大了,不能在正常的时间重写。

    新方法是创建和运行基于 django应用程序(+Apache)提供了比 旧应用程序

    为此,它需要:

    • 授权(与Master不同,但所有Master auth.*表都在TC组中,根本不传输,因此可以在Slave上本地重用)
    • 它读取TA组的一些表(但只读取,不修改内容)
      • 每个奴隶都不一样,不向主人报告
    • 使用S-local API(并稍微扩展它—没问题)

    质疑的解决方案:

    • 复制主设备上TD表的模型,并让它们与TB表一起传输到从属设备(仅结构)
    • 在上安装新版本 这种方式:
      1. 更新主机上的TD以与主机上的新版TD同步 并在主机上迁移
      2. 在从机上进行传输(因此必须有新版本)
      3. 新应用程序 关于奴隶和正义的使用 ./manage.py migrate --fake 停止抱怨

    M-S公司 API及其传输(只起作用,数据库中的默认值应用于现有记录/行的新字段),创建视图和模板(如果model表包含的字段多于model,则忽略这些字段)

    这样,Master就不会以任何方式使用TD表/模型(没有接口,没有管理,只是在那里是空的),Slave将在外部与Master同步更新。型号.py两者的数据部分是相同的(可能是TD的主缺失函数和一些TA/TB表的从缺失方法)

    问题

    1. 这样行吗(假迁移)
    2. django在Master上是否需要(并自动管理)一些“系统”表,这些表需要传输(最终与数据一起)到从属服务器(可能与迁移所做的工作有关,或者与需要满足的表结构有关)型号.py(要求) 2.1. 这样的表是否被转移,甚至需要在从机上进行假迁移?(因为所有的迁移都在这些表中提到了,而且模型也很适合,所以我认为没有迁移)
    1 回复  |  直到 8 年前
        1
  •  1
  •   Tushar    8 年前

    我希望客户机指的是本地服务器,全天候运行,而不是客户的笔记本电脑/台式机。

    1. 请理解,任何涉及复制数据库表的解决方案都可能是脆弱的,特别是在有外键的情况下,如 created_by 它指向一个用户,在本地设置中,它们可能必须指向某个本地用户(或一个虚拟用户)。

    2. 此外,服务器应用程序中也可能有其他数据库更改,除非您在客户端Django应用程序中也更改了相应的模型,否则您不能在客户端使用相同的模型,并且如果您使用其他工具添加列,那么Django中的列可能不再可用。任何使用django模型创建的表,如果不这样做,都会导致很多问题。

    3. 因此,最好避免复制表,并尝试使用一些更标准的方法,如使用api连接这两个系统,以便完全控制数据的复制方式。

    4. 您可以通过API在服务器应用程序上公开选定的表,在客户端可以使用类似 django-celery-beat

    5. 每当服务器应用程序发生某些更改时,您需要在本地应用程序中进行更改。将该数据添加到相应的API响应中。并在客户端应用程序中进行更改以获取和保存/利用这些数据。

    6. 班级购买(models.Model): 客户id=型号.外键(CustomerTable,related\u name='purchased\u by') 项目=models.CharField(最大长度=50) 日期=模型.DateTimeField(auto\u now\u add=True)

    customer_id , item price 在本地应用中, 创建API http://server_app.com/purchase ,向您发送这样的响应。 [{"customer_id": 4, "item": "soap", "price": 20}, {"customer_id": 5, "item": "toothbrush", "price": 10}, ...] . 此响应可由客户端应用程序使用,并可保存在如下所示的本地模型中。如果数据量很大,还可以让系统将CSV文件作为下载文件发回,代替JSON响应。

    class CustomerTrend(models.Model):
        customer_id = models.ForeignKey(CustomerTable, related_name='purchased_by')
        item = models.CharField(max_length=50)
        price = models.PositiveIntegerField()
    

    更新

    好吧,在你编辑之后,有一件事是肯定的,因为它是一个巨大的遗留系统,我们正在谈论的,重组不是一个选择。据我所知,您希望在现有系统的客户端插入一个基于Django的UI。让我们看看,还有什么其他的选择:

    1. 您可以应用假迁移,也可以选择根本不应用任何迁移。让当前系统在本地系统上复制数据/模式。
    2. 在客户端Django应用程序中复制所需的模型 in code
    3. 要小心任何新的模型或列,你添加在任何一边,他们必须有一个明智的选择 default value ,如果可能允许 Null(None) . 这样做的目的是在两个系统之间保持向后兼容性,并且您不会遇到 Integrity Errors 在客户端应用程序上,以防 only a few columns . 它让我想起了我工作过的另一个遗留系统(用C&PHP,大约15年前。我在它12岁的时候就开始做了)。我们过去也遵循类似的策略,多个系统共享一个数据库,所有系统都运行不同版本的客户机,需要不同的数据。 如果您使用的是Django的自定义身份验证,那么只需对身份验证表进行一次性复制,然后禁用该表的复制(据我所知,您不会迁移这些表上的数据)。如果您使用的是默认身份验证,只需在本地安装程序的第一次部署期间分别迁移它们。
    4. 如前所述,运行假迁移是可以的,或者根本不运行它们。这是一个只有您才能基于特定用例进行的调用,您可能会更好地理解它。但如果您不在本地应用(假)迁移,您就不能在将来应用任何迁移(因为django的内部迁移表没有任何数据)。如果您看到将来可能有特定于客户端的表,那么就进行假迁移。
    5. 底线是,绝不允许两个系统(DB replicator&Django)在同一个客户机数据库上进行模式更改,否则会变得很糟糕。由于DB replication是必需的,因此客户端应用程序代码应该确保它能够与重新定位的数据库一起运行(使用具有正确默认值和可空性的列)。在两个服务器和客户机应用程序的模型中所做的代码更改应该相同。(代码评审应该关注这一点,因为这实际上可能是您将来的单点失败)。
    推荐文章