【OceanBase专栏】脚本调用OB过程实验

Oracle && OceanBase 相关文档,希望互相学习,共同进步

风123456789~-CSDN博客


1.背景知识

1.1 概述

OceanBase存储过程,同Oracle 用来"封装"一组为了完成特定功能的 SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

PL/SQL 是数据库对 SQL 语句的扩展 ,在普通 SQL 语句的基础上增加了编程语言 的特点,把数据操作和查询语句组织在 PL/SQL 代码的过程化代码中,通过逻辑判断、循环等操作实现复杂的功能 使用 PL/SQL 可以编写具有很多高级功能的程序,能够把业务逻辑封装在数据库内部,提供更好的抽象或者安全性,同时减少了网络的交互,并且调用更快,从而提升整体性能。

1.2 执行理论

OceanBase PL 采用编译执行的方式,使用 LLVM 生成 native code,并直接把机器码装载到程序段执行,无需依赖外部 C 编译器和生成动态链接库。编译后的程序比解释执行性能提升 1.05 到 2.4 倍。参见文章:OceanBase存储过程基本使用

1)PL 缓存器(pl-cache)

OceanBase 会将 PL 编译后的可执行代码缓存在 pl-cache 中,以便对编译结果进行复用,降低 PL 编译的开销,提升整体的执行效率

如果 pl-cache 中已缓存该条命令涉及到的 PL 程序的编译结果,OceanBase 会使用该缓存的编译结果执行,否则进入正常的 PL 程序编译流程,生成的编译结果将被添加到 pl-cache 中供后续 PL 命令复用。

2)语法分析(Parser)

当一条 PL 命令涉及到的 PL程序未命中 pl-cache 的时候,会进入正常的语法分析流程。语法分析的过程把输入的 PL程序字符串转换为一颗语法树。

语法树不包含语义信息,仅仅是是字面的表示。这个过程完全使用 flex 和 bison 自动生成。输出结果是以 ParseNode 为节点的树。

3)语义分析(Resolver)

语义分析:输入的语法树转换为包含 PL 程序语义的内部数据结构表示(ObPLAST)。在此过程中,还要根据 PL 程序的语义进行语义检查,及时报错。

例如,语义检查的内容包括:

1、在使用变量时,变量是否已经进行了定义,类型是否合法。

2、同一个名字空间下符号是否有重复定义,对于重复定义的符号需要及时报错。

3、PL 程序中使用的表、列、自定义类型、包、函数等对象是否已经存在。语义分析的输出为 ObPLAST,这个结构是由符号表、类型表、异常表、标签表以及多个 ObPLStmt 和的集合,多个 stmt 对象表示 PL程序中的每条指令语句,如 IF、While、Goto。

4)代码生成(Code generator)

OceanBase PL 采用编译执行的方式,因此由语义分析输出的 ObPLAST 还会进一步进行翻译,为后面编译成可执行代码做进一步的准备。OceanBase 的 PL 采用了 LLVM 作为编译器的后端,代码生成则是为通过使用 LLVM 提供的接口,把 AST 树翻译成 IR 中间码的过程。IR 码可以输出,以核对翻译过程是否正确。

5)编译(Compiler)

通过 LLVM JIT 把 IR 码生成可执行代码的过程,生成的可执行代码会缓存到 pl-cache 中,供其他语句复用。

6)PL执行(PL Execution)

PL 执行器:负责执行编译生成的可执行代码,除了执行代码外,还执行:

1、构造当前 PL的执行环境,比如设置一些权限相关上下文、准本入参。

2、通过 SPl(Server Programming Interface)与 SQL 引擎交互,将 PL 中需要执行的 SQL 语句交给 SQL 引擎执行,并从 SQL 引擎中返回结果。

3、处理 PL 的出参以及函数的返回值等信息。

说明: SPl用于在 PL 程序中执行 SQL 操作,并返回结果。广泛应用在 PL实现的各个环节,如 procedure、function、trigger 等。

PL引擎(PL Engine)和 SQL引擎(SQL Engine)可互相交互,SQL 可以直接访问 PL引擎,比如在一个 SQL 语句中使用了用户自定义函数(function)。PL 引擎可以通过 SPI 接口访问 SQL 引擎,比如在 PL 里进行表达式计算和执行 SQL 语句。

1.3 PL 的分布式执行

