manually create a new oracle database

本文介绍了一种不使用DBCA的手动创建Oracle 11g数据库的方法。步骤包括:准备初始化参数文件、设置环境变量、创建目录、启动SQL*Plus会话、运行创建数据库的脚本等。此外还介绍了如何通过SQL*Plus运行Oracle自带的catalog.sql和catproc.sql脚本来完成数据库创建后的初始化工作。
using [b]dbca[/b] to create a database is preferred approach:
http://docs.oracle.com/cd/B28359_01/server.111/b28310/create002.htm

The following describes MANUALLY creating a new oracle database:

Oracle online doc reference:
[u]http://docs.oracle.com/cd/B28359_01/server.111/b28310/create003.htm[/u]

Reference 2:
Search youtube "Oracle DBA Justin - How to create an 11g Oracle database"
http://www.youtube.com/watch?v=QCYIo2Pkke4

1. Create the database ini file under location "$ORACLE_HOME/database".
The file name must be "initMydbname.ora". for instance, for database
SID(less than 8 characters?) "AWCC", the file would be
"$ORACLE_HOME/database/initAWCC.ora".

two mandatory params are "db_name" and "control_files". for example:
db_name=AWCC and control_files="/u02/oracle/databae/oradata
/AWCC/control_01.ctl"

2. create the directories to store database files, this can be anywhere, like:
mkdir /u02/database/oradata/AWCC

3. set env variables:
export ORACLE_HOME=Oracel_installation_dir/product/11.x.x/db_1
export ORACEL_SID=AWCC

4. sqlplus to the database to create, ie, AWCC
sqlplus / as sysdba

5. startup the database, though it's not created yet!
SQL>startup;

6. run your create database script (create database AWCC ...) from sqlplus
SQL>@full_path_to_your_create_db_script;

After complete successfully, database files would be created, including
control files(.CTL), log files(.LOG) and data files (.DBF) etc.

7. run two Oracle scripts "catalog.sql" and "catproc.sql" from sqlplus, these
files are located at $ORACLE_HOME/rdbms/admin

SQL>@?/rdbms/admin/catalog.sql;
SQL>@?/rdbms/admin/cataproc.sql;

? means $ORACLE_HOME

8. restart your database
SQL>shutdown;
SQL>startup;

