“工藤邦明先生似乎是个诚实可靠的人。和他结婚,你和美里获得幸福的几率应该比较高。请把我完全忘记,千万不要有罪恶感。因为如果你过得不幸福,我的行为将会完全成为徒劳。”
---《嫌疑人X的献身》

看到这里别慌,笔者写这篇文章的目的不是为了想要跟你探讨关于这部电影里的那些哲学命题:
拟一个别人无法解答的问题和解开这个问题,何者更困难?
自己想出的答案和判断别人的答案,何者更容易?
只是作为一个DBA(逗B啊)随着对接项目的增多,难免会需要给相关的开发解答一些存在共性的数据库问题。所以在笔者的从职生涯里,关于故障处理有一些比较头大的场景:
一类是那种你需要参考古老的DSI(Oracle的技术内部文档但很早就停止更新了)去进行推演验证的,抑或使用场景极端,碰上了BUG。
还有一类问题就比较尴尬了,比如 开发找到你“我也不知道怎么了,感觉环境有问题”。
朋友,你拟问题的时候是不是把我想像成了《嫌疑人X的献身》里的智商爆表的物理学家。生怕线索给多了,问题太简单就给解决了就没意思了,显得我不厉害?

用人话来比喻一下:一个病人得了肾结石,他到医院看病,医生问诊的时候他虽然不用明确的告诉医生他是由于肾结石导致的腰部钝痛,需要肌肉注射20mg黄体酮来扩张、松弛输尿管平滑肌……
他不用清楚这个病的病理,也不用去理解黄体酮的药理。他只需要跟医生描述病情的时候他能够分得清他钝痛的部位是腰,那里不是脑袋,也不是手,不是胳膊不是腿。医生只要再问问他是不是伴有恶心,呕吐的症状。到这线索就明朗了,医生再让他去拍个B超到这基本就能确诊了。当然自己的身体,我们看着他长大(这句话有点怪怪的),所以我们能够分得清胳膊脑袋腿,这些关于生理构造的基本认知能够很大程度的降低我们于医生沟通是有效信息传递的难度。
对于开发人员,但凡你需要将数据落地存储于一个永久介质以便你能复用这些数据,就永远要跟数据库打交道。因此,笔者亦希望通过这篇文章介绍一条SQL的操作执行在ORACLE数据库的历程。能够让你能够分得清数据库的“脑袋”“胳膊”“腿”,让你在跟DBA打交道时少走些弯路。
DBA哲学三问
我是谁,我在哪里,我要去哪。人生三大命题,与你的人生一样,一条sql其实也需要搞懂这三大哲学命题。
先从连接串下手:它决定了你连接的是哪个数据库。不论是IDE工具亦或者是sqlplus直接连接数据库用户名密码之外连接串是必须填写的。
192.xx.xx.1:1521/xxxServ 完整的oracle连接串就由这3部分组成:
目标机器IP地址 192.xx.xx.1
监听工作端口(默认是1521,只有少数的ORACLE数据库环境会把监听配置在其他端口)
oracle的服务名或(SIDname) xxxServ。当然大部分会通过配置tnsname来简化这个链接串的配置。

(1)客户端使用SQL Plus或ODBC请求连接,监听接受客户端的TCP连接,并获取客户端发过来的TNS数据包。
这一步容易出的问题有两类:
比如客户端的ODBC驱动太老,或者Oracle 的Client没有被正确安装
在网络环境中默认的数据库端口的1521 tcp协议被限制
常规处理:客户端测试,ODBC测试,Telnet网络端口协议测试
(2)监听进程打开用于与子进程通信的管道,同时fork一个子进程,称为“监听子进程1”的子进程,然后监听进程一直等待,直到这个“监听子进程1”结束。
(3)监听子进程1 Fork出子进程2。
(4)完成上面一步,子进程1马上退出并结束子进程1。
(5)子进程2收集本进程所在的主机名丶IP地址及进程号等信息,并把子进程2重名成server process(这里我们也把server process叫前台进程或叫服务器进程),申请占用一小块PGA内存。
注:第二到第五步,oracle已经把这块工作流封装的很好很快了,几乎不会出问题,但是到了第五步这里,可能会由于oracle的运行参数process限制以及session限制导致亦或者是pga完全耗尽(单个session占的pga内存信息可以通过v$session,v$process_memory,v$process几个性能管理视图查询获取)。当然一般碰上这类问题,会有十分明显的报错,并且报错很直接。
(6)前台进程把主机名丶IP地址及进程号发送给监听进程。
(7)监听进程收到前台进程的信息,并返回客户端的信息(比如用户密码环境变量等)给前台进程。
(8)前台进程查询USER$丶PROFILE$等数据字典,校验用户名密码是否合法,如果用户密码错误就报错用户名密码无效,否则就与客户端进行交互。
(9)客户端收到前台进程的信息与之交互,整个连接创建完成。
以上过程,用理发这个活动来解释一下:

我(Client程序)需要到理发店(DB 数据库)找造型总监Tony老师(建立连接后指定给client的会话资源)理发(数据操作即事务之后以一条update为例),我要完成理发这件事,我需要找到这家理发店(连接串即地址)。
但是我不是这家店的员工(client非DBservevice的后台进程),我需要到门口找到业务员(server端的1521监听,负责监听远程连接client通过他完成与数据库建立连接)。
关于理发这件事我可能会碰上如下情况:
这件店地址不对(即连接串无效)
我自身不能进这家理发店(Client程序错误或者ODBC驱动太成就有问题)
门口接待的业务员没了(监听程序未启动,或DB处于维护状态DBA将监听关闭
身份验证失效(会员卡密码忘了)
这家店太忙了,不论是tony老师还是peter老师都排满了(session或者process达到db的配置允许上限,PGA无法给client连接分配内存)
好了,客户端跟数据库的远程连接已经建立,你可以开始执行sql了。
明天请听笔者继续啰嗦。

本文作者:崔霄(点融黑帮),目前就职于点融网infra团队,DBA一枚。喜欢徒步、开车。
随着点融网新一轮融资,点融网即将开始大规模的扩张,需要各种优秀人才的加入,如果你觉得自己够优秀,欢迎加入我们!获取更多职位信息,请关注点融黑帮。