OceanBase 的分布式特性,天然决定 PL的执行也是分布式的。但对于 PL本身是不会分布式执行的,PL 自身的解析、编译和执行都在某一台 OBServer 节点上完成。

当 PL 里涉及到 SQL 交互时,会通过 SPI调用 SQL Engine,由 SQL Engine 执行 SQL 语句。如果该 SQL 语句是一个分布式的,那么自然而然会进行分布式执行。分布式执行的 SQL 调用了 PL 函数时,PL 函数可能会在多台 OBServer 节点上编译执行,每台OBServer 会保证在相同的环境参数下进行编译,从而编译出的 PL具有相同的行为。

1.4 存储过程优势

● 性能优化:预编译执行,减少SQL解析和编译开销

● 代码复用:一次编写,多次调用,减少代码冗余。存储过程只在创建时进行编译,以后每次执行存储过程都不需要重新编译,而一般 SQL 语句每执行一次就编译一次,使用存储过程可提高数据库执行速度。

● 安全性:通过权限控制保护数据,避免直接表操作。参数化的存储过程可以防止 SQL 注入式攻击。

● 减少网络传输:批量操作在数据库端完成,减少客户端与服务器间的数据传输。存储过程位于服务器上,调用的时候只需要传递存储过程的名称以及参数即可,降低了网络传输的数据量。

● 事务管理:支持复杂的事务控制,确保数据一致性

2. 实验

2.1 准备工作

1)创建日志表 tbl_dayend_log

创建索引 seq_tbl_dayend_log

2)创建存储过程 get_logger1

sql 复制代码
create  table TBL_DAYEND_LOG
(
  logid         NUMBER  NOT NULL ,
  function_name VARCHAR2(200),
  table_name    VARCHAR2(200),
  data_issue    VARCHAR2(8),
  logtime       DATE,
  type          VARCHAR2(50),
  message       VARCHAR2(4000)
)
;

-- 创建序列
CREATE SEQUENCE seq_TBL_DAYEND_LOG 
START WITH 1 
INCREMENT BY 1 
MAXVALUE 9999999999999 
CYCLE 
CACHE 20;
sql 复制代码
---创建存储过程
CREATE OR REPLACE PROCEDURE GET_LOGGER1(pDataIssue    IN varchar2) is --处理信息
  --插入日志
BEGIN

  insert into TBL_DAYEND_LOG
    (LOGID,FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOGTIME, TYPE, MESSAGE)
  values
    (seq_TBL_DAYEND_LOG.nextval,'---test', '', pDataIssue, sysdate, '1', 'ok');
  commit;

END GET_LOGGER1;

存储过程,单独执行,测试也没有问题

查看表中结果:

sql 复制代码
SELECT to_char(logtime,'yyyymmdd hh24:mi:ss') aa ,t.* FROM TBL_DAYEND_LOG t;

2.2 在命令行调用

1)连接

sql 复制代码
obclient -h192.168.3.14 -P2881 -ufeng@fengoracle -p'xxx1'

2)执行

sql 复制代码
call GET_LOGGER1('2025-11');

执行截图:

再次查询表中,已多一条记录,插入成功,调用成功

3)命令调用

sql 复制代码
obclient -h192.168.3.14 -P2881 -ufeng@fengoracle -p'xxx' -e "call GET_LOGGER1('2025-08');"


或

obclient -h192.168.3.14 -P2881 -ufeng@fengoracle -p'XXX' -e"
set echo off;
call GET_LOGGER1(2025-11);
select count(*) from tbl_dayend_log;
"

截图:

从截图看,执行成功,插入正确。ok

2.3 脚本调用

1)创建通用的调用脚本 proc.sh

比如:入参3个,分别是 连接描述符、过程名、过程参数

bash 复制代码
#!/bin/bash
source ~/.bash_profile
source /home/oceanbase/test/config/config.ini

userid=$tbl_userid
packageName=$2
params=$3

echo $userid
#echo $packageName
#echo $params
##sqlplus -S $userid  <<EOF

#echo obclient $userid
echo "---调用过程开始  "

#eval "obclient $userid  -e\"
#set echo off;
#call $packageName($params);
#select count(*) from tbl_dayend_log;
#\""

obclient $userid  -e"
set echo off;
call $packageName($params);
select count(*) from tbl_dayend_log;
"

echo "---调用过结束  "

2)创建公共的参数初始化

