From d153a2b6c42f4eecb08f10bbb17d091d32bea442 Mon Sep 17 00:00:00 2001 From: Xargin Date: Tue, 1 Jan 2019 20:42:10 +0800 Subject: [PATCH] fix db --- ch5-web/ch5-05-database.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ch5-web/ch5-05-database.md b/ch5-web/ch5-05-database.md index 4a61894..95d6f94 100644 --- a/ch5-web/ch5-05-database.md +++ b/ch5-web/ch5-05-database.md @@ -1,6 +1,6 @@ # 5.5 Database 和数据库打交道 -本节将对`db/sql`官方标准库作一些简单分析,并介绍一些应用比较广泛的开源ORM和sql builder。并从企业级应用开发和公司架构的角度来分析哪种技术栈对于现代的企业级应用更为合适。 +本节将对`db/sql`官方标准库作一些简单分析,并介绍一些应用比较广泛的开源ORM和SQL Builder。并从企业级应用开发和公司架构的角度来分析哪种技术栈对于现代的企业级应用更为合适。 ## 5.5.1 从 database/sql 讲起 @@ -102,7 +102,7 @@ func main() { 聪明如你的话,在上面这段简短的程序中可能已经嗅出了一些不好的味道。官方的`db`库提供的功能这么简单,我们每次去数据库里读取内容岂不是都要去写这么一套差不多的代码?或者如果我们的对象是结构体,把`sql.Rows`绑定到对象的工作就会变得更加得重复而无聊。 -是的,所以社区才会有各种各样的sql builder和orm百花齐放。 +是的,所以社区才会有各种各样的SQL Builder和ORM百花齐放。 ## 5.5.2 提高生产效率的ORM和SQL Builder @@ -143,7 +143,7 @@ o := orm.NewOrm() num, err := o.QueryTable("cardgroup").Filter("Cards__Card__Name", cardName).All(&cardgroups) ``` -很多ORM都提供了这种Filter类型的查询方式,不过实际上在某些ORM背后甚至隐藏了非常难以察觉的细节,比如生成的sql语句会自动 limit 1000。 +很多ORM都提供了这种Filter类型的查询方式,不过实际上在某些ORM背后甚至隐藏了非常难以察觉的细节,比如生成的SQL语句会自动`limit 1000`。 也许喜欢ORM的读者读到这里会反驳了,你是没有认真阅读文档就瞎写。是的,尽管这些ORM工具在文档里说明了All查询在不显式地指定Limit的话会自动limit 1000,但对于很多没有阅读过文档或者看过ORM源码的人,这依然是一个非常难以察觉的“魔鬼”细节。喜欢强类型语言的人一般都不喜欢语言隐式地去做什么事情,例如各种语言在赋值操作时进行的隐式类型转换然后又在转换中丢失了精度的勾当,一定让你非常的头疼。所以一个程序库背地里做的事情还是越少越好,如果一定要做,那也一定要在显眼的地方做。比如上面的例子,去掉这种默认的自作聪明的行为,或者要求用户强制传入limit参数都是更好的选择。 @@ -157,7 +157,7 @@ num, err := o.QueryTable("cardgroup").Filter("Cards__Card__Name", cardName).All( 当然,我们不能否认ORM的进步意义,它的设计初衷就是为了让数据的操作和存储的具体实现所剥离。但是在上了规模的公司的人们渐渐达成了一个共识,由于隐藏重要的细节,ORM可能是失败的设计。其所隐藏的重要细节对于上了规模的系统开发来说至关重要。 -相比ORM来说,sql builder在sql和项目可维护性之间取得了比较好的平衡。首先sql builer不像ORM那样屏蔽了过多的细节,其次从开发的角度来讲,sql builder简单进行封装后也可以非常高效地完成开发,举个例子: +相比ORM来说,SQL Builder在SQL和项目可维护性之间取得了比较好的平衡。首先sql builer不像ORM那样屏蔽了过多的细节,其次从开发的角度来讲,SQL Builder简单进行封装后也可以非常高效地完成开发,举个例子: ```go where := map[string]interface{} { @@ -170,17 +170,17 @@ orderBy := []string{"id asc", "create_time desc"} orders := orderModel.GetList(where, limit, orderBy) ``` -写sql builder的相关代码,或者读懂都不费劲。把这些代码脑内转换为sql也不会太费劲。所以通过代码就可以对这个查询是否命中数据库索引,是否走了覆盖索引,是否能够用上联合索引进行分析了。 +写SQL Builder的相关代码,或者读懂都不费劲。把这些代码脑内转换为sql也不会太费劲。所以通过代码就可以对这个查询是否命中数据库索引,是否走了覆盖索引,是否能够用上联合索引进行分析了。 -说白了sql builder是sql在代码里的一种特殊方言,如果你们没有DBA但研发有自己分析和优化sql的能力,或者你们公司的DBA对于学习这样一些sql的方言没有异议。那么使用sql builder是一个比较好的选择,不会导致什么问题。 +说白了SQL Builder是sql在代码里的一种特殊方言,如果你们没有DBA但研发有自己分析和优化sql的能力,或者你们公司的DBA对于学习这样一些sql的方言没有异议。那么使用SQL Builder是一个比较好的选择,不会导致什么问题。 -另外在一些本来也不需要DBA介入的场景内,使用sql builder也是可以的,例如你要做一套运维系统,且将MySQL当作了系统中的一个组件,系统的QPS不高,查询不复杂等等。 +另外在一些本来也不需要DBA介入的场景内,使用SQL Builder也是可以的,例如你要做一套运维系统,且将MySQL当作了系统中的一个组件,系统的QPS不高,查询不复杂等等。 -一旦你做的是高并发的OLTP在线系统,且想在人员充足分工明确的前提下最大程度控制系统的风险,使用sql builder就不合适了。 +一旦你做的是高并发的OLTP在线系统,且想在人员充足分工明确的前提下最大程度控制系统的风险,使用SQL Builder就不合适了。 ## 5.5.3 脆弱的数据库 -无论是ORM还是sql builder都有一个致命的缺点,就是没有办法进行系统上线的事前sql审核。虽然很多ORM和sql builder也提供了运行期打印sql的功能,但只在查询的时候才能进行输出。而sql builder和ORM本身提供的功能太过灵活。使得你不可能通过测试枚举出所有可能在线上执行的sql。例如你可能用sql builder写出下面这样的代码: +无论是ORM还是SQL Builder都有一个致命的缺点,就是没有办法进行系统上线的事前sql审核。虽然很多ORM和SQL Builder也提供了运行期打印sql的功能,但只在查询的时候才能进行输出。而SQL Builder和ORM本身提供的功能太过灵活。使得你不可能通过测试枚举出所有可能在线上执行的sql。例如你可能用SQL Builder写出下面这样的代码: ```go where := map[string]interface{} { @@ -201,9 +201,9 @@ res, err := historyModel.GetList(where, limit, orderBy) 对于现在7乘24服务的互联网公司来说,服务不可用是非常重大的问题。存储层的技术栈虽经历了多年的发展,在整个系统中依然是最为脆弱的一环。系统宕机对于24小时对外提供服务的公司来说,意味着直接的经济损失。个中风险不可忽视。 -从行业分工的角度来讲,现今的互联网公司都有专职的 DBA。大多数DBA并不一定有写代码的能力,去阅读sql builder的相关“拼sql”代码多多少少还是会有一点障碍。从DBA角度出发,还是希望能够有专门的事前sql审核机制,并能让其低成本地获取到系统的所有sql内容,而不是去阅读业务研发编写的sql builder的相关代码。 +从行业分工的角度来讲,现今的互联网公司都有专职的DBA。大多数DBA并不一定有写代码的能力,去阅读SQL Builder的相关“拼SQL”代码多多少少还是会有一点障碍。从DBA角度出发,还是希望能够有专门的事前SQL审核机制,并能让其低成本地获取到系统的所有SQL内容,而不是去阅读业务研发编写的SQL Builder的相关代码。 -所以现如今,大型的互联网公司核心线上业务都会在代码中把sql放在显眼的位置提供给DBA评审,举一个例子: +所以现如今,大型的互联网公司核心线上业务都会在代码中把SQL放在显眼的位置提供给DBA评审,举一个例子: ```go const (