看了上面大佬写的东西,自己也总结一下吧,元对象系统中实现了很多功能,有信号槽机制,将信号,槽,qt 的一些宏转化为 moc_h文件,而且其中的信号和槽连接,是通过字符串连接的,然后通过存储的数据,在函数中判断所类型,和取得的序列号,然后通过switch case到达相应的槽。
值得注意的点:
而对于qobject的构造函数,首相将q指针,指向this,将d指针指向threadData,然后在初始化threadData,设置父节点
Q_D(QObject);
d_ptr->q_ptr = this;
d->threadData = (parent && !parent->thread()) parent->d_func()->threadData : QThreadData::current();
d->threadData->ref();
if (parent) {
QT_TRY {
if (!check_parent_thread(parent, parent parent->d_func()->threadData : 0, d->threadData))
parent = 0;
setParent(parent);
} QT_CATCH() {
d->threadData->deref();
QT_RETHROW;
}
}
#if QT_VERSION < 0x60000
qt_addObject(``this``);
#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast``<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(``this``);
实现方法进程与指定cpu绑定
:SetProcessAffinityMask(GetCurrentProcess(),dwMask);
线程与指定cpu绑定:
SetThreadAffinityMask(GetCurrentThread(),dwMask);dwMask为CPU序号的或运算值:1(0001)
代表只运行在CPU1,2(0010)代表只运行在CPU2,3(0011)代表可以运行在CPU1和CPU2
,以此类推。
设置之前最好判断一下系统有几个CPU:
SYSTEM_INFOSystemInfo;
GetSystemInfo(&SystemInfo);CPU个数:SystemInfodwNumberOfProcessors
当前启用的CPU序号:
SystemInfodwActiveProcessorMask
,Mask representing the set of processors configured into the system Bit 0 is processor 0;
bit 31 is processor 31
CPU亲缘性介绍
按照默认设置,当系统将线程分配给处理器时,Windows使用软亲缘性来进行 *** 作。这意味着如果所有其他因素相同的话,它将设法在它上次运行的那个处理器上运行线程。让线程留在单个处理器上,有助于重复使用仍然在处理器的内存高速缓存中的数据。
有一种新的计算机结构,称为NUMA(非统一内存访问),在该结构中,计算机包含若干块插件板,每个插 件板上有4个CPU和它自己的内存区。
当CPU访问的内存是它自己的插件板上的内存时,NUMA系统运行的性能最好。如果CPU需要访问位于另一个插件板上的内 存时,就会产生巨大的性能降低。在这样的环境中,就需要限制来自一个进程中的线程在共享同一个插件版的CPU上运行。
为了适应这种计算机结构的需要,Windows允许你设置进程和线程的亲缘性。换句话说,你可以控制哪个CPU能够运行某些线程。这称为硬亲缘性。请注意,子进程可以继承进程的亲缘性。
注意:(1)无论计算机中实际拥有多少个CPU,Windows98及以前系统只使用一个CPU,上述API不被支持。
(2)在大多数环境中,改变线程的亲缘性就会影响调度程序有效地在 各个CPU之间移植线程的能力,而这种能力可以最有效地使用CPU时间。
应用场景举例:
将UI线程限制在一个CPU,将其他实时性要求较高的线程限制在另一个CPU。这样,当UI需要占用大量CPU时间时,就不会拖累其他实时性要求较高的线程的执行
。同样可以将UI线程与一些优先级不高但耗时的异步运算线程设置在不同CPU上,避免UI给人卡顿的感觉。
把你的源码上传上来,直接用你的源码修改还说得过去!
你这样谁知道登录哪里,验证码来源哪里,验证码输入哪里!
难道别人还要帮你完整的做个客户端 与 服务器,然后做验证码。多线程。。。
windows里面信号量比较难用,下面是我模仿一本教材写的一个例子,加了一些注释,在net 2008环境下调试通过的。你可以参考下,不过直接复制过去是很难调的过的吧,还有其他一些相关文件。
// ProducerCustomer2cpp : 定义控制台应用程序的入口点。
//
#include "stdafxh"
#include <windowsh>
#include <fstream> //与课本不同
#include <iostream> //与课本不同
#include <string>
#include <conioh>
using namespace std;
//定义一些常量;
//本程序允许的最大临界区数;
#define MAX_BUFFER_NUM 10
//秒到毫秒的乘法因子;
#define INTE_PER_SEC 1000
//本程序允许的生产和消费线程的总数;
#define MAX_THREAD_NUM 64
//定义一个结构,记录在测试文件中指定的每一个线程的参数
struct ThreadInfo
{
int serial; //线程序列号
char entity; //是P还是C
double delay; //线程延迟
int thread_request[MAX_THREAD_NUM]; //线程请求队列
int n_request; //请求个数
};
//全局变量的定义
//临界区对象的声明,用于管理缓冲区的互斥访问;
CRITICAL_SECTION PC_Critical[MAX_BUFFER_NUM];
int Buffer_Critical[MAX_BUFFER_NUM]; //缓冲区声明,用于存放产品;
HANDLE h_Thread[MAX_THREAD_NUM]; //用于存储每个线程句柄的数组;
ThreadInfo Thread_Info[MAX_THREAD_NUM]; //线程信息数组;
HANDLE empty_semaphore; //一个信号量;
HANDLE h_mutex; //一个互斥量;
DWORD n_Thread = 0; //实际的线程的数目;
DWORD n_Buffer_or_Critical; //实际的缓冲区或者临界区的数目;
HANDLE h_Semaphore[MAX_THREAD_NUM]; //生产者允许消费者开始消费的信号量;
//生产消费及辅助函数的声明
void Produce(void p);
void Consume(void p);
bool IfInOtherRequest(int);
int FindProducePositon();
int FindBufferPosition(int);
int main(void)
{
//声明所需变量;
DWORD wait_for_all;
ifstream inFile;
//初始化缓冲区;
for(int i=0;i< MAX_BUFFER_NUM;i++)
Buffer_Critical[i] = -1;
//初始化每个线程的请求队列;
for(int j=0;j<MAX_THREAD_NUM;j++){
for(int k=0;k<MAX_THREAD_NUM;k++)
Thread_Info[j]thread_request[k] = -1;
Thread_Info[j]n_request = 0;
}
//初始化临界区;
for(int i =0;i<MAX_BUFFER_NUM;i++)
InitializeCriticalSection(&PC_Critical[i]);
//打开输入文件,按照规定的格式提取线程等信息;
inFileopen("testtxt");
//从文件中获得实际的缓冲区的数目;
inFile >> n_Buffer_or_Critical;
n_Buffer_or_Critical = inFileget();
printf("输入文件是:\n");
//回显获得的缓冲区的数目信息;
printf("%d \n",(int) n_Buffer_or_Critical);
//提取每个线程的信息到相应数据结构中;
while(inFile){
inFile >> Thread_Info[n_Thread]serial;
inFile >> Thread_Info[n_Thread]entity;
inFile >> Thread_Info[n_Thread]delay;
char c;
inFileget(c);
while(c!='\n'&& !inFileeof()){
inFile>> Thread_Info[n_Thread]thread_request[Thread_Info[n_Thread]n_request++];
inFileget(c);
}
n_Thread++;
}
//回显获得的线程信息,便于确认正确性;
for(int j=0;j<(int) n_Thread;j++){
int Temp_serial = Thread_Info[j]serial;
char Temp_entity = Thread_Info[j]entity;
double Temp_delay = Thread_Info[j]delay;
printf(" \n thread%2d %c %f ",Temp_serial,Temp_entity,Temp_delay);
int Temp_request = Thread_Info[j]n_request;
for(int k=0;k<Temp_request;k++)
printf(" %d ", Thread_Info[j]thread_request[k]);
cout<<endl;
}
printf("\n\n");
//创建在模拟过程中几个必要的信号量
empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,
NULL);
h_mutex =CreateMutex(NULL,FALSE,NULL);
//下面这个循环用线程的ID号来为相应生产线程的产品读写时所
//使用的同步信号量命名;
for(int j=0;j<(int)n_Thread;j++){
std::string lp ="semaphore_for_produce_";
int temp =j;
while(temp){
char c = (char)(temp%10);
lp+=c;
temp/=10;
}
h_Semaphore[j+1]=CreateSemaphore(NULL,0,n_Thread,NULL);
}
//创建生产者和消费者线程;
for(int i =0;i< (int) n_Thread;i++){
if(Thread_Info[i]entity =='P')
h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce),
&(Thread_Info[i]),0,NULL);
else
h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),
&(Thread_Info[i]),0,NULL);
}
//主程序等待各个线程的动作结束;
wait_for_all = WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1);
printf(" \n \n全部生产者和消费者都已完成它们的工作 \n");
printf("按任意键返回!\n");
_getch();
return 0;
}
//确认是否还有对同一产品的消费请求未执行;
bool IfInOtherRequest(int req)
{
for(int i=0;i<n_Thread;i++)
for(int j=0;j<Thread_Info[i]n_request;j++)
if(Thread_Info[i]thread_request[j] == req)
return TRUE;
return FALSE;
}
//找出当前可以进行产品生产的空缓冲区位置;
int FindProducePosition()
{
int EmptyPosition;
for (int i =0;i<n_Buffer_or_Critical;i++)
if(Buffer_Critical[i] == -1){
EmptyPosition = i;
//用下面这个特殊值表示本缓冲区正处于被写状态;
Buffer_Critical[i] = -2;
break;
}
return EmptyPosition;
}
//找出当前所需生产者生产的产品的位置;
int FindBufferPosition(int ProPos)
{
int TempPos;
for (int i =0 ;i<n_Buffer_or_Critical;i++)
if(Buffer_Critical[i]==ProPos){
TempPos = i;
break;
}
return TempPos;
}
//生产者进程
void Produce(void p)
{
//局部变量声明;
DWORD wait_for_semaphore,wait_for_mutex,m_delay;
int m_serial;
//获得本线程的信息;
m_serial = ((ThreadInfo)(p))->serial;
m_delay = (DWORD)(((ThreadInfo)(p))->delay INTE_PER_SEC);
Sleep(m_delay);
//开始请求生产
printf("生产者 %2d 发送生产请求信号\n",m_serial);
//确认有空缓冲区可供生产,同时将空位置数empty减1;用于生产者和消费者的同步;
wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1);
//互斥访问下一个可用于生产的空临界区,实现写写互斥;
wait_for_mutex = WaitForSingleObject(h_mutex,-1);
int ProducePos = FindProducePosition();
ReleaseMutex(h_mutex);
//生产者在获得自己的空位置并做上标记后,以下的写 *** 作在生产者之间可以并发执行;
//核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别;
printf("生产者 %2d 开始在缓冲区 %2d 生产产品\n",m_serial,ProducePos);
Buffer_Critical[ProducePos] = m_serial;
printf("生产者 %2d 完成生产过程 :\n ",m_serial);
printf(" 缓冲区[ %2d ]:%3d \n" ,ProducePos,Buffer_Critical[ProducePos]);
//使生产者写的缓冲区可以被多个消费者使用,实现读写同步;
ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL);
}
//消费者进程
void Consume(void p)
{
//局部变量声明;
DWORD wait_for_semaphore,m_delay;
int m_serial,m_requestNum; //消费者线程的序列号和请求的数目;
int m_thread_request[MAX_THREAD_NUM];//本消费者线程的请求队列;
//提取本线程的信息到本地;
m_serial = ((ThreadInfo)(p))->serial;
m_delay = (DWORD)(((ThreadInfo)(p))->delay INTE_PER_SEC);
m_requestNum = ((ThreadInfo )(p))->n_request;
for (int i = 0;i<m_requestNum;i++)
m_thread_request[i] = ((ThreadInfo)(p))->thread_request[i];
Sleep(m_delay);
//循环进行所需产品的消费
for(int i =0;i<m_requestNum;i++){
//请求消费下一个产品
printf("消费者 %2d 请求消费 %2d 产品\n",m_serial,m_thread_request[i]);
//如果对应生产者没有生产,则等待;如果生产了,允许的消费者数目-1;实现了读写同步;
wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i]],-1);
//查询所需产品放到缓冲区的号
int BufferPos=FindBufferPosition(m_thread_request[i]);
//开始进行具体缓冲区的消费处理,读和读在该缓冲区上仍然是互斥的;
//进入临界区后执行消费动作;并在完成此次请求后,通知另外的消费者本处请求已
//经满足;同时如果对应的产品使用完毕,就做相应处理;并给出相应动作的界面提
//示;该相应处理指将相应缓冲区清空,并增加代表空缓冲区的信号量;
EnterCriticalSection(&PC_Critical[BufferPos]);
printf("消费者 %2d 开始消费 %2d 产品 \n",m_serial,m_thread_request[i]);
((ThreadInfo)(p))->thread_request[i] =-1;
if(!IfInOtherRequest(m_thread_request[i])){
Buffer_Critical[BufferPos] = -1;//标记缓冲区为空;
printf("消费者 %2d 成功消费 %2d:\n ",m_serial,m_thread_request[i]);
printf(" 缓冲区[ %2d ]:%3d \n" ,BufferPos,Buffer_Critical[BufferPos]);
ReleaseSemaphore(empty_semaphore,1,NULL);
}
else{
printf("消费者 %2d 成功消费产品 %2d\n ",m_serial,m_thread_request[i]);
}
//离开临界区
LeaveCriticalSection(&PC_Critical[BufferPos]);
}
}
序号
[xù hào]
order number; sequence number; serial number
例句:
1
向主程序注册序号、中断属性和线程属性。
Register the sequence number, interrupt nature, and thread attributes to the main program
2
指示已复制的上一个日志文件的生成序号。
Indicates the generation sequence number of the last log file that has been copied
3
这是一个仅用于枚举的列表对象,必须按序号编索引。
This is an enumeration-only list object and must be indexed by ordinal
oracle 归档日志
归档日志(Archive Log)是非活动的重做日志备份通过使用归档日志,可以保留所有重做历史记录,当数据库处于ARCHIVELOG模式并进行日志切换式,后台进程ARCH会将重做日志的内容保存到归档日志中当数据库出现介质失败时,使用数据文件备份,归档日志和重做日志可以完全恢复数据库
日志 *** 作模式:ARCHIVELOG NOARCHIVELOG
1,改变日志 *** 作模式:
检查当前日志 *** 作模式
SELECT log_mode from v$database;
关闭数据库,然后装载数据库
SHUTDOWN IMMEDIATE
STARTUP MOUNT
改变日志 *** 作模式,然后打开数据库
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
2,执行手工归档
从oracle database 10g开始,当将日志 *** 作模式转变未ARCHIVELOG模式时,oracle会自动启动ARCH进程如果要使用手工归档那么在改变日志 *** 作模式时必须使用命令ALTER DATABASE ARCHIVELOG MANUAL
需要注意,使用手工归档方式,数据库管理员必须手工执行归档命令如果没有执行手工归档命令,日志组的原有内容将不能被覆盖ALTER DATABASE ARCHIVELOG MANUAL 命令是为了与先前的版本兼容而保留的,将来的oracle版本会淘汰该命令,使用手工归档方式是,数据库管理员可以执行以下命令归档重做日志:
ALTER SYSTEM ARCHIVELOG ALL;
3,配置归档进程
初始化参数LOG_ARCHIVE_MAX_PROCESSES用于指定例程初始启动的最大归档进程个数,当将数据库转变为ARCHIVELOG模式时,默认情况下oracle会自动启动两个归档进程通过改变初始化参数LOG_ARCHIVE_MAX_PROCESS的值,可以动态地增加或降低归档进程的个数:
ALTER SYSTEM SET LOG_ARCHIVE_MAX_PROCESSES=3;配置归档位置和文件格式
当数据库处于ARCHIVELOG模式时,如果进行日志切换,后台进程将自动生成归档日志,归档日志的默认位置为%oracle_home%rdbms,在oracle database 10g中,归档日志的默认文件格式为ARC%S_%R%T为了改变归档日志的位置和名称格式,必须改变相应的初始化参数,1,初始化参数LOG_ARCHIVE_FORMAT用于指定归档日志的文件名格式,设置该初始化参数时,可以指定以下匹配符:
%s: 日志序列号:
%S: 日志序列号(带有前导0)
%t: 重做线程编号
%T: 重做线程编号(带有前导0)
%a: 活动ID号
%d: 数据库ID号
%r RESETLOGS的ID值
从10g开始,配置归档日志文件格式时,必须带有%s,%t和%r匹配符,配置了归档文件格式后,必须重启数据库
2,使用LOG_ARCHIVE_DEST配置归档位置
如果不使用备用数据库,只需要将归档日志存放到本地目录配置本地归档位置可以使用初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST,其中,第一个参数用于设置第一个归档位置,第二个参数用于指定第二个归档位置
ALTER SYSTEM SET log_archive_dest='d:demoarchive1';ALTER SYSTEM SET log_archive_duplex_dest='d:demoarchive2';3,使用LOG_ARCHIVE_DEST_n配置多个归档位置
初始化参数LOG_ARCHIVE_DEST_n用于指定多个归档位置,该参数最多可以指定10个归档位置通过使用初始化参数LOG_ARCHIVE_DEST_n,不仅可以配置本地归档位置,还可以配置远程归档位置
如果既要在主节点上生成归档日志,又要将归档日志传递到备用节点,那么必须使用参数LOG_ARCHIVE_DEST_n该参数与LOG_ARCHIVE_DEST具有如下区别;初始化参数LOG_ARCHIVE_DEST_n可以配置本地归档位置和远程归档位置,而初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST只能配置本地归档位置
初始化参数LOG_ARCHIVE_DEST_n可以配置多达10个归档位置,而初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST最多只能配置两个归档位置
初始化参数LOG_ARCHIVE_DEST_n 不能与初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST同时使用
因为初始化参数LOG_ARCHIVE_DEST_n不能与初始化参数LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST同时使用,所以必须禁用初始化参数LOG_ARCHVE_DEST和LOG_ARCHIVE_DUPLEX_DEST当使用初始化参数LOG_ARCHIVE_DEST_n配置本地归档位置时,需要指定LOCALTION选项当配置远程归档位置时,需要指定SERVICE选项
示例如下:
ALTER SYSTEM SET log_archive_duplex_dest='';ALTER SYSTEM SET log_archive_dest='';
ALTER SYSTEM SET log_archive_dest_1='location=d:demoarchive1';ALTER SYSTEM SET log_archive_dest_2='location=d:demoarchive2';ALTER SYSTEM SET log_archive_dest_3='location=d:demoarchive3';ALTER SYSTEM SET log_archive_dest_4='service=standby';配置远程归档位置时,SERVICE选项需要指定远程数据库的网络服务名(在tnsnamesora文件中配置)4,使用LOG_ARCHIVE_DEST_n选项
使用初始化参数LOG_ARCHIVE_DEST_n配置归档位置时,可以在归档位置上指定OPTIONAL或MANDATORY选项指定MANDATORY选项时,可以设置REOPEN属性
OPTIONAL:该选项是默认选项使用该选项时,无论归档是否成功,都可以覆盖重做日志
MANDATORY:强制归档使用该选项时,只有在归档成功之后,重做日志才能被覆盖
REOPEN:该属性用于指定重新归档的时间间隔,默认值为300秒,必须跟在MANDATORY后
例:
Alter system set log_archive_dest_1=’location=d:demoarchive1 mandatory’;Alter system set log_archive_dest_2=’location=d:demoarchive2 mandatory reopen=500’;Alter system set log_archive_dest_3=’location=d:demoarchive3 optional’;5,控制本地归档成功的最小个数
使用初始化参数LOG_ARCHIVE_MIN_SUCCEED_DEST控制本地归档的最小成功个数Alter system set log_archive_min_succeed_dest=2;6,使用初始化参数LOG_ARCHIVE_DEST_STATE_n控制归档位置的可用性设置该参数为ENABLE(默认值),表示会激活相应的归档位置;设置该参数为DEFER,表示禁用相应归档位置当归档日志所在磁盘损坏或填满时,DBA需要暂时禁用该归档位置
Alter system set log_archive_dest_state_3=defer;(禁用)Alter system set log_archive_dest_state_3=enable;(启用)显示归档日志信息
1,使用ARCHIVE LOG LIST命令可以显示日志 *** 作模式,归档位置,自动归档机器要归档的日志序列号等信息
2显示日志 *** 作模式
SELECT name,log_mode FROM v$database;
3,显示归档日志信息
Col name format a46
Select name, swquence#, first_change# FROM v$archived_log;Name用于表示归档日志文件名,sequence#用于表示归档日志对应的日志序列号,firs_change#用于标识归档日志的起始SCN值
4、执行介质恢复时,需要使用归档日志文件,此四必须准确定位归档日志的存放位置通过查询动态性能视图v$archive_dest可以取得归档日志所在目录
SELECT destination FROM v$archive dest;
5,显示日志历史信息
SELECT FROM v$loghist;
THREAD#用于标识重做线程号,SEQUNCE#用于标识日志序列号,FIRST_CHANGE#用于标识日志序列号对应的起始SCN值,FIRST_TIME用于标识起始SCN的发生时间SWICTH_CHANGE#用于标识日志切换的SCN值
6显示归档进程信息
进行日志切换时,ARCH进程会自动将重做日志内容复制到归档日志中,为了加快归档速度,应该启用多个ARCH进程通过查询动态性能视图V$ARCHIVE_PROCESSES可以显示所有归档进程的信息!
SELECT FROM v$archive_processes;
Porcess用于标识ARCH进程的编号,status用于标识ARCH进程的状态(ACTIVE:活动,STOPPED:未启动),log_sequence用于标识正在进行归档的日志序列号,state用于标识ARCH进程的工作状态==========================================用Oracle归档日志进行恢复的方法
用Oracle归档日志进行恢复的方法
联机重演日志没有丢失应使用完成恢复,如联机重演日志损坏,而又没有备份,就只能进行不完全恢复。
一、完全恢复:
1.使用命令“svrmgrl”调用行方式服务器管理;2.输入命令“connect internal”,然后输入命令“startup mount’;3.输入命令“recover database;”
4.按下ENTER,接受默认值。
5.然后输入命令“alter database open;”完成数据库恢复。
二、不完全恢复
警告:
应用不完成恢复前,必须将数据库做一次完全冷备份,因为应用不完全恢复后,联机重演日志将重置,以前的所有日志不可用。
如果恢复不成功,数据库就不能使用了。再次强调,做完全冷备份后再应用不完全恢复。
1)基于变化的恢复(change-based recovery)要执行基于变化的恢复,需要知道丢失日志之前的系统写入归档重演日志的最大的变化号(SCN),然后可以启动恢复语句恢复数据库直到改变scn_number,其中比scn_number是写到已归档重演日志文件顺序号386的SCN(即,小于丢失日志顺序号387的SCN)。可以从V$log_history视图中得到SCN信息。
select first_change# from v$log_history where sequence#=387;其中387为最后一个有效的日志文件号加1,该例是查找386
知道了SCN后,使用下述步骤完成恢复
1.使用命令“svrmgrl”调用行方式服务器管理;2.输入命令“connect internal”,然后输入命令“startup mount’;3.输入命令“recover database until change 9999;”
4.在回答Oracle第一个归档重演日志建议信息时,输入“auto”,Oracle在找到第387号重演日志之前停止恢复。
5.用命令“alter database open resetlogs;”打开数据库。(应用该命令前请确认数据库已备份,如打开失败,日志将不可用)2)基于停止的恢复(cancel-based recovery)
1.使用命令“svrmgrl”调用行方式服务器管理;2.输入命令“connect internal”,然后输入命令“startup mount’;3.输入命令“recover database until cancel;”,Oracle提示需要的第一个归档重演日志文件名.按下ENTER键接受缺省文件名,并且—路ENTER直到询问顺序号387的日志。输入“cancel”,停止恢复 *** 作。
4.用命令“alter database open resetlogs;”打开数据库。(应用该命令前请确认数据库已备份,如打开失败,日志将不可用)3)基于时间的恢复(time-based recovery)
为使用基于时间的恢复,必须知道记录在V$log_history归档重演日志序号387(丢失重演日志)的时间,通过执行查询语句“select time from v$log_history where sequence#=387;”得到。本例得到的时间是:2002-06-23 14:42:04现在开始实施恢复。
1.使用命令“svrmgrl”调用行方式服务器管理;2.输入命令“connect internal”,然后输入命令“startup mount’;3.输入命令“recover database until time '2002/06/23 14:42:04';”,Oracle提示需要的第一个归档重演日志文件名,输入“auto”,Oracle恢复归档重演日志直到序号为387的日志,停止恢复 *** 作。
4.用命令“alter database open resetlogs;”打开数据库。(应用该命令前请确认已数据库已备份,如打开失败,日志将不可用)提示: 使用基于时间的恢复,时间的格式是YYYY/MM/DD HH24:MI:SS,并且用单引号括起。
附:如何启用Oracle的归档方式
1参照以下内容编辑initora文件:
log_archive_start = true
log_archive_dest_1 = " LOCATION=D:\Oracle\oradata\ORCL\archive "og_archive_format = %%ORACLE_SID%%T%TS%SARC2关闭数据库
svrmgrl> connect internal
svrmgrl> shutdown normal
3然后启动实例并安装该数据库,但不打开数据库。
svrmgrl> startup mount
4接着,发布下列更改数据库的命令。
Svrmgrl> alter database archivelog;
5现在,数据库已经更改为归档方式,您可以打开数据库。
svrmgrl> alter database open;
提示:也可以使用DBA studio工具启用数据库的归档方式, *** 作很简单=============================================================ORACLE归档模式的设置
在ORACLE 数据库的开发环境和测试环境中,数据库的日志模式和自动归档模式一般都是不设置的,这样有利于系统应用的调整,也免的生成大量的归档日志文件将磁盘空间大量的消耗。但在系统上线,成为生产环境时,将其设置为日志模式并自动归档就相当重要了,因为,这是保证系统的安全性,有效预防灾难的重要措施。这样,通过定时备份数据库和在两次备份间隔之间的日志文件,可以有效的恢复这段时间的任何时间点的数据,可以在很多时候挽回或最大可能的减少数据丢失。
一、 要使OARCLE 数据库进行日志的自动归档,需要做两方面的事情;1.是数据库日志模式的设置(可为Archive Mode 和No Archive Mode);2.就是自动归档模式设置(Automatic archival,可为Enabled 和Disabled)。
二、 如何查看数据库的现行日志和自动归档模式的设置可用archive log list 命令来查看。
运行在日志自动归档模式下的数据库系统查看结果如下(一般是生产环境):
SQL> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination /backup/archivelog
Oldest online log sequence 2131
Next log sequence to archive 2133
Current log sequence 2133
没有启动数据库日志模式和自动归档的数据库系统查看结果如下(一般是测试环境):
SQL> archive log list
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination /u01/app/oracle/product/817/dbs/archOldest online log sequence 194
Current log sequence 196
三 数据库日志模式的设置
在创建数据库时,可以在CREATE DATABASE 语句中指定数据库的日志模式。假如没有指明,则缺省为NOARCHIVELOG 模式。由于如果在创建数据库时指明是Archive Mode的话,会增加约20%的创建时间,而在以后启动INSTANCE 时再设置的话,一般只用去几秒的时间,所以一般在创建数据库时是不设置为ARCHIVE MODE 的。
将数据库的日志模式设置切换(Archive Mode 和No Archive Mode 之间的切换)的步骤和 *** 作如下:
1 关闭运行的数据库实例
SQL> shutdown
在进行日志模式切换之前,必须将运行的数据库正常关闭。
2 备份数据库
该备份跟以后产生的日志一起用于将来的灾难恢复(很重要,如要改为归档日志模式,没有这个数据库备份,仅有日志文件是无法从该时间点恢复的)。
3 启动数据库实例到mount 状态,但不要打开。
SQL> startup mount
4 切换数据库日志模式。
SQL> alter database archivelog;(设置数据库为归档日志模式)或SQL> alter database noarchivelog;(设置数据库为非归档日志模式)5 打开数据库
SQL> alter database open;
6 确认数据库现在处于归档日志模式。
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination for example: $ORACLE_HOME/dbs/archOldest on-line log sequence 275
Next log sequence 277
Current log sequence 278
7 将这个时间点的redo logs 归档
SQL> archive log all;
8 确认新产生的日志文件已在相应的归档目录下面。
四 自动归档模式设置(Automatic archival,可为Enabled 和Disabled)。
在该模式下,数据库启动一个arch 进程,专门负责将redo logs 写到系统归档设备的相应目录下。在数据库的参数文件中设置参数(一般是在$ORACLE_HOME/dbs/initora 文件中):
LOG_ARCHIVE_START=
LOG_ARCHIVE_DEST=
LOG_ARCHIVE_FORMAT=
LOG_ARCHIVE_START:
cuda进行计算时需要同时指定线程块序号和网格序号才行,而一个网格中包含多个线程块,所以线程增量为二者积。下面几个链接解释的很清楚了:
网页链接
网页链接
一:使用synchronized关键字
二:使用CollectionssynchronizedList()
一、 ArrayList概述:
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用CollectionssynchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。
每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。
在添加大量元素前,应用程序也可以使用ensureCapacity *** 作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。
注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。
以上就是关于QT QObject分析全部的内容,包括:QT QObject分析、如何设置进程(线程)在指定的CPU上运行、易语言 多线程 判定条件等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)