bash 复制代码
cat config.ini
tbl_userid="-h192.168.3.14 -P2881 -ufeng@fengoracle -p'xxx^01'"
workPath=/home/oceanbase/test

3)脚本调用实验 pro_test.sh

bash 复制代码
 vim pro_test.sh
bash 复制代码
#! /bin/bash
source ~/.bash_profile
source /home/oceanbase/test/config/config.ini

if [ $# -eq 2 ]; then
  year=$1
  month=$2
else
  year=`date -d" last month" +%Y`
  month=`date -d" last month" +%m`
fi

#echo "1:$workPath/proc.sh"
#echo "2: $tbl_userid"
#echo "3:'GET_LOGGER1'"
#echo "4:$year-$month"
#echo "$tbl_userid"
#echo "----"
#echo ""$tbl_userid""

sh $workPath/proc.sh "$tbl_userid" "GET_LOGGER1" "$year-$month"

为了避免干扰,先清空表 ,再测试

调用:sh pro_test.sh

发现报错,提示貌似是无法登录,语法不对

4) 报错处理

简单还原试验:

oceanbase@appx-container test\]$echo $userid -h192.168.3.14 -P2881 -ufeng@fengoracle -p'xxx' \[oceanbase@appx-container test\]$ obclient $userid ERROR 1045 (42000): Access denied for user 'FENG'@'xxx.xxx.xxx.xxx' (using password: YES) \[oceanbase@appx-container test\]$ 发现此时就是上门的报错,无法直接识别,需要二次解析,这里用到eval 基本语法: eval \[arguments

arguments: 可以是一个或多个参数,串联成命令字符串

功能说明 :1)二次扫描命令行:先替换变量、命令替换、特殊字符,再执行命令

2)适用场景:处理复杂变量、动态生成命令

3)安全风险:避免处理用户输入,防止命令注入

按上面思路,修改proc.sh

bash 复制代码
eval "obclient $userid  -e\"
set echo off;
call $packageName($params);
select count(*) from tbl_dayend_log;
\""

执行截图:

看上图,执行成功。ok!

注意双引号中的双引号,需要转义一下哦~~~~

实验验证:ok


项目管理--相关知识

项目管理-项目绩效域1/2-CSDN博客

项目管理-项目绩效域1/2_八大绩效域和十大管理有什么联系-CSDN博客

项目管理-项目绩效域2/2_绩效域 团不策划-CSDN博客

高项-案例分析万能答案(作业分享)-CSDN博客

项目管理-计算题公式【复习】_项目管理进度计算题公式:乐观-CSDN博客

项目管理-配置管理与变更-CSDN博客

项目管理-项目管理科学基础-CSDN博客

项目管理-高级项目管理-CSDN博客

项目管理-相关知识(组织通用治理、组织通用管理、法律法规与标准规范)-CSDN博客


Oracle其他文档,希望互相学习,共同进步

Oracle-找回误删的表数据(LogMiner 挖掘日志)_oracle日志挖掘恢复数据-CSDN博客

oracle 跟踪文件--审计日志_oracle审计日志-CSDN博客

ORA-12899报错,遇到数据表某字段长度奇怪现象:"Oracle字符型,长度50"但length查却没有50_varchar(50) oracle 超出截断-CSDN博客

EXP-00091: Exporting questionable statistics.解决方案-CSDN博客

Oracle 更换监听端口-CSDN博客

相关推荐
爬山算法5 小时前
Redis(158)Redis的主从同步问题如何解决?
数据库·redis·缓存
2501_941148157 小时前
多语言微服务架构与边缘计算技术实践:Python、Java、C++、Go深度解析
数据库
w***z508 小时前
MYSQL 创建索引
数据库·mysql
章鱼哥7309 小时前
[特殊字符] SpringBoot 自定义系统健康检测:数据库、Redis、表统计、更新时长、系统性能全链路监控
java·数据库·redis
5***E6859 小时前
MySQL:drop、delete与truncate区别
数据库·mysql
记得记得就1519 小时前
【MySQL数据库管理】
数据库·mysql·oracle
Austindatabases10 小时前
给PG鸡蛋里面挑骨头--杭州PostgreSQL生态大会
数据库·postgresql
秃了也弱了。10 小时前
MySQL空间函数详解,MySQL记录经纬度并进行计算
android·数据库·mysql
星环处相逢10 小时前
MySQL数据库管理从入门到精通:全流程实操指南
数据库·mysql