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

在KunlunBase中使用高级SQL功能之约束与数据有效性验证

KunlunBase支持丰富的高级SQL功能,包括视图、物化视图、触发器、存储过程、domain、CHECK约束、Row Level Security(RLS)、多层级多粒度的访问控制等。KunlunBase的这些功能继承自PostgreSQL,同时经过我们扩展和增强,让它们在KunlunBase分布式数据库系统中可以继续正常工作。

这些高级SQL功能在经典数据库时代就已经存在,在现在的分布式数据库时代,这些功能还有用吗?对数据库系统性能有什么影响?有没有更好的替代方案?这应该是有一定数据库使用经验的技术人员会考虑的问题。下面我们就介绍一下每一种功能的使用场景,以及在KunlunBase中这些功能的价值和利弊。

 

约束


 

一个表的常规的数据有效性约束包括数据类型、主键(primary key)、唯一性(uniqueness)、是否可空(nullability)这些通用规则,它们能够在一定程度规范数据有效性,但是它们无法具体规定一个表每一行一个或者多个字段的合法字段值范围和约束关系。只有使用CHECK约束才可以做到这一点,所以CHECK约束对于应用系统正确地实现业务逻辑是极其重要的。

必须在数据源头也就是数据库系统中定义数据有效性验证规则,而不是依赖应用软件层做这样的校验和检查,否则在实践中就一定会有非法数据进入数据库系统从而影响应用系统正常工作。之所以如此,是因为随着应用软件持续的迭代、扩展,那些数据有效性规则可能在最初的系统设计中被严格遵守,而到了后来则可能随着开发人员的更迭和技术文档缺失而被遗漏。

非法数据就像毒药和污染物一样,会污染有效数据,影响应用系统稳定性,甚至对数据分析决策产生误导。非法数据进入数据库后,原有的业务逻辑可能发生无法预料的异常行为,影响系统的稳定性甚至导致其不能正确工作。

这是因为使用这些数据的模块根据业务需求来处理数据,并不会预期到会有这些非法数据。所以数据库的数据有效性校验机制就像过滤器一样,把有毒的、非法的、错误的数据过滤出去,确保数据库中存储的都是有意义的合法数据。


CHECK约束

CREATE TABLE[1]语句中定义CHECK约束[2],可以在INSERT和UPDATE每一行时检查该行的一个或者多个字段符合用户定义的有效性约束规则。不符合这个表的有效性规则的INSERT/UPDATE语句会执行出错被回滚掉,这就杜绝了非法数据进入数据库。

外键

在经典数据库时代,外键是一种常用的约束,不过外键的引用完整性规则对于系统的INSERT,UPDATE,DELETE的性能有较大的影响。而在分布式数据库系统中,这种性能开销就更加巨大了 --- 表t1的一行所引用的表t2的行可能在另一个节点上,这就让引用完整性检查变的非常昂贵,因此KunlunBase不支持外键。这是KunlunBase的唯一一个不支持的常用经典SQL高级功能。

外键最初之所以有必要,很重要的原因是Edgar Codd最初设计关系模型时设想的是把SQL作为用户直接操作数据库中的数据的语言而存在的,也就是SQL由人来输入,就像那个时代使用计算机就是在敲命令进去执行一样。这就容易引发人为误操作导致的错误。而在当今实际的应用系统中,数据库都是作为应用软件的后台服务器而运行的,SQL是由应用软件开发人员撰写或者ORM中间件自动生成的,然后由应用软件发送给数据库的,这就把人为错误排除在了实际运行期间之外。开发调试期间这类错误就被解决了。

同时应用操作逻辑也完全可以正确地定制化实现符合需求的引用完整性规则。如果要删除t2的一行,那么引用它的t1中的行可以由应用软件显式删除,或者保留,或者设置为NULL或者其他值。这样更安全更灵活,也可以防止级联删除导致的数据意外丢失。

给MySQL用户的特殊忠告

MySQL直到8.0.16版本才正式支持了CHECK约束,在此之前用户定义的CHECK约束直接被解析器忽略了。CHECK约束的缺失曾经给MySQL应用开发带来了极大的隐患,依赖应用软件做数据有效性检查非常容易导致有效性规则被无意甚至有意绕过。所以强烈建议MySQL用户尽快养成在CREATE TABLE语句中设置有效性检查规则的良好习惯。

MySQL支持非常灵活的数据类型转换,这种灵活性也是一种诅咒,让一些初级MySQL用户失去了对数据类型的理解,导致数据类型的约束性、有效性验证、比较方法等功能都失效或者被滥用了。

数据类型本身就是一种最基本的数据有效性约束,它规定了合法数据的范围和可以执行的操作,特别是做比较的方法和数据排列顺序。数据类型之间也并不是都可以转换的,比如把日期、时间、时间戳与数值之间互转通常没什么意义,但是MySQL竟然是支持的,并且其转换方法也很有想象力 --- 比如’2023-07-16’ 这个日期值与20230716这个整数是互转的。

