暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

如何选择你所需要的数据库

白鳝的洞穴 2020-08-21
772
以前选择数据库很简单,要么使用Oracle、SQL SERVER、DB2之类的商用数据库,要么用开源的Mysql、PG。这些数据库之间虽然SQL语法支持、存储过程、触发器、序列号发生器之类的有一些区别,不过大体上差不太多,只要应用程序开发的时候做些注意就可以了。不过在一些高并发、大数据量场景下,开发商还是吃过一些苦头的,比如同样的应用,在Oracle上跑的好好的,到了DB2上,锁的问题就很严重了。这个主要原因是Oracle在行锁和MVCC并发控制方面的技术要比当时的DB2成熟一些。DB2的行锁升级会导致严重的锁冲突故障,这个实际上和数据库底层的锁机制和行锁实现模式的差异有关了。不过虽然也遇到些小问题,大体上选择哪种数据库,最终对于开发商来说关系并不大,虽然不同数据库对同一个应用表现出来的性能有所差异。
现在不同了,大量的数据库如雨后春笋一样一夜之间冒了出来,让人眼花缭乱。我们先不说那些NONSQL的数据库,就算是号称是正宗的RDBMS,常见的没有一两百,大几十种总是有的。在这些新兴的数据库中,大多数还是分布式架构的数据库,号称比传统数据库技术上领先好几条街。这么多新数据库的出现让我们出现了选择恐惧症。好像每种数据库都宣传自己是最好的,最适合你的应用的。事实上真的如此吗?在这里老白要引入一个“通用关系型数据库”的词汇,以前我们使用的无论商用关系型数据库还是开源关系型数据库其实分为两类,一类是通用型的,适合于不同类型的应用场景;一类是专用型的,只适用于某些特定的场景,比如SQLLITE只要适用于嵌入式场景,在锁机制,并发机制等方面都与通用型关系型数据库不同的。
实际上,目前大多数新兴的分布式数据库与传统的通用数据库还是有一些不同的。在为你的应用系统选择数据库的时候要特别小心。去年我的一个朋友的一个负载十分巨大的系统用ORACLE承载有点吃力了,所以想选择一款分布式数据库来替代。刚刚开始交流的时候,觉得新兴数据库特别适合自己的场景。不过测试到后期的时候发现,这款数据库不支持传统意义上的行锁,只支持乐观锁。如果要让自己的系统支持乐观锁,那么整个系统最核心的代码要做完全的重构,从时间上和成本上都无法接受,于是花费了大半年的改造工作只能终止。
以老白的经验,在选择数据库的时候以下几个方面是要十分注意的:
1)SQL的兼容性,对标准的SQL/1999,SQL/2003等标准的支持程度,大家都说支持,实际上哪怕是ORACLE数据库在这方面的支持都是不完整的,因此我们不可能指望数据库完全支持这些标准,不过对于核心功能的支持一定要十分明确的。如果你的系统中使用了比较复杂的统计函数,窗口函数,这些函数的支持也是需要提前确认的,否则你就必须在你的应用系统中做相关的改动。
2)表连接方式的支持,大家常用的表连接的方式有NESTED LOOP、HASH JOIN,SORT MERGE JOIN等,不同的应用场景适合的表连接方式会有不同,如果你的系统中存在多张数据量较大的表的JOIN的话,一定要认真研究数据库对不同的JOIN类型的支持。在做这方面分析的时候,一定要特别仔细,不能光看某种数据库是否支持某种JOIN方式,还要看一些限制条件。比如有些数据库只支持=方式的HASH JOIN,不支持不等于方式,这对我们后续应用的性能优化,也是一个不小的坑。
3)并发控制,并发控制比较复杂,包括行锁机制、事务隔离级别、MVCC等方面。行锁方面,一定要注意只支持乐观锁的数据库,乐观锁的实现方式是在写数据的时候不做锁控制,只是在事务提交的时候才判断锁,如果提交时发现锁冲突,那么先提交的事务可以成功,后提交的事务全部失败,必须回滚。这种锁的模式对于某些特定类型的应用影响不大,比如银行的核心业务,对于某个账户的操作一般都是通过最终结果一致性来确定一致性的,同一个账号的业务是有严格的先后顺序的,如果某笔交易冲突,可以通过业务流程冲正。不过一些传统类的业务,乐观锁可能会引起较大的问题。比如我们批量提交几十万条数据,提交时发现锁冲突,我们必须回滚这一批数据,然后再重新处理,这种处理是十分麻烦的。
另外一方面就是事务隔离级别,如果我们的应用只使用read commited事务隔离级别,可能还感受不到差异。不过如果我们的应用中需要做重复读或者串行化事务隔离,那么我们可能需要关注,并不是所有的数据库都支持这些事务隔离级别。
另外对于一些分布式数据库,每个事务中允许的记录行数也是有限制的,最为常见的是32K,也就是说在同一个事务中,只支持不超过32行数据受到影响,超过这个就会出错。虽然说32K行数据也是一个不小的数字,对于绝大多数应用来说是够用的,不过万一哪天你需要对一张几千万条记录的表做一次UPDATE,那时候你就会发现,一条SQL是解决不了问题的。老白曾经使用过这样的数据库,当时厂家告诉我如果不够用,这个值是可以通过参数修改的,于是老白把参数修改为原来的100倍,虽然不报错了,不过所有事务的性能都下降了数倍。
4)区分数据库是一套完整的数据库还是一个数据库代理带上一帮小弟,对于选择分布式数据库十分关键。如果数据库是一体化设计的,那么无论是区分SQL引擎节点还是不区分SQL引擎节点的数据库,我们可以把任意一个SQL引擎节点当成应用的接口界面,我们也可以把整个分布式数据库环境当成一个数据库来使用和运维。如果某个数据库的架构是一个或者几个SQL代理,带着一些独立的数据库系统,从整体上形成了一个逻辑数据库,那么这种分布式数据库你也是要特别注意的。并不是说这种架构的数据库就有问题,而是说你需要仔细分析这个数据库的整体架构,是不是做了一体化的设计,比如节点的高可用、多副本的读写属性以及主副本管理的方式是否足够智能化与自动化,都十分重要,否则今后你的系统运维就是个大问题了。
当然,选择一个数据库的原则还很多,老白今天也只是把一些以前遇到的坑拿出来和大家分享分享。关于这个话题,再说上几天也说不完,今天就先谈到这里吧。
文章转载自白鳝的洞穴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论