dbms.buffer.BufferAccess

本文介绍了一个缓存管理系统的设计实现,包括缓存池管理、时钟淘汰算法、最近最少使用(LRU)算法以及如何处理锁定的关键块。系统采用单例模式,并支持不同类型的特殊块如元数据块、模式块等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class BufferAccess{

         public static final int cacheSize= 16*1024*1024/DiskManagement.BLOCK_SIZE;

         private static BufferAccess bufferAccessInstance= null;

         private DiskManagement diskManagement;

        

          /**
         * 锁住的关键块,只在文件打开时放入,文件关闭时取出
         * 存放mata, schema, index block, index info block
         */
          private Set LockedBlockSet = new HashSet();
       

          /**
          * 块缓冲池,load factor 0.75,确保没有rehash发生
          * 方便起见,只存DataBlock
          */

           private Map blockCache=new HashMap((int)(cacheSize/0.75));

          

           /**
          * 时钟算法的环中的当前元素,下一个元素才是淘汰候选对象
          */
          private DataBlock lastUsedBlock;
          //stop here , review the clock algo and LRU algo

         

           private BufferAccess(){

           this.diskManagement = DiskManagement.getInstance();

           }

 

           public static BufferAccess getInstance() {

            if(bufferAccessInstance == null)

              bufferAccessInstance = new BufferAccess();

              return bufferAccessInstance;

            }

 

             /**
              * 从buffer中得到一个数据块
              * @param fileID
              * @param blockID
              * @return
              */

               public DataBlock getBlock (Integer fileID, int blockID){

                 IDEntry id =new IDEntry (fileID,blockID);

                 DataBlock block =(DataBlock) blockCache.get(id);

                 if(block !=null){

                      block.keepNextTurn=true;

                      return block;

                  }

                 

                  byte[] blockByte=diskManagement.readFromDisk(fileID,blockID);

                  block =new DataBlock(blockByte,id);

                  ensureSpace();

                  addBlock(block);

                  blockCache.put(id,block);

                  return block;

                  }

 

                  void reloadDataBlock(DataBlock nullBlock){

                   IDEntry id=nullBlock.getIdEntry();

                   DataBlock block =(DataBlock) blockCache.get(id);

                  //内存中没有相同id的块

                   if(block ==null)

                    {

                       byte[] blockByte=diskManagement.readFromDisk(id.getFileID(),id.getBlockID());

                       ensureSpace();

                       nullBlock.setData(blockByte);

                       addBlock(nullBlock);

                       blockCache.put(id,nullBlock);

                       return;

                      }

                      //内存中有相同id的块,需要用到identical指针

                      nullBlock.setData(block.getData());

                      nullBlock.identical=block.identical;

                      block.identical = nullBock;

                    }

                

                      /**
                       * 得到一个锁住的块,该块不参与LRU算法的竞争
                       * 只可能是MetaBlock,SchemaBlock,IndexBlock
                       * @param fileID
                       * @param blockID
                       * @param blockType
                       * @return
                       */

                         public Block getLockedBlock(Integer fileID, int blockID, int blockType) {

                              IDEntry id = new IDEntry(fileID, blockID);

                              Block block = null;

                              byte[] blockByte = diskManagement.readFromDisk(fileID, blockID);
                              switch(blockType){

                                case Block.META_BLOCK:

                                        block= new MetaBlock(blockByte,id);

                                        break;

                                case Block.SCHEMA_BLOCK:
                                        block = new SchemaBlock(blockByte,id);

                                        break;

                                case Block.INDEX_BLOCK:

                                        block = new IndexBlock( blockByte, id );

                                        break;

                                 case Block.INDEX_INFO_BLOCK:

                                         block = new IndexInfoBlock( blockByte, id);

                                         break;  

                                 default:
                                 System.out.println(" illegal block type argument ");
                                }

                               LockBlockSet.add(block);s

<think>我们正在处理一个PL/SQLDeveloper中出现的"Accessviolationataddress"错误。根据用户提供的错误信息,具体错误地址是00000000006B23C9在plsqldev.exe模块中。虽然引用内容主要讨论的是ORA错误和触发器问题,但我们需要专注于访问违规错误。访问违规(AccessViolation)通常是由于程序试图访问未被分配的内存地址或无权访问的内存区域引起的。在PL/SQLDeveloper环境中,这可能是由以下原因引起的:1.**PL/SQLDeveloper软件缺陷**:特定版本的plsqldev.exe可能存在bug。2.**与Oracle客户端库不兼容**:使用的Oracle客户端(OCI)版本与PL/SQLDeveloper不兼容。3.**损坏的安装**:PL/SQLDeveloper或Oracle客户端的安装文件损坏。4.**冲突的第三方软件**:如防病毒软件、其他开发工具等干扰。5.**系统问题**:如内存故障、操作系统更新问题等。解决方案:**步骤1:更新PL/SQLDeveloper**访问[官方网站](https://www.allroundautomations.com/),下载并安装最新版本。旧版本可能存在已知问题。**步骤2:检查Oracle客户端兼容性**确保使用32位Oracle客户端(即使系统是64位),因为PL/SQLDeveloper是32位应用程序。推荐使用与数据库版本匹配的OracleInstantClient32位版本。**步骤3:重新安装Oracle客户端**卸载当前Oracle客户端,从Oracle官网下载新的32位InstantClient,并解压到无空格和特殊字符的路径(如`D:\oracle\instantclient_19_3`)。设置环境变量:-`PATH`:包含InstantClient目录-`TNS_ADMIN`:指向包含`tnsnames.ora`的目录**步骤4:配置PL/SQLDeveloper**在PL/SQLDeveloper中设置正确的OCI路径:-OracleHome:InstantClient目录(如`D:\oracle\instantclient_19_3`)-OCILibrary:InstantClient目录下的oci.dll(如`D:\oracle\instantclient_19_3\oci.dll`)**步骤5:以管理员身份运行**右键点击PL/SQLDeveloper快捷方式,选择“以管理员身份运行”。**步骤6:排除软件冲突**临时禁用防病毒软件,关闭其他应用程序,尤其是其他Oracle工具(如Toad、SQLDeveloper)。**步骤7:修复系统文件**打开命令提示符(管理员),运行:```sfc/scannow```**步骤8:检查内存**运行Windows内存诊断工具,排除内存故障。**步骤9:创建新的配置文件**重命名PL/SQLDeveloper的配置文件目录(位于`%APPDATA%\PLSQLDeveloper`),然后重新启动PL/SQLDeveloper,让其生成新的配置。**步骤10:查看事件查看器**在Windows事件查看器中查看应用程序日志,寻找与plsqldev.exe相关的错误事件。如果以上步骤无法解决,可能需要联系PL/SQLDeveloper的技术支持,提供具体的错误地址(00000000006B23C9)以便他们定位问题。根据引用内容,虽然不直接相关,但注意以下:-引用[1]提到并行查询相关的错误(ORA-07445),这通常是数据库服务器端的问题,与客户端访问违规不同。-引用[2]提到登录触发器错误(ORA-00604),这同样发生在数据库端。-引用[3]是查看SQL执行计划的示例。因此,我们当前的问题属于客户端应用程序崩溃,而非数据库错误。生成相关问题:1.如何确定PL/SQLDeveloper的版本信息?2.如何配置PL/SQLDeveloper使用多个Oracle客户端?3.访问违规错误是否可能由PL/SQL代码引起?4.除了访问违规,PL/SQLDeveloper还有哪些常见错误?</think>### PL/SQL Developer "Access Violation at Address" 错误解决方案 #### 核心原因分析 1. **内存管理冲突** - PL/SQL Dev 进程尝试访问未分配内存区域(地址 `00000000006B23C9`) - 常见于大查询/并行操作导致内存超限(参考 ORA-04030 错误[^1]) ```admonish 错误特征:`kxfpqrclb()+71` 表明并行查询服务器中断(ORA-10382)[^1] ``` 2. **OCI 库不兼容** - 32位/64位 Oracle Instant Client 与 PL/SQL Dev 版本冲突 - `plsqldev.exe` 模块加载错误内存地址 3. **递归 SQL 级联故障** - 数据库级触发器(如 `AFTER LOGON`)引发递归 SQL 错误(ORA-00604)[^2] ```sql -- 示例:可能引发递归错误的登录触发器 CREATE OR REPLACE TRIGGER sys.logon_audit AFTER LOGON ON DATABASE BEGIN INSERT INTO audit_table VALUES (SYS_CONTEXT('USERENV','OS_USER')); END; ``` 4. **执行计划冲突** - 复杂 SQL 的优化器计划异常(参考 `v$sql_plan` 查询[^3]) ```sql SELECT operation, object_name, cost FROM v$sql_plan WHERE address = HEXTORAW('82157784'); -- 替换实际地址 ``` --- ### 分步解决方案 #### ▶ **第一步:缓解内存压力** 1. **降低并行度**: ```sql ALTER SESSION SET PARALLEL_DEGREE_POLICY = MANUAL; ALTER SESSION SET PARALLEL_MIN_SERVERS = 1; ``` 2. **优化大查询**: - 使用 `/*+ NO_PARALLEL */` 提示禁用并行 - 分页处理:`ROWNUM <= 1000` #### ▶ **第二步:修复 OCI 库冲突** 1. **强制使用 32 位客户端**: - 下载 [Oracle 32-bit Instant Client](https://www.oracle.com/database/technologies/instant-client/win32-downloads.html) - 配置路径: ```ini Oracle Home = C:\Oracle\instantclient_19_3 OCI Library = C:\Oracle\instantclient_19_3\oci.dll ``` 2. **清除异常会话**: ```sql SELECT sid, serial# FROM v$session WHERE status = 'KILLED'; ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE; ``` #### ▶ **第三步:处理递归错误** 1. **禁用问题触发器**: ```sql ALTER TRIGGER sys.logon_audit DISABLE; ``` 2. **检查递归 SQL**: ```sql SELECT * FROM dba_errors WHERE name LIKE '%LOGON_AUDIT%'; ``` #### ▶ **第四步:修正执行计划** 1. **锁定问题 SQL**: ```sql SELECT sql_id, sql_text FROM v$sql WHERE executions > 1000 AND buffer_gets > 1000000; ``` 2. **添加优化器提示**: ```sql SELECT /*+ OPTIMIZER_FEATURES_ENABLE('11.2.0.4') */ ... ``` --- ### 高级诊断方法 1. **内存转储分析**: ```bash oradebug dump errorstack 3 oradebug tracefile_name -- 获取跟踪文件路径 ``` 2. **事件 10046 跟踪**: ```sql ALTER SESSION SET events '10046 trace name context forever, level 12'; -- 重现错误后关闭 ALTER SESSION SET events '10046 trace name context off'; ``` 3. **检查核心转储**: ```bash strings /opt/app/oracle/diag/.../PRODB_p135_15651.trc | grep SIGSEGV ``` > **关键指标**:当出现 `ORA-07445: exception encountered: core dump` 时[^1],需检查操作系统日志(`/var/log/messages`) --- ### 预防措施 1. **资源限制配置**: ```sql CREATE PROFILE dev_user LIMIT SESSIONS_PER_USER 10 PGA_AGGREGATE_LIMIT 2G; ``` 2. **定期清理无效对象**: ```sql BEGIN DBMS_UTILITY.compile_schema('APP_USER', compile_all => FALSE); END; ``` 3. **版本兼容性检查**: ```sql SELECT * FROM v$version; -- PL/SQL Dev 版本需匹配 Oracle Client 主版本号 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值