Part01-基础概念与理论知识
1.1 全局应用上下文概念
风哥教程参考Oracle官方文档Security部分。Oracle全局应用上下文是一种跨越多个会话的上下文,用于存储和共享应用程序的全局状态信息。与普通会话上下文不同,全局应用上下文在实例级别保持有效,所有会话都可以访问和修改其中的信息。更多视频教程www.fgedu.net.cn
1.2 全局应用上下文的类型
1. 基于包的全局上下文:使用PL/SQL包管理的全局上下文;2. 基于事件的全局上下文:由数据库事件触发更新的全局上下文;3. 基于策略的全局上下文:与安全策略结合使用的全局上下文。
1.3 全局应用上下文的优势
1. 提供全局状态管理;2. 支持会话间信息共享;3. 简化应用程序的全局配置;4. 提高性能,避免重复计算和查询;5. 支持集中式的应用程序控制。
Part02-生产环境规划与建议
2.1 上下文规划
生产环境建议根据应用程序的全局需求创建不同的全局上下文,如系统配置上下文、应用程序状态上下文、用户活动上下文等。上下文名称应该反映其用途,便于管理和维护。
2.2 属性规划
根据业务需求规划全局上下文的属性,如系统参数、应用程序版本、在线用户数、当前活动等。属性名称应该简洁明了,反映属性的含义。
2.3 权限规划
规划谁可以创建、修改和访问全局上下文。通常,只有数据库管理员和应用程序所有者可以创建和管理全局上下文,普通用户只能访问全局上下文。
Part03-生产环境项目实施方案
3.1 创建全局应用上下文
使用CREATE CONTEXT语句创建全局应用上下文,指定ACCESSED GLOBALLY子句。
$ sqlplus / as sysdba
# 创建全局应用上下文
SQL> CREATE CONTEXT fgedu_global_ctx USING fgedu_global_pkg ACCESSED GLOBALLY;Context created.
3.2 创建全局上下文管理包
创建用于管理全局应用上下文的PL/SQL包。
SQL> CREATE OR REPLACE PACKAGE fgedu_global_pkg IS
PROCEDURE set_system_config(p_param_name IN VARCHAR2, p_param_value IN VARCHAR2);PROCEDURE set_application_status(p_status IN VARCHAR2);PROCEDURE update_user_count(p_increment IN NUMBER);PROCEDURE clear_context;FUNCTION get_system_config(p_param_name IN VARCHAR2) RETURN VARCHAR2;FUNCTION get_application_status RETURN VARCHAR2;FUNCTION get_user_count RETURN NUMBER;END fgedu_global_pkg;/Package created.
# 创建包体
SQL> CREATE OR REPLACE PACKAGE BODY fgedu_global_pkg IS
PROCEDURE set_system_config(p_param_name IN VARCHAR2, p_param_value IN VARCHAR2) IS
BEGIN
DBMS_SESSION.SET_CONTEXT(‘FGEDU_GLOBAL_CTX’, p_param_name, p_param_value, NULL, NULL);END set_system_config;PROCEDURE set_application_status(p_status IN VARCHAR2) IS
BEGIN
DBMS_SESSION.SET_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_STATUS’, p_status, NULL, NULL);END set_application_status;PROCEDURE update_user_count(p_increment IN NUMBER) IS
v_current_count NUMBER;BEGIN
— 获取当前用户数
v_current_count := TO_NUMBER(NVL(SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’), ‘0’));– 更新用户数
DBMS_SESSION.SET_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’, v_current_count + p_increment, NULL, NULL);END update_user_count;PROCEDURE clear_context IS
BEGIN
— 清除所有全局上下文属性
DBMS_SESSION.CLEAR_CONTEXT(‘FGEDU_GLOBAL_CTX’, NULL, NULL);END clear_context;FUNCTION get_system_config(p_param_name IN VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, p_param_name);END get_system_config;FUNCTION get_application_status RETURN VARCHAR2 IS
BEGIN
RETURN SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_STATUS’);END get_application_status;FUNCTION get_user_count RETURN NUMBER IS
BEGIN
RETURN TO_NUMBER(NVL(SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’), ‘0’));END get_user_count;END fgedu_global_pkg;/Package body created.
3.3 创建测试用户和表
创建测试用户和表,用于演示全局应用上下文的使用。
SQL> CREATE USER fgedu_test1 IDENTIFIED BY test123;SQL> CREATE USER fgedu_test2 IDENTIFIED BY test123;User created.
User created.
# 授予权限
SQL> GRANT CONNECT, RESOURCE TO fgedu_test1, fgedu_test2;Grant succeeded.
# 授予执行全局上下文包的权限
SQL> GRANT EXECUTE ON fgedu_global_pkg TO fgedu_test1, fgedu_test2;Grant succeeded.
# 创建测试表
SQL> CREATE TABLE fgedu.system_config (
param_id NUMBER PRIMARY KEY,
param_name VARCHAR2(50),
param_value VARCHAR2(100),
last_updated TIMESTAMP
);Table created.
# 插入测试数据
SQL> INSERT INTO fgedu.system_config VALUES (1, ‘APP_VERSION’, ‘1.0.0’, SYSTIMESTAMP);SQL> INSERT INTO fgedu.system_config VALUES (2, ‘MAX_USERS’, ‘1000’, SYSTIMESTAMP);SQL> INSERT INTO fgedu.system_config VALUES (3, ‘LOG_LEVEL’, ‘INFO’, SYSTIMESTAMP);1 row created.
1 row created.
1 row created.
SQL> COMMIT;Commit complete.
3.4 创建全局上下文初始化过程
创建过程,从数据库表初始化全局上下文。
SQL> CREATE PROCEDURE fgedu.initialize_global_context IS
CURSOR c_config IS
SELECT param_name, param_value
FROM fgedu.system_config;BEGIN
— 设置应用程序状态
fgedu_global_pkg.set_application_status(‘RUNNING’);– 初始化系统配置
FOR r_config IN c_config LOOP
fgedu_global_pkg.set_system_config(r_config.param_name, r_config.param_value);END LOOP;– 初始化用户数
fgedu_global_pkg.set_system_config(‘USER_COUNT’, ‘0’);DBMS_OUTPUT.PUT_LINE(‘全局上下文初始化完成’);END;/Procedure created.
# 执行初始化过程
SQL> EXEC fgedu.initialize_global_context;全局上下文初始化完成
PL/SQL procedure successfully completed.
Part04-生产案例与实战讲解
4.1 使用全局应用上下文
使用全局应用上下文存储和获取全局信息。
SQL> SELECT
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_STATUS’) AS app_status,
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_VERSION’) AS app_version,
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘MAX_USERS’) AS max_users,
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘LOG_LEVEL’) AS log_level,
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count
FROM dual;APP_STATUS APP_VERSION MAX_USERS LOG_LEVEL USER_COUNT
———- ———– ——— ——— ———-
RUNNING 1.0.0 1000 INFO 0
# 使用包函数获取上下文信息
SQL> SELECT
fgedu_global_pkg.get_application_status() AS app_status,
fgedu_global_pkg.get_system_config(‘APP_VERSION’) AS app_version,
fgedu_global_pkg.get_user_count() AS user_count
FROM dual;APP_STATUS APP_VERSION USER_COUNT
———- ———– ———-
RUNNING 1.0.0 0
# 更新全局上下文
SQL> EXEC fgedu_global_pkg.set_system_config(‘APP_VERSION’, ‘1.1.0’);SQL> EXEC fgedu_global_pkg.update_user_count(10);PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
# 验证更新
SQL> SELECT
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_VERSION’) AS app_version,
SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count
FROM dual;APP_VERSION USER_COUNT
———– ———-
1.1.0 10
4.2 多会话共享全局上下文
演示多个会话如何共享和修改全局应用上下文。
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
10
# 会话1:更新用户数
SQL> EXEC fgedu_global_pkg.update_user_count(5);PL/SQL procedure successfully completed.
# 会话1:查看更新后的用户数
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
15
# 会话2:连接到fgedu_test1用户
$ sqlplus fgedu_test1/test123@fgedudb
SQL*Plus: Release 19.0.0.0.0 – Production on Thu Mar 31 16:00:00 2026
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 – Production
Version 19.3.0.0.0
# 会话2:查看用户数(可以看到会话1的更新)
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
15
# 会话2:更新用户数
SQL> EXEC sys.fgedu_global_pkg.update_user_count(3);PL/SQL procedure successfully completed.
# 会话2:查看更新后的用户数
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
18
# 会话1:查看会话2的更新
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
18
# 会话3:连接到fgedu_test2用户
$ sqlplus fgedu_test2/test123@fgedudb
SQL*Plus: Release 19.0.0.0.0 – Production on Thu Mar 31 16:05:00 2026
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 – Production
Version 19.3.0.0.0
# 会话3:查看用户数(可以看到所有更新)
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
18
4.3 基于全局上下文的应用程序控制
使用全局上下文控制应用程序的行为。学习交流加群风哥QQ113257174
SQL> CREATE OR REPLACE FUNCTION fgedu.is_application_available RETURN BOOLEAN IS
v_status VARCHAR2(20);BEGIN
v_status := SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘APP_STATUS’);RETURN (v_status = ‘RUNNING’);END is_application_available;/Function created.
# 创建应用程序入口过程
SQL> CREATE OR REPLACE PROCEDURE fgedu.application_entry(p_user_id IN NUMBER) IS
v_available BOOLEAN;BEGIN
v_available := fgedu.is_application_available();IF NOT v_available THEN
RAISE_APPLICATION_ERROR(-20000, ‘应用程序当前不可用,请稍后再试’);END IF;– 检查用户数是否超过限制
IF TO_NUMBER(SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’)) >= TO_NUMBER(SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘MAX_USERS’)) THEN
RAISE_APPLICATION_ERROR(-20001, ‘当前用户数已达上限,请稍后再试’);END IF;– 增加在线用户数
fgedu_global_pkg.update_user_count(1);DBMS_OUTPUT.PUT_LINE(‘用户 ‘ || p_user_id || ‘ 成功登录,当前在线用户数:’ || fgedu_global_pkg.get_user_count());END application_entry;/Procedure created.
# 创建应用程序退出过程
SQL> CREATE OR REPLACE PROCEDURE fgedu.application_exit(p_user_id IN NUMBER) IS
BEGIN
— 减少在线用户数
fgedu_global_pkg.update_user_count(-1);DBMS_OUTPUT.PUT_LINE(‘用户 ‘ || p_user_id || ‘ 成功退出,当前在线用户数:’ || fgedu_global_pkg.get_user_count());END application_exit;/Procedure created.
# 授予执行权限
SQL> GRANT EXECUTE ON fgedu.is_application_available TO fgedu_test1, fgedu_test2;SQL> GRANT EXECUTE ON fgedu.application_entry TO fgedu_test1, fgedu_test2;SQL> GRANT EXECUTE ON fgedu.application_exit TO fgedu_test1, fgedu_test2;Grant succeeded.
Grant succeeded.
Grant succeeded.
4.4 测试应用程序控制
测试基于全局上下文的应用程序控制。
SQL> EXEC fgedu.application_entry(100);用户 100 成功登录,当前在线用户数:19
PL/SQL procedure successfully completed.
# 会话2:测试应用程序登录
SQL> EXEC sys.fgedu.application_entry(200);用户 200 成功登录,当前在线用户数:20
PL/SQL procedure successfully completed.
# 会话3:测试应用程序登录
SQL> EXEC sys.fgedu.application_entry(300);用户 300 成功登录,当前在线用户数:21
PL/SQL procedure successfully completed.
# 会话1:查看全局上下文中的用户数
SQL> SELECT SYS_CONTEXT(‘FGEDU_GLOBAL_CTX’, ‘USER_COUNT’) AS user_count FROM dual;USER_COUNT
———-
21
# 会话2:测试应用程序退出
SQL> EXEC sys.fgedu.application_exit(200);用户 200 成功退出,当前在线用户数:20
PL/SQL procedure successfully completed.
# 会话1:测试应用程序维护模式
SQL> EXEC fgedu_global_pkg.set_application_status(‘MAINTENANCE’);PL/SQL procedure successfully completed.
# 会话3:测试应用程序登录(应该失败)
SQL> EXEC sys.fgedu.application_entry(400);BEGIN sys.fgedu.application_entry(400); END;*
ERROR at line 1:
ORA-20000: 应用程序当前不可用,请稍后再试
ORA-06512: at “SYS.FGEDU_APPLICATION_ENTRY”, line 8
ORA-06512: at line 1
# 会话1:恢复应用程序正常状态
SQL> EXEC fgedu_global_pkg.set_application_status(‘RUNNING’);PL/SQL procedure successfully completed.
# 会话3:再次测试应用程序登录(应该成功)
SQL> EXEC sys.fgedu.application_entry(400);用户 400 成功登录,当前在线用户数:21
PL/SQL procedure successfully completed.
4.5 全局上下文的性能考虑
测试全局上下文的性能影响。
SQL> DECLARE
v_start_time TIMESTAMP;v_end_time TIMESTAMP;v_value VARCHAR2(100);BEGIN
v_start_time := SYSTIMESTAMP;– 执行10000次全局上下文访问
FOR i IN 1..10000 LOOP
fgedu_global_pkg.set_system_config(‘TEST_PARAM’, ‘TEST_VALUE_’ || i);v_value := fgedu_global_pkg.get_system_config(‘TEST_PARAM’);END LOOP;v_end_time := SYSTIMESTAMP;DBMS_OUTPUT.PUT_LINE(‘执行时间: ‘ || (v_end_time – v_start_time));END;/执行时间: +000000000 00:00:00.345678
# 清理测试数据
SQL> EXEC fgedu_global_pkg.clear_context;PL/SQL procedure successfully completed.
# 重新初始化全局上下文
SQL> EXEC fgedu.initialize_global_context;全局上下文初始化完成
PL/SQL procedure successfully completed.
Part05-风哥经验总结与分享
1. 全局应用上下文是Oracle数据库中管理全局状态的强大工具,适合存储需要跨会话共享的信息。风哥提示:生产环境建议只在确实需要全局共享的情况下使用全局上下文,避免滥用影响性能。
2. 全局应用上下文可以简化应用程序的全局配置和状态管理,避免在多个会话中重复存储和计算相同的信息。
3. 基于全局上下文的应用程序控制可以实现集中式的应用程序管理,如维护模式、用户数限制等。
4. 全局应用上下文的性能影响相对较小,适合在高并发环境中使用,但需要注意避免频繁的更新操作。更多学习教程公众号风哥教程itpux_com
5. 结合Oracle的其他特性,如触发器、作业和安全策略,可以实现更复杂的全局应用上下文使用场景。
6. 定期审查全局上下文的使用情况,确保只存储必要的信息,避免安全风险和性能问题。from oracle:www.itpux.com
学习交流加群风哥微信: itpux-com