这种任意的数据类型转换不仅很容易导致非法值出乎意料地进入数据表,而且容易导致索引工作不正常或者不符合预期,比如找不到本应该在表中的值,常见于范围查找;或者本应该使用到索引但是实际上没有用到等问题。

比如有的用户习惯把表的所有数值类型定义为字符串,这样的问题是你要做范围查找的时候,返回的结果其实是错误的,因为数据按照字符串来比较。

除非你在字符串表示的数值左边补0,但是那样你就要么面临数值溢出风险因为预定的宽度较小,要么就是占用空间比数值类型大很多倍。同时,字符串比较的CPU开销也远大于NUMERIC/DECIMAL以外的数值类型比较。

有的用户习惯把时间戳列也定义为字符串或者datetime类型,这就导致时间戳类型的时区信息无法生效,无法对不同时区的用户显示当地时区的值。同时把任何date, time, datetime, timestamp列定义为字符串类型都会导致范围查找出错,数据显示格式混杂,本地化(l10n)和国际化(i18n)失效,非法值进入数据表等等问题,并且占用的存储空间远大于使用正确类型。

最后再说一下字符串类型的字符集和collation属性。MySQL支持在表级和列级指定charset和collation,这本来是一个非常灵活的功能,但同时对很多用户也是个巨大的坑。

在实际的应用中,很多用户经常因为这种灵活性而出现由于两个列的charset, collation不匹配而导致的问题。比如表t1.a和t2.b都是varchar(64)类型并且有UNIQUE约束,但是二者的collation不同,然后查询语句中出现WHERE t1.a = t2.b AND t2.b=’xxx’ 这样的条件,然后你EXPLAIN发现竟然对t1做了全表扫描,而不是使用t1.a的唯一索引,导致性能极差。另一类问题是collation转换操作带来的性能问题,如果同一个语句中对大量行的字段做collation转换操作的话,其性能开销也很可观。

所以,最好在一个database范围内统一使用UTF8MB4。UTF8MB4这个字符集包含了人类所有语言的文字,以及emoji表情包,真的非常全面了,不需要使用其他字符集了。有的国内用户习惯使用GB2312/GB18030/GBK等字符集,但是这些字符集不包含很多外文文字,如果有一天你的业务可以出海了,你会发现海外用户的输入数据无法在你的系统中正确使用。所以还是建议统一使用UTF8MB4。



题外话和感慨

MySQL的上述所谓的灵活性唯一的价值就是让那些对SQL和数据库知之甚少的程序员(很多是高中生和大学在读学生)迅速地完成他们的网站项目。

在那个互联网如星火燎原般爆炸的年代,把网站迅速做出来并且‘基本能跑起来’比严谨和健壮、可维护性、逻辑完备性更有价值。对这些’草根’程序员来说,先不管正确有效,能把数据塞进去,取出来,就够了。至于什么数据加密,访问控制,3NF,ACID,很多人甚至没听说过。

而MySQL也正是抓住并迎合了这些草根程序员的痛点,满足了他们的需求,从而成为了互联网时代发展最快的关系数据库。

特别是在InnoDB还不是默认存储引擎的时代,使用myisam 加上binlog异步复制就是高可用方案了,现在看完全是个玩具级的技术实力,但是在那时真的就支撑着当时全球最流行的各种网站和互联网服务。

那时一旦MySQL实例崩溃,那么DBA就要用myisam的数据文件修复工具结合binlog熬夜加班手动修复数据,并且很难找回全部提交的事务的数据,估计经历过的当事人一定有一种咬牙切齿龇牙咧嘴的酸爽。即便如此他们仍然把MySQL捧在手中当作宝贝。只能说,这个世界太奇妙了!



参考文章:

[1]CREATE TABLE:https://downloads.kunlunbase.com/docs/html/sql-createtable.html

[2]CHECK约束:https://downloads.kunlunbase.com/docs/html/ddl-constraints.html











现在,我们发起一轮新的投票,希望就以下问题请教大家,收集大家的反馈。为了感谢您的参与,所有参与问卷调查并留下邮箱联系方式的,由于我们的问卷系统不支持在线抽奖,我们将在后续会统一随机抽取 15 名有效填写者作为幸运参与者,送精美纪念礼品一份,感谢大家参加。
👆扫码填写

END

同时欢迎大家扫码👇添加小助手(备注:加入KunlunBase技术交流群)欢迎大家在交流群共同探讨更多问题及主题。

 点击👆上方,关注获取源代码及技术信息~ 

推荐阅读



关于我司将 KunlunBase 产品名称改为 Klustron 的通知

 在KunlunBase中使用高级SQL功能之多层级访问控制

文章转载自KunlunBase 昆仑数据库,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论