在工作上遇到的各类开发需求中,只要涉及到后端功能,关系数据库的使用几乎不可避免。虽说有各类NoSQL产品竞争和补充,但是它们没法完全替代关系数据库,实际上也很难替代。各项技术,各有各的优点和长处。我这里提出一个经过实践检验总结出来的新的数据库开发、管理思路。也许早已经有人采用这个思路和办法,这里的新是对我而言。

大量的开发者使用关系数据库都会遇到一个痛点:“阻抗不匹配”。(阻抗不匹配:指持久化存储数据所采用的数据模型与编写程序时所采用的数据模型有差异。)因为数据库使用标准的SQL语言操纵数据,而连接操作数据库的语言则五花八门,语言特性差别很大。这里面让人头疼的地方是:不管你是什么用语言开发,操作数据库都必须使用SQL语言,你需要把语言的数据及操作,映射到数据库;此外,敏捷思维下迭代开发很多,特别是前期,数据库表、视图结构的设计并不是稳定的,也经常随着需求变化,时不时的都要修改表结构、字段属性,同时再同步修改对它的操作过程。

对于操作数据库的语言匹配问题,社区开发出各种语言内的ORM系统,试图用本语言自己的对象及操作方法,自动的转化为对数据库的操作调用。这种模式发展的还算比较成功,Python/PHP/Java等语言,主流开发框架都有自己的ORM实现。除了个别特殊情况,现在几乎已经没人在开发框架内手写拼接SQL语句查询了。如果有,你需要立刻反思下自己的数据库Model设计是否不够合理,以及是否没有了解掌握语言框架的ORM系统。使用ORM系统优点多多,方便安全,这是首选方法。

另外一个问题,目前看,似乎还没有标准、成熟的解决方式。恐怕大部分人还是开发的时候,利用数据库客户端工具,手工设计、修改数据库结构,处理各种数据库表,再跟自己的程序联调。后面需求变更,再继续修改数据库和程序,循环往复。即便借助工具设计操作,也没摆脱数据库客户端,也是手工的一类。

这样的实践过程,是比较低级的,对数据库的变更操作往往缺乏记录和管理。另外还需要开发者时不时的切换到SQL模式,使用它的规则来行动。这是一种心智负担。你的关注点是分散的,需要同时关注数据库的设计变更和开发中操作的变化。另外,开发过程往往是线上、测试两套数据库隔离,等开发出新版系统要部署上线,还需要对已有的数据库进行修改变更,这个可不是简单的输出测试数据库的表结构安装覆盖就能解决的了。线上的库里面可是有数据的呀!出现一点差错都不可接受。手工操作的弊端和风险是很大的。

有的朋友可能会提到:是否可以使用存储过程去屏蔽数据库的结构变化?这个问题在这篇文章里面有详细的讨论,可以参考:http://davidwaynebaxter.com/2013/10/28/orm-or-sprocs/

对于这个事情,我经过研究发现,业界著名的Python 语言Web开发框架 – Django的解决模式很不错,值得学习研究和借鉴。

enter image description here

后端功能,并不一定是以Web形式存在。但是Web开发的飞速发展,业界积累了大量的开发经验,开发出十分出众的框架和配套工具。所以,开发者如果技术全面,这里优点又体现出来了:“他山之石,可以攻玉”。你完全可以使用Web开发的框架/工具,来管理自己的关系数据库,而并不需要开发Web的应用。即使需要也并不困难。

Django的思路是这样的:它使用Python语言的对象类型,模拟数据库表结构和关系。它使用ORM操作数据库,又通过定义“迁移”的过程,管理表结构和关系的变化。只要你按照它的设计思路一直演进开发,它就能保证线上的库也能按线下的测试库一样,得到正确的修改和变化。

你需要做的工作就是定义好应用里面的Model – 它代表一个数据库的表。当你需要修改数据库的时候,不要去用客户端工具修改MySQL这些数据库,而是修改Django里面的Model。你对Model的更改 – 增删字段、变更字段的属性等等,Django会在迁移操作中进行记录并自动执行数据库的修改。这样,你的关注点就只有一个了。Django定义了一个makemigrations操作,自动扫描各应用中Model的状态,与实际数据库的差异并记录下来。然后在后面的migrate操作中,执行修改行为,这样线下线上的映射关系,就自动的保持一致了。Django会自动的保存所有变更记录,可以放在Git里面管理。而且,你的Model就是ORM操作中使用的对象,完全不存在代码重复和管理麻烦的问题。

这个设计思路十分的优秀,非常合理。经过我的使用验证,非常的好用方便。反观另外一大Web开发阵营:PHP语言的框架则没有这种思路的实现。它们也有所谓的“迁移”定义和工具,可是它们的操作是反的,执行的是从线上数据库表映射到框架内的Model或者某种文件的表示。如果你更改模型,并不能如同Django一般,简单的映射到线上表示,自动同步,还需要自己编写变更脚本。如果谁知道哪个优秀的PHP框架做到了,烦请通告。Java阵营貌似有工具也可以干这个事情,不过用的少,没仔细研究。顺便说一句,Django框架真的很棒,文档优秀,社区繁荣,性能也不错,技术选型中需要的时候值得大力推荐。不同的阵营,设计出现这种差别,不知道是否是语言实现的原因,按道理大家都是相互学习借鉴的呀。Python语言天然的适合这种映射的表示,使用Django系统中的Python对象来表达数据库表,真的是太容易、太方便了。而且Django把Model的表示内容单独抽离,设计的结构很理想。

所以,如果你使用的框架无法做到从Model自动映射、同步到数据库表结构,而你能操纵Python阵营的系统,在觉得成本合理的情况下,完全可以单独建立一个Django工程来管理数据库,而不必实现其Web功能,需要的时候也真的不难。同时,可以让你采用的语言框架、系统,用工具从线上再同步回来,由Table映射到Model,这样变更就容易的多了。等你的系统上线的时候,就会明白,有专业的系统管理是多么好的一件事了,一条命令就实现了线上的数据库变更操作。

下面给出一些参考链接,有兴趣的朋友们可以继续研究研究。更好的开发模式可以有效的提升产品质量和开发效率,所以,我对于寻找更好的方法从来都是乐此不疲的。

MyBatis Migrations:http://www.mybatis.org/migrations/index.html Flyway:https://flywaydb.org/documentation/ Phinx Migrations:https://book.cakephp.org/3.0/en/phinx.html Django Migrations:https://docs.djangoproject.com/en/2.0/topics/migrations/

作者博客