Warning: these only the steps to create a new Oracle database on the video, not yet tested on a linux machine.
<think> 我们正在讨论的是在AOP切面中创建线程池来执行定时任务(每分钟重置计数器)的场景。 用户建议手动创建线程池(Manually create thread pool is better),这通常是因为: 1. 可以更精确地控制线程池参数(核心线程数、队列类型等) 2. 避免使用Executors工厂方法可能导致的资源耗尽问题(如newCachedThreadPool无限创建线程) 在之前的实现中,我们使用了: Executors.newSingleThreadScheduledExecutor() 这实际上是一个单线程的调度线程池。但使用Executors工厂方法在某些规范中不被推荐,因为可能隐藏了不合理的参数设置。 改进方案:手动创建ScheduledThreadPoolExecutor实例,并显式设置参数。 修改后的构造方法如下: ```java public TrackingPointAspect() { // 手动创建单线程的调度线程池 ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() { private final AtomicInteger threadCount = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("tracking-stat-reset-" + threadCount.getAndIncrement()); thread.setDaemon(true); // 设置为守护线程,避免阻止JVM关闭 return thread; } }); // 设置线程池在shutdown时的策略:取消周期任务 executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); // 每分钟重置计数器 executor.scheduleAtFixedRate(() -> { long count = methodCallCounter.getAndSet(0); log.info("===== 方法调用统计重置 ====="); log.info("上一分钟总调用次数: {}", count); }, 0, 60, TimeUnit.SECONDS); } ``` ### 手动创建线程池的优势 1. **线程命名可控** 自定义线程名称(如`tracking-stat-reset-1`)便于问题排查 2. **线程类型控制** 明确设置为守护线程(`setDaemon(true)`),不会阻止JVM正常关闭 3. **资源释放策略** 配置`setContinueExistingPeriodicTasksAfterShutdownPolicy(false)`确保Spring关闭时终止任务 4. **避免OOM风险** 直接使用`ScheduledThreadPoolExecutor`而非`Executors`,避免后者可能产生的无界队列问题 ### 注意事项 - **线程池关闭** 添加`@PreDestroy`方法优雅关闭线程池: ```java @PreDestroy public void destroy() { executor.shutdownNow(); } ``` - **异常处理** 在定时任务中添加try-catch避免任务因异常终止: ```java executor.scheduleAtFixedRate(() -> { try { // 重置逻辑 } catch (Exception e) { log.error("重置计数器异常", e); } }, ...); ``` ### 完整切面代码调整 ```java @Slf4j @Aspect @Component public class TrackingPointAspect { private final AtomicLong methodCallCounter = new AtomicLong(0); private final ScheduledExecutorService executor; // 改为手动创建的线程池 public TrackingPointAspect() { // 手动创建线程池 executor = new ScheduledThreadPoolExecutor(1, new CustomThreadFactory()); // 配置拒绝策略(由于是单线程定时任务,通常不会触发) ((ScheduledThreadPoolExecutor) executor).setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 配置关闭策略 ((ScheduledThreadPoolExecutor) executor).setContinueExistingPeriodicTasksAfterShutdownPolicy(false); executor.scheduleAtFixedRate(() -> { try { long count = methodCallCounter.getAndSet(0); log.info("===== 方法调用统计重置 ====="); log.info("上一分钟总调用次数: {}", count); } catch (Exception e) { log.error("重置计数器异常", e); } }, 0, 60, TimeUnit.SECONDS); } @PreDestroy public void destroy() { executor.shutdownNow(); } // 自定义线程工厂 static class CustomThreadFactory implements ThreadFactory { private final AtomicInteger counter = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("tracking-stat-thread-" + counter.getAndIncrement()); thread.setDaemon(true); return thread; } } // 原有切点和方法保持不变... } ``` §§相关问题§§ 1. 在Spring应用中,如何确保手动创建的线程池能被正确关闭? 2. 除了守护线程,还有哪些方法可以避免线程池阻止JVM退出? 3. 当定时任务执行时间超过周期间隔时,线程池会如何处理? 4. 如何通过Spring的Bean生命周期管理替代构造方法来初始化线程池? 5. 对于高并发场景,使用单线程调度器重置计数器可能存在什么瓶颈? </think> ### 手动创建线程池的优化方案 在AOP切面中手动创建线程池是更优的选择,以下是重构后的实现方案: ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import javax.annotation.PreDestroy; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicInteger; @Slf4j @Aspect @Component public class TrackingPointAspect { // 方法调用计数器(线程安全) private final AtomicLong methodCallCounter = new AtomicLong(0); // 手动创建线程池 private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor( 1, // 核心线程数 new CustomThreadFactory(), // 自定义线程工厂 new ThreadPoolExecutor.DiscardPolicy() // 拒绝策略 ); // 自定义线程工厂 static class CustomThreadFactory implements ThreadFactory { private final AtomicInteger counter = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("tracking-stat-thread-" + counter.getAndIncrement()); thread.setDaemon(true); // 设置为守护线程 return thread; } } public TrackingPointAspect() { // 每分钟重置计数器 scheduler.scheduleAtFixedRate(() -> { long count = methodCallCounter.getAndSet(0); log.info("===== 方法调用统计重置 ====="); log.info("上一分钟总调用次数: {}", count); }, 0, 60, TimeUnit.SECONDS); } // 优雅关闭线程池 @PreDestroy public void destroy() { scheduler.shutdown(); try { if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { scheduler.shutdownNow(); } } catch (InterruptedException e) { scheduler.shutdownNow(); Thread.currentThread().interrupt(); } } @Pointcut("@annotation(com.tplink.nbu.demo.basicspringboot.annotation.TrackingPointEnable)") public void trackingPointPointcut() {} @Around("trackingPointPointcut()") public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { // 增加调用计数 long currentCount = methodCallCounter.incrementAndGet(); // ... [原有日志逻辑保持不变] ... // 打印当前统计 log.info("当前1分钟内执行次数: {}", currentCount); return result; } } ``` ### 手动创建线程池的优势 1. **精确控制线程参数** ```java new ScheduledThreadPoolExecutor( 1, // 核心线程数 new CustomThreadFactory(), // 自定义线程工厂 new ThreadPoolExecutor.DiscardPolicy() // 拒绝策略 ) ``` - 避免`Executors`隐藏的默认配置问题 - 可直接设置核心线程数、存活时间等 2. **自定义线程工厂** ```java thread.setName("tracking-stat-thread-1"); // 明确线程用途 thread.setDaemon(true); // 避免阻止JVM关闭 ``` 3. **安全拒绝策略** - 使用`DiscardPolicy`避免任务堆积导致OOM - 替代`Executors.newSingleThreadScheduledExecutor()`的无界队列风险 4. **生命周期管理** ```java @PreDestroy public void destroy() { scheduler.shutdown(); // 优雅关闭 } ``` - 确保Spring容器关闭时释放资源 - 添加超时强制终止保护 ### 关键配置说明 1. **线程池类型选择** - 监控场景适合`ScheduledThreadPoolExecutor` - IO密集型任务可考虑增加线程数 2. **拒绝策略对比** | 策略 | 适用场景 | 风险 | |------|---------|------| | AbortPolicy | 严格场景 | 抛出异常 | | DiscardPolicy | 监控场景 | 丢弃任务 | | CallerRunsPolicy | 平衡场景 | 可能阻塞调用线程 | 3. **守护线程优势** - 不会阻止JVM正常退出 - 适合后台监控任务 - 需确保任务可中断 ### 生产环境建议 1. **监控线程池状态** ```java // 定期记录线程池指标 log.info("活动线程: {}, 队列大小: {}", ((ThreadPoolExecutor)scheduler).getActiveCount(), ((ThreadPoolExecutor)scheduler).getQueue().size()); ``` 2. **动态参数调整** ```java // 运行时动态修改核心线程数 ((ThreadPoolExecutor)scheduler).setCorePoolSize(newSize); ``` 3. **集成Micrometer监控** ```java Metrics.gauge("method.call.count", methodCallCounter); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值