2015年12月17日星期四

windows7的keyboard layout

win7安装在esx上,通过vsphere去连接,结果怎么修改都是英文键盘。通过remote desktop连接也是英文键盘。

修改了驱动为日文键盘也没用。
增加"IgnoreRemoteKeyboardLayout"=dword:00000001也没用

 
后来发现,必须先在vsphere里面login,然后里面是session的keybard是日文后,再remote desktiop进同样的session去就是日文的。
如果用remote desktop直接login,就是英文了。

记下来,免得下次折腾。

2015年12月14日星期一

url-pattern

虽然一直用,因为基本不会遇到问题。
这里弄清楚一下

对tomcat,有4种
/*  wildcardWrappers

*. extensionWrappers

/ defaultWrapper

其他 exactWrappers

优先级是
1.精确匹配最优先,exactWrappers
2.前缀匹配,wildcardWrappers /*
3.扩展名匹配,extensionWrappers *.
4.显示welcome
5.使用默认的servlet来处理,defaultWrapper  /

到这里,就能区分开/*和/的区别了

例子,springmvc里,定义了/*来处理所有的请求给springmvc的DispatcherServlet,也定义了一个@RequestMapping为index.jsp,web目录里面也放一个index.jsp
如果输入http://xxxx/index.jsp,那么请求会被/*给拦截给springmvc,因为rule2比rule3优先。

如果springmvc的servlet里定义的是/, index.jsp就不会被拦截给springmvc,因为rule3比rule5高。

同时,我们还可能会碰到这样的问题
springmvc里面定义/*拦截,然后@RequestMapping定义为index,做一个viewResolver,指向WEB-INF/views/login.jsp。这个时候,如果访问index,会出现什么结果?
a。index会被springmvc拦截,然后去访问 WEB-INF/views/login.jsp
b。 结果WEB-INF/views/login.jsp又被springmvc再次拦截了(rule2比rule3优先级高)
结果导致出现
No mapping found for HTTP request with URI [/xiu_template/WEB-INF/views/login.jsp] in DispatcherServlet with name 'spring.mvc'
出来不了我们想要的东西。

解决法子,最简单的自然是定义springmvc为比如url-pattern *.html,然后访问index.html,然后去WEB-INF/views/login.jsp,然后去的*.jsp的servlet。是没有问题的。

如果就是不想用扩展名的的方法咋办?? url-pattern是没有exclude的。
其实,只要在web.xml里面多顶一个前缀匹配就ok了。default的名字,是固定的。tomcat还可以写为jsp,因为真正的名字是jsp(可以通过serveletcontext找到getServletRegistrations后知道里面注册的servelet是org.apache.jasper.servlet.JspServlet,名字是jsp)。

    <servlet-mapping>
     <servlet-name>default</servlet-name>
     <url-pattern>/WEB-INF/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
     <servlet-name>default</servlet-name>
     <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>

追到这里,就不由想到难道springmvc就不能处理jsp或者static的东西了?查了一下,发现早就有一个
<mvc:default-servlet-handler/>来对应这个事情,定义了这个,拦截了后不能mapping的就给这个default了。
这下才算是完满了。 web.xml里面清爽了。
 default-servlet-handler自动发现server(tomcat)的默认serlet,交个它来出来自己搞不定的事情。

那是不是说定义了这个东西,事情就算完了?我发现如果网站在default-servlet-handler和spring-security搭配起容易出问题。



2015年11月27日星期五

context:property-placeholder vs PropertySourcesPlaceholderConfigurer

spring各个版本还不一样,目前最新的是

3.1前,property-placeholder 解析为 PlaceholderConfigurerSupport
3.1后,property-placeholder 解析为PropertySourcesPlaceholderConfigurer

关于父子容器
父亲里面定义的property-placeholder,儿子里面@Value读不到。

要想多个 property-placeholder,需要设置ignore-unresolvable="true" ,顺序靠order,但是是以order小的优先。比如order1先加载了keyA=valueA,order2里面如果有keyA=valueAA,order2里面的keyA=valueAA不会加载,所以内容仍然是order1里的valueA。

property-placeholder定义的内容进不了Environment,所以env.getProperty是拿不着东西,就算@Value拿到了也不行。

挺乱。


结论就是,不要再使用 property-placeholder了,以后要用 @PropertySource
 @PropertySource自己并不会注册PropertySourcesPlaceholderConfigurer ,所以需要自己定义一个PropertySourcesPlaceholderConfigurer bean
 @PropertySource的父子容器是
父亲定义的,儿子可以读取,@Value可以读,env可以读。
同一个容器里的多个 @PropertySource,就拼先后顺序了。

2015年11月13日星期五

spring的豆知识

http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html 

<context:annotation-config/>,@AnnotationDrivenConfig
AnnotationConfigApplicationContext来实现的。有了它可以使用
@Configuration,@Bean然后

@Resource 、@PostConstruct、@PreDestroy
@PersistenceContext
@Autowired
@Required
@Autowired就有了注入功能。不用再写ref=xxx了。自身并不创建bean。
<context:component-scan>@ComponentScan,包含了component-scan所有的功能,另外加上了扫描到的Component的自动创建注册功能。@Component(以及后代@Repository,@Service,@Controller,@RestController)都创建起来了。

这里@Configuration其实已经注解了@Component了,它其实也是@Component的后代。


<mvc:annotation-driven />@EnableWebMvc,@RequestMapping起作用了。提供了mvc里面的req到controller的mapping功能,没有它reqdispatch不到controller,也就是找不着dispatch的对象。它对应JavaConfig里的@EnableWebMvc。当然相关的Mvc的配置也跟着就被调用了,如WebMvcConfigurerAdapter.configureContentNegotiation。


WebApplicationInitializer(AbstractAnnotationConfigDispatcherServletInitializer)相关的是启动时会被扫描,然后加载配置类,是完全拥有自己的Container(ServletContext)的。

配置类,
如果Initialize加载,就去配置Initializer里面创建的上下文ConfigWebApplicationContext属性,然后上下文属性在作用到里面创建的servlet(DispatcherServlet),当然一个ConfigWebApplicationContext可以创建多个servlet,也就是同一份配置,应用到了多个servlet,这些servlet共享一个上下文,也就是同一个Container里面的不同servlet共享bean了。

如果是被web.xml里面指定的servlet的ComponeScan扫描到,就去配置当前servlet的上下文,这里不会再次创建上下文,所以@Configure的类只是对已有的配置进行再配置。如果同一个servlet扫描到多个@Configure怎么办?我认为是后面的进一步补充前面的。

配置类里想要知道 自己被应用到哪些SerletContext了?我没找到方法。

另外,这些配置是不会被子container给继承的,比如root containter定义了<mvc:annotation-driven />,它的child仍然需要定义。

http://techidiocy.com/annotation-config-vs-component-scan-spring-core/
http://www.cnblogs.com/fangqi/archive/2012/11/04/2748579.html 
http://stackoverflow.com/questions/7414794/difference-between-contextannotation-config-vs-contextcomponent-scan

2015年9月29日星期二

http://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes

http://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes

2015年9月22日星期二

angular的动画,nganimate

https://docs.angularjs.org/api/ngAnimate,白话顺一遍 。
有几个方式来实现
1. css动画,CSS-based Animations
A。用css 的transition
例子
/* The starting CSS styles for the enter animation */
.fade.ng-enter {
  transition: opacity 0.5s linear 0s;
  opacity:0;这是动画开始属性
}

/* The finishing CSS styles for the enter animation */
.fade.ng-enter.ng-enter-active {
  opacity:1;这是动画结束属性
}
transition的设置是:http://www.htmq.com/css3/transition.shtml
第一个是要trans的属性名(opacity),
第二个是要持续多长时间(0.5s),
第三个是用的算法(linear),
第四个是delay多久才执行(0s)。
B.用keyframe来实现
例子
.fade.ng-enter {
  animation: fadeIn 1s; 
},这里的fadeIn一般用别人的,animation.css里面定义了不少keyframe。
用keyframe方法不需要实现-active来表示结束。
 
 CSS Staggering Animations这个好像没啥用,因为staggering指定的值,
可以用transtion的第四个值指定啊 
 
JavaScript-based Animations类型的,没jquery的话,自己好像比较难搞。
 
 
 



2015年9月20日星期日

去掉debug log信息

search了一下,知道目前有一个gulp-strip-debug可以用来去掉 console, alert, and debugger,但是这个不是我想要的,因为我自己封装了一个logger。
再找,说gulp-uglify自己就带的有参数,drop_console可以去掉debugger,也并不是我想要的。另外http://lisperator.net/uglifyjs/compress里面可以定义变量,然后压缩的时候就会去掉里面的代码,这个的确是不错,我用的是gulp-uglify,它后面是call的uglifyjs,看https://www.npmjs.com/package/gulp-uglify
所以可以
  .pipe($.uglify({ compress: {global_defs: {DEBUG: false}}})).on('error', conf.errorHandler('Uglify'))
来传递进去。这样在做production的时候,就会去删掉debug的代码。挺好。但是问题是,岂不是代码里到处都是if (DEBUG)。继续找

最后看到了gulp-defeatureify,直接设置去掉哪些功能,雖然它主要是給ember用的,但是仍然可以給angular用。
    .pipe($.defeatureify({enableStripDebug: true, debugStatements: ['log.debug', 'log.debug.apply']}))
這樣,所有的log.debug代碼就都給去掉了。
 
要留意的是,它删不掉这样的
self(this).log.debug('xxxx')
也就是, debugStatements里面设置的,必须是点[.]下去的的。
 
 

2015年9月11日星期五

调试gulp

1。要安装gulp-intercept
npm install gulp-intercept --save-dev

2。执行node-inspector
C:\Users\Jacky>node-inspector
Node Inspector v0.12.3
Visit http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858 to start debugging.

3。windows上调试gulp,需要到应用的目录下
node-debug "C:\Users\Jacky\AppData\Roaming\npm\node_modules\gulp\bin\gulp.js" styles,这个会发现node-inspector,然后连接上node-inspector后启动chrome
 unix上面 执行node-debug $(which gulp) styles

4。在chrome里面单步就可以了。

虽然这样可以调试gulp了,但是gulp的那一堆的pipe却是不行的,要想查看pipe里面的内容,需要用到gulp-print,gulp-debug,或者gulp-intercept,
gulp-print只能打印出filename
gulp-debug可以打印出filename以外的内容,但是仍然打印不出文件的内容自身
gulp-intercept才是最强,可以打印出所有的内容。

测试代码如下


    .pipe(wiredep(_.extend({}, conf.wiredep)))
    //.pipe($.print())      //only can print filename
    /*.pipe($.print(function(filepath) { //custom print filename
      return "built: " + filepath;
      })
    )
    .pipe($.intercept(function(file){
      //https://www.npmjs.com/package/vinyl
      //console.log('file: ' + JSON.stringify(file));
      console.log('file.cwd: ' + file.cwd );
      console.log('file.base ' + file.base );
      console.log('file.path: ' + file.path );
      console.log('file.history: ' + file.history );
      console.log('file.relative : ' + file.relative);
      console.log('file.dirname : ' + file.dirname);
      console.log('file.basename : ' + file.basename);
      console.log('file.extname : ' + file.extname);
      //https://nodejs.org/api/fs.html#fs_class_fs_stats
      console.log('file.stat: ' + JSON.stringify(file.stat));
      //console.log('file.contents.type: ' + file._contents.type);
      //console.log('file.contents: ' + file.contents.toString() );
      return file;})
    )*/
    //.pipe($.debug({title: 'zyz debug:', minimal: false}))

2015年8月21日星期五

2015年8月13日星期四

webpack的babel-loader支持Object.assign

需要
npm install babel-runtime --save
然后
        loaders: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?optional[]=runtime'}]

这里得追加上
optional[]=runtime'

https://github.com/babel/babel-loader
http://babeljs.io/docs/usage/options/
http://babeljs.io/docs/usage/runtime/

less的@import

不像c语言的include,没找到官方文档,明确如何找文件的,感觉上是

相对路径,关键得弄清楚相对谁,谁为base
1。以使用@import的文件所在base,开始找。找不到的情况下,进入下一条
2。如果lessc命令指定了
lessc --include-path=PATH1;PATH2
或者http://lesscss.org/features/
{ paths: ['PATH1', 'PATH2']  }
就以这些目录为base进行查找,找不到进入下一条  

3。以执行node命令时当前目录为base开始找,找不到也就报错咯。



2015年8月11日星期二

ionic

1。安装好jdk,android sdk,xcode。
下载http://dl.google.com/android/android-sdk_r24.3.3-macosx.zip,解压后,里面有一个SDK Readme.txt,里面写着执行tools/android upate sdk --no-ui,就会自动安装一堆,包括很老版本的sdk。如果要选择性按照,就去掉--no-ui。安装后,设置.bash_profile
export LANG=ja_JP.UTF-8
export ANDROID_HOME=/Users/jacky/Downloads/android-sdk-macosx
export PATH=$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH
安装xcode就没啥好写的了。

2。按照nodejs相关的东西,我是用nodebrew,的确好用。

3。安装ionic和相关
npm install -g cordova ionic ios-sim
 
4。建立程序,并跑一下
ionic start myApp tabs
cd myApp
ionic platform add ios(android)
ionic build ios(android)
ionic emulate ios(android)
直接编译并运行 ionic run ios(android)
 
ionic的一些命令行
ionic lib update 更新ionic js的库
ionic serve --lab 在网页查看
https://github.com/driftyco/ionic-cli
http://ionicframework.com/docs/cli/
 
ionic下的各个文件和目录的作用,熟悉angular开发的话,应该就不是问题了。  目前还是用WebStorm来做的编辑。

ionic官方用来建立程序的项目太过简单,了sccs以为其他都要自己安装,太繁琐,我找了一下generator,发现有两个用的比较多,一个generator-ionic,内容充实但是用的是grunt,我一直用 gulp,一个generator-ionic-gulp看起来和目前写angular web非常一样,编译后的东西再写往ionic的www目录,所以我决定用
generator-ionic-gulp来生成项目。步骤很简单,照着git做就可以了,但最后却跑不到模拟器上(报出错8100端口网络错误),只得放弃,回退到generator-ionic。

debug
http://www.smashingmagazine.com/2014/09/testing-mobile-emulators-simulators-remote-debugging/2/

2015年5月30日星期六

日子过得很漫长

要在windows上搞node,各种坑。好不容易搞成了,记录下来。

1.node要安装 v0.10.36,11后的版本去掉了v8,各种node-gyp编译不过,比如ws,socket.io。
2.-g 安装gulp后,在项目目录下再次执行npm install --save-dev gulp还是没有用,得自己手动安装一堆
npm install gulp-angular-templatecache gulp-filter gulp-jshint gulp-load-plugins gulp-ng-annotate gulp-replace gulp-rev gulp-rev-replace gulp-useref gulp-minify-html gulp-flatten
这个命令会检查依赖,然后安装
3.安装vs2005没过去,还是vs2013才过去,就为了一个msbuild。

2015年5月27日星期三

yeoman的默认generator产生的目录结构

yo默认的generator是generator-angular,它产生的目录结构我的确是不喜欢,所谓的view都在一个目录下,然后所有的js在一个目录script下,scripts目录下分controllers,directives,services这样子,估计和ruby一样走的模式。但是这导致了一个问题,内容多了后,根据一个view要去找到自己的controller真的麻烦,还是喜欢mvc自己在自己的目录里。
拜google,找到了这个文章 ,看来大家都有这个想法。
目前找到两个指导风格
https://github.com/johnpapa/angularjs-styleguide :
└── app
    ├── app.module.js
    ├── app.config.js
    ├── app.routes.js
    ├── components       
    │   ├── calendar.directive.js  
    │   ├── calendar.directive.html  
    │   ├── user-profile.directive.js  
    │   └── user-profile.directive.html  
    ├── layout
    │   ├── shell.html      
    │   ├── shell.controller.js
    │   ├── topnav.html      
    │   └── topnav.controller.js
    ├── people
    │   ├── attendees.html
    │   ├── attendees.controller.js  
    │   ├── speakers.html
    │   ├── speakers.controller.js
    │   ├── speaker-detail.html
    │   └── speaker-detail.controller.js
    ├── services       
    │   ├── data.service.js  
    │   ├── localstorage.service.js
    │   ├── logger.service.js   
    │   └── spinner.service.js
    └── sessions
        ├── sessions.html      
        ├── sessions.controller.js
        ├── session-detail.html
        └── session-detail.controller.js  

https://github.com/mgechev/angularjs-style-guide :
├── app
│   ├── app.js
│   ├── common
│   │   ├── controllers
│   │   ├── directives
│   │   ├── filters
│   │   └── services
│   ├── home
│   │   ├── controllers
│   │   │   ├── FirstCtrl.js
│   │   │   └── SecondCtrl.js
│   │   ├── directives
│   │   │   └── directive1.js
│   │   ├── filters
│   │   │   ├── filter1.js
│   │   │   └── filter2.js
│   │   └── services
│   │       ├── service1.js
│   │       └── service2.js
│   └── about
│       ├── controllers
│       │   └── ThirdCtrl.js
│       ├── directives
│       │   ├── directive2.js
│       │   └── directive3.js
│       ├── filters
│       │   └── filter3.js
│       └── services
│           └── service3.js
├── partials
├── lib
└── test


后来我打算安装文章最后提到的generator-ng-poly
根据介绍,Inspired by John Papa's Angular Style Guide and Todd Motto's AngularJS styleguide

安装
npm install -g ng-poly gulp
ng-poly用的gulp来打包,不是用grunt了,少了io速度上前进了一步。
然后去
cd D:\WebProjects,不用先建项目的目录了。
yo ng-poly,这里会问你要建立的项目的名字,然后会根据你的名字建立目录。这里我回退了node的版本为0.11.16,因为的确0.12时会hang在home.css上,但是回退了还是没用,结果一样挂了。直接ctrl+c算了。


http://blog.jobbole.com/78946/

2015年5月10日星期日

Yeoman的generate-angular产生的目录的删除

在mac上自然直接rm,windows上却远远超过了最长path的限制,怎么都删不掉。后来google,发现可以这样删
比如要删除
D:\WebProjects\YeomanTest
用下面的手法删
cd D:\WebProjects
md a
robocopy  a YeomanTest /mir,这里会执行比较长时间,mir会将源a镜像到目的YeomanTest,所以会清除YeomanTest目录下的东西,从而达到删除的目的。
rd a
rd /s  YeomanTest

今天找到一个新的法子,远比robocopy来的快。
既然node_modules是在node里面创建出来,就在node里面删,方法如下:
先安装rimraf
npm install rimraf -g
然后执行
rimraf D:\WebProjects\YeomanTest就可以了,瞬间删除。 

yo angular要跑好大半天,难道每次都去执行一下?太慢了。想在本地copy目录,robocopy(robocopy YeomanTest YemanTest2 /mir) 也跑了好大半天,所以还是在node里面执行来的快。
npm install ncp -g
ncp YeomanTest YeomanTest2,这里虽然也会跑很久,但是比起从网上下载再untar要快不少了。

 

2015年5月8日星期五

angular的mac

1。安装nodejs,没有直接去nodejs.org下载再安装,版本变化频繁,还有就是下载二进制安装是root。用了nodebrew,比起homebrew,感觉这个用来管理nodejs的版本以及切换版本都很方便。 并且也都在非root下操作。
安装nodebrew
curl -L git.io/nodebrew | perl - setup,安装nodebrew后需要修改环境变量export PATH=$HOME/.nodebrew/current/bin:$PATH
安装 node
nodebrew install-binary latest
然后看一下安装了啥
nodebrew ls
然后使用安装的版本
nodebrew use v0.12.2
可以使用了
Jacky-Air:~ jacky$ node -v
v0.12.2
Jacky-Air:~ jacky$ npm -v
2.7.4

2。安装ruby的bundler和compass
要用 css的Scss,先更新一下ruby的gem。
Jacky-Air:~ jacky$ ruby -v
ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin13]
Jacky-Air:~ jacky$ gem -v
2.4.1
Jacky-Air:~ jacky$ sudo gem update --system
Jacky-Air:~ jacky$ gem -v
2.4.6
Jacky-Air:~ jacky$ sudo gem install bundler
Jacky-Air:~ jacky$ bundler -v
Bundler version 1.9.6
Jacky-Air:~ jacky$ sudo gem install compass
Jacky-Air:~ jacky$  compass -v
Compass 1.0.3 (Polaris)


3。bower用了git,git默认有了
Jacky-Air:~ jacky$ git --version
git version 1.9.3 (Apple Git-50)
安装Yeoman
Jacky-Air:~ jacky$ npm install -g  bower grunt-cli yo
Jacky-Air:~ jacky$ yo --version
1.4.6
Jacky-Air:~ jacky$ grunt  --version
grunt-cli v0.1.13
这里目前还看不见grunt的版本,要看grunt的版本,得到项目的目录下执行。
Jacky-Air:~ jacky$ bower --version
1.4.1

4。安装npm install -g generator-angular
然后去自己的目录下,建项目
Jacky-Air:YeomanTest jacky$ pwd
/Users/jacky/Projects/YeomanTest
Jacky-Air:YeomanTest jacky$ yo angular
这里下载东西多,会搞很久

5。到这里一个项目的样子就出来了,剩下的是自己开发了。
运行一下grunt serve,访问localhost:9000可以看到内容了

用grunt来打包前端项目很是方便,配置文件为Gruntfile.js,但是和普通的grunt相比,yeoman将grunt的依赖也交给了bower管理,所以目录下会有bower.json文件,当然nodejs的package.json也是必须的。 使用了yeoman,将grunt的门槛降低了不少,不用自己配置Gruntfile.js也不必自己去下载一堆grunt-contrib插件了。



2015年4月21日星期二

flashback2

1。flashback database。
可以将数据库整个回到指定的时间或者scn。
flashback database不依赖undo log,而是flash log来实现的,flashback log是相对于redo log,redo log往前滚,flashback log则是往后滚。要想使用flashback database功能,首先得打开这个功能,这个功能默认是关闭的。
select flashback_on from v$database;看是否开区
alter database flashback on;开区flashback database功能。
另外,flashback log放在回闪区
db_recovery_file_dest位置
db_recovery_file_dest_size大小
db_flashback_retention_target可以回退的时间,单位分钟,默认1440,1天。
由于其他很多东西也在这个回闪区,所以要留意空间的大小。
select * from v$recovery_file_dest;看用量
select * from v$flash_recovery_area_usage;看各类用量
启动了flashback database功能后,会多一个进程Recover Writer(RVWR),它负责写flashback log。

flashback database时的步骤
1。进mount
2。flashback database to timestamp to_timestamp('2015-04-21 18:12:05','yyyy-mm-dd hh24:mi:ss');
flashback database to scn xxx;
3。alter database open resetlogs;
要想知道可以flashback log可以回到何时
select * from v$flashback_database_log;
这个view里有可以回到的最早时间和最早scn。
select * from v$flashback_database_stat这个view里有以小时为单位的统计,统计数据库的数据的变量量。可以用来估算回闪区容量。flashback_data 代表flashback log产生数量,db_date 代表数据改变数量,redo_date代表日志数量。


2。flashback table
将某个表回到指定的时间或者scn。
flashback table依赖undo,要回,首先的让表是行移动模式。
alter table zyz.tbl_test1 enable row movement;
--alter table zyz.tbl_test1 disable row movement;
--select current_scn from v$database; 要权限
select timestamp_to_scn(systimestamp) from dual;
flashback table tbl_test1 to scn 8994000;
flashback table tbl_test1 to timestamp to_timestamp('2015-04-21 18:43:47','yyyy-mm-dd hh24:mi:ss');
flashback table直接运行,也不用进mount,误操作时挺方便。

flashback table的限制是表的结构不能变,也不能是被truncate后的表,另外flashback table也会触发trigger,但是执行时会自动disable trigger,要想trigger有效,需要在语句后面增加enable triggers。

3。flashback data archive
有时,对于某个表,比起undo的flash query version,希望更长期的保留它的变更情况;比起普通的archive,又不希望是database级别的修改备份策略。flashback data archive就是不依赖undo,并且可以以[表]为单位来设置的。后台对应的进程是Flashback Data Archiver Process (FDBA)
 select name,description from v$bgprocess where name='FBDA';它负责将表的数据变化写入data archive区。
步骤如下。
第一步:创建fda的表空间,和普通一样。当然,也可以直接在已经存在的表空间创建fda区。
create tablespace fda1 datafile '/ORADATA/app/oradata/orcl11g/fda01_01.dbf' size 100m;
create tablespace fda2 datafile '/ORADATA/app/oradata/orcl11g/fda02_01.dbf' size 100m;
第二步:在表空间上创建 flashback data archive区。这里需要记得,其实fda区是一个逻辑概念,也即是一个fda区,是可以跨多个表空间的。对于每个表空间,可以指定各自的配额。另外,创建时可以指定是否是默认fda区,以及保留时间。
create flashback archive default fda1 tablespace fda01 quota 30m retention 1 year;
alter flashback archive fda1 add tablespace fda02 quota 40m;
这里先在fda01上创建了fda区fda1,配合30m,保留1年;然后再将fda02表空间的40m配额加到了fda1上。如果不指定配额,就是无限。
可以创建多个fda区,但是默认的只能有一个。每个fda区有自己的保留时间。
第三步:有了fda区,就可以将某个表的加进fda区,那么这个表的所有变化,就自动记录下来了。但是在这之前,有两个权限的说明一下。
FLASHBACK ARCHIVE ADMINISTER,这个是管理系统所有fda区的,有这个权限,才可以看到sys.dba_flashback_archive表。有这个权限才可以将指定的表,放进fda区。
grant flashback archive administer to fda_admin
要执行闪回,还需要FLASHBACK ANY TABLE 权限,以及DBMS_FLASHBACK的EXECUTE权限。
grant flashback any table to zyz;
grant execute on dbms_flashback to zyz;
有了 FLASHBACK ARCHIVE ADMINISTER,就可以在创建表的时候,直接
create table tbl_test2 (col varchar2(32)) flashback archive;
create table tbl_test3 (col varchar2(32)) flashback archive fda1;
或者对已经存在的表执行
alter table zyz.tbl_test1 flashback archive
alter table zyz.tbl_test1 flashback archive fda1;
alter table zyz.tbl_test1 no flashback archive;
这里,还没提供直接切换fda区,必须先取消掉已经配额的fda区,再换到别的区
alter table zyz.tbl_test1 no flashback archive;
alter table zyz.tbl_test1 flashback archive fda2;
前面当然也说到,fda实际是一个逻辑概念(虚的),所以用户还得有fda背后的表空间的访问权限和配额才可以。
第四步:配置好了,现在可以执行回返了。
所谓回返,其实还是query,和flashback query或者flash version query一样,只不过支持的时间或者scn长了很多。
select versions_starttime, versions_endtime, versions_operation, col1 from tbl_test1
versions between timestamp to_timestamp('2015-04-21 10:00','yyyy-mm-dd hh24:mi') and maxvalue;
select * from tbl_test1 as of timestamp (systimestamp - interval '60'minute);

对于fda的admin,有不少他需要做的事情。
select * from  dba_flashback_archive_ts查看有哪些fda区
select * from  dba_flashback_archive;查看哪些表放进了哪个fda区
select * from dba_flashback_archive_tables;查看fda区里的内容
alter flashback archive fda2 modify tablespace fda01 quota 50m;修改配额
alter flashback archive fda1 modify retention 1 day;
alter flashback archive fda1 remove tablespace fda02;去掉表空间
drop flashback archive fda1;删除fda区
 select current_scn from v$database;
alter flashback archive fda1 purge before scn 3232323; 清空scn以前的数据
alter flashback archive fda1 purge before timestamp (systimestamp - interval '1' day);
 alter flashback archive fda1 purge all;


fda的限制,不像flash query,flash version query,fda在truncate表,增删列,rename表,dropb表后仍然有效,因为它就是一个记录的log,不像ddl会清空undo数据。

2015年4月19日星期日

flashback

tspitr恢复restore recovery啥的很费时间,依赖archivelog和redo,flashbacckup功能则基本靠undo,只要在undo里面,不用restore和recovery就可以恢复数据。

flashback的功能分类
a。flashback drop不依赖undo。
b。flashback database不依赖undo,依赖flashback log。
c。flash query(包括flashback query, flashback version query, flashback transaction query)依赖undo
d。flashback table依赖undo
e。flashback data archive不依赖undo。11g新增的。

1.flashback drop。
flashbackup drop不依赖undo,因为drop语句不是dml,不进undo。oracle搞了一个回收站recyclebin,drop后进这里。回收站的东西的删除是自动的,当表空间不够时,会自动被删,这里的表空间不够是说在【表自动扩张前】的不够,也就是表空间不够时,会先去删recylebin,不够的话再去扩张。回收站以schema单位存在,所以普通用户也是可以查看恢复自己的表。
打开recycylebin,看recyclebin paramer,为on表示已经启动了。默认就是on。这个参数是可以session级别修改的 alter session  set recyclebin = off。
普通用户select * from user_recyclebin或者recyclebin可以看自己的,dba用dba_recyclebin看全部。回收站里的只能看,不能再ddl或者dml了。要恢复时,用
flashback table 原来表名 to before drop。恢复时根据【后进先出】规则,比如一个表建了删删了再建再删,反复drop了n次,那么,flashback table时先恢复最后删的。
当然,也可以直接fashback table 垃圾相里的名字 to before drop,这样就可以直接恢复指定时间的表了。
恢复是,可以重命名表名
flashback table zyz to before drop rename to zyz_flashback。
drop 表的时候,和表相关的比如索引约束triger啥的,会一起进recyclebin,但是flashback时,也会restore回来,但是名字不会变,这个得自己去重命名alter index bin$xxx rename to xxx这样。当然,重建也是可以的。
可以用
purge table  tablename
purge index indexname
purge tablespace tablespacename
purge user_recyclebin
purge dba_recyclebin
来清空垃圾或者垃圾的object。
flashback drop不支持存储过程或者函数,如果不小心删掉了,得用flashback query(从dba_source或者all_source里面往回找)
flashback drop不支持system表空间里的对象,删掉了就没了。

2。flashback query
可以查会以前的数据内容,只要还在undo里。
用时间转换
select * from tbl_test1
as of timestamp to_timestamp('2015-04-19 20:00:00', 'YYYY-MM-DD HH24:MI:SS');
时间查
select * from tbl_test1
as of timestamp (systimestamp - interval '60' minute);
先找scn再query
select timestamp_to_scn(systimestamp - interval '60' minute) as scn from dual;
select * from tbl_test1
as of scn 8734545


3.flashback version query
可以查询一段时间或者scn内的数据演变,只要这些数据还在undo里面
根据scn
select versions_starttime, versions_endtime, versions_operation col1 from tbl_test1
versions between scn minvalue and maxvalue
根据实际
select versions_starttime, versions_endtime, col1 from tbl_test1
versions between timestamp to_timestamp('2015-04-19 20:00:00', 'YYYY-MM-DD HH24:MI:SS') and to_timestamp('2015-04-19 21:00:00', 'YYYY-MM-DD HH24:MI:SS');
这里可以有几个伪列
versions_starttime
versions_endtime
versions_startscn
versions_endscn
versions_operation
versions_xid 当时的transaction id
version query对外部表(外部表只能select,不能dml),临时表(临时表,虽然有undo,但是comit后或者session完了后就没了),固定表(X$打头的表,oracle内部使用),view都没有效果。

4.flashback transaction query
前面的flashback version只能一个表一个表的看,如果一个事物里面更新了多个表,就回退需要用到flashback transaction了。

flashback transaction (query)需要archivemode才可以。
使用条件,使用flashback transaction的话11g需要开启附加log(supplemental logging)功能,这个功能默认情况下是关闭的。这个功能更分几个级别。附加log会影响redo的产生。
alter database add supplemental log data; 打开是最小功能min。
alter database add supplemental log data(all) columns;
alter database add supplemental log data(primary key) columns;
alter database add supplemental log data(unique) columns;
alter database add supplemental log data(foreign key) columns;

调整了这些参数后,虽然会立刻反应进v$database,但需要重新启动instance才干活。

查看打开的级别
select supplemental_log_data_min, 这个最小构成
supplemental_log_data_pk, 是否打开了主键的附加log
supplemental_log_data_ui, unique key的log

supplemental_log_data_fk, 外键的log
supplemental_log_data_all,是否支持所有类型,比如LONG,LOB等集合
from v$database;
另外,用户也需要权限select any transaction的权限
grant select any transaction to zyz;
满足这个最小mini条件后,再谈flashback transaction的功能。
另外,flash drop或者flash query是不需要 supplemental logging开启的。


先用flashback version找到versions_xid,然后再根据xid查找事物。这个是在flashback_transaction_query里面表里有字段
xid
table_name
start_scn
logon_user
operation
undo_sql 可以执行这个sql,进行将数据还原
select * from flashback_transaction_query
where xid = '01001700A7160000'

5.flashback transaction
flashback transaction 除了flashback transaction query的前提条件外,还需要 dbms_flashback.transaction_backout的执行权限。
使用dbms_flashback.transaction_backout来取消transaction
有三个参数,一个numtxns表示后面xids有多个item,一个xids是一个数组,数组元素是transaction的xid。
decalre
  trans_arr sys.xid_array
begin
  trans_arr := sys.xid_array('01001700A7160000 ');
  dbms_flashback.transaction_backout(numtxns => 1, xids => trans_arr);
end
这个我没执行成功,报错
ORA-55507:Encountered mining error during Flashback Transaction Backout. function:krvxglsr ORA-01291: missing logfile
查询了一些资料,开去了附加log的pk和fk,仍然不成功。
这个func还有第三个参数
分别是
NOCASCADE,事务不被依赖,自己做自己的取消,有依赖时就失败。
CASCADE,将依赖事务也给取消
NOCASCADE_FORCE,不考虑其他依赖事务,先自己取消。其他依赖事物照样执行。
NONCONFILICT_ONLY,只取消和其他事务没冲突的。
例子
比如有数据3行,分别值1,2,3。
tx1修改后变成值为11,22,33。tx2修改后变成11,222,333。现在打算backout tx1。
NOCASCADE,报错,因为tx2依赖tx1。
CASCADE,均回退,数据变成1,2,3。
NOCASCADE_FORCE,tx1取消(取消了t1更新的3行),tx2照样执行,结果变成1,222,333
NONCONFILICT_ONLY,tx1取消(取消了t1更新的第一行,因为2,3行在tx2里),tx2照样执行,结果变成,1,222,333

用dbms_flashback.transaction_backout恢复后,还需要手动commit或者rollback的。

最后,这个dbms_flashback已经不光只用到了undo,它其实后面用了logminer去找redo和archivelog了。

可以通过
dba_flashback_txn_state 查看已经取消了的transaction的依存关系
dba_flashback_txn_report 查看依存transaction的具体信息

untilClause

http://docs.oracle.com/cd/B28359_01/backup.111/b28273/rcmsubcl018.htm#RCMRF160

都不包括指定的值,比如scn,time等。

tspitr功能的测试

10g就有了以【表空间为单位】的定点恢复,这里测试如下


targetdb自然必须是archive模式才可以,并且恢复后,恢复点以后的原来rman备份的的东西都不在有用,【没使用catalog的情况下,只能恢复一次,恢复后不能再次恢复】,这的确不是件好事(所以还是flashbackup table好用)。tspitr流程大概就是创建启用辅助(auxiliary)db,将数据按点clone到辅助db上,在辅助db上resetlog open后,将表空间的数据和词典倒腾(expdp,impdp)回来。

tspitr不能恢复直接删除或者重新命名后的表空间。

准备工作。
1。要恢复,要求恢复的表空间必须是自包含的。
select *
from ts_pitr_check
where (ts1_name = 'ZYZ' and ts2_name <> 'ZYZ')
or (ts1_name <> 'ZYZ' and ts2_name = 'ZYZ')
检查一下,如果有和别的表空间关联,也需要一起恢复。
2。恢复到某一个点后,这个点以后创建的objet都会没有了,可以查看一下是哪些object,必要的情况下,先export出来
select owner, name, tablespace_name, creation_time
from ts_pitr_objects_to_be_dropped
where tablespace_name = 'ZYZ'
and creation_time > '15-04-18'
这里,我的NLS_DATE_FORMAT是RR-MM-DD

开始恢复
恢复有3个模式,内容基本一样,
1。rman全自动
recover tablespace zyz until time "TO_DATE('2015-04-19','YYYY-MM-DD')" auxiliary destination '/ORADATA/aux'
 过程中,虽然targetdb的instance没有重新启动,但是在最后的impdb时,ZYZ是offline了再impdb的后再online的,看target的alertlog里面有
alter tablespace ZYZ offline immediate
drop tablespace  ZYZ including contents keep datafiles
DM00 started with pid=40, OS id=29123, job SYS.TSPITR_IMP_Bogq
Plug in tablespace ZYZ with datafile
  '/ORADATA/app/oradata/orcl11g/zyz01.dbf'
alter tablespace  ZYZ read write
alter tablespace  ZYZ offline
也就是最后没将它online,我们还得手动将表空间online
执行alter tablespace  ZYZ online
2. rman clone instance,但是可以修改修改run的script。
3.全都自己搞


2015年4月17日星期五

rman来复制db

1。用rman来复制db,本地步骤如下
源orcl11g,目的orcl11g3
a。先建立一个pfile,我是直接copy源的initorcl11g.ora到initorcl11g3.ora然后修改内容,修改的内容如下把里面的orcl11g都给替换为orcl11g3,由于是local复制,追加了下面两行
*.db_file_name_convert=(/ORADATA/app/oradata/orcl11g,/ORADATA/app/oradata/orcl11g3)
*.log_file_name_convert=(/ORADATA/app/oradata/orcl11g,/ORADATA/app/oradata/orcl11g3),免得文件冲突。
b。oracl里面用到的目录都给mkdir -p一下
c。有了pfile,就可以启动instance了,startup nomount pfile=initorcl11g3.ora,启动后就create spfile from pfile,然后重新启动再次进nomount。
d。需要将orcl11g3静态注册进listener.ora
SID_LIST_LISTENER =
   (SID_DESC =
     (GLOBAL_DBNAME = orcl11g3)
     (ORACLE_HOME = /ORADATA/app/product/11.2.0/dbhome_1)
     (SID_NAME = orcl11g3)
     )
  )注册后重新启动一下lsnrctl,然后lsnrctl service看一下是否有。到此,目标的东西就完事了。
f。需要创建pwfile,直接orapwd file=$ORACLE_HOME/dbs/orapworcl11g3 password=oracle entries=5 
e。现在开始复制。直接rman target / auxiliary sys/oracle@orcl11g3,进去后duplicate target database to orcl11g3;就完事了。当然也可以指定要duplicate到啥时,啥restore point。

2。异地复制,目前我看到的是,还不支持直接复制(配送tnsname.ora后直接duplicat),还是需要将源的备份上载到目的地,然后再在目的duplicate。
a。在目的地,同样先建立instance。
b。将备份文件上载到目的,比如scp啥的
c。上目的地, rman auxiliary / ,然后执行duplicate target database to dup backup location '/ORADATA/app/flash_recovery_area/ORCL11G';就完事了,当然也可以在源执行rman, rman  auxiliary sys/oracle@orcl11g3,这时就需要配置tnsname.ora了。



前面两个法子,都是rman对已经备份的内容进行clone,11g支持了在线clone db。语法是
duplicate target database to 目标db from active database。这个我也进行了测试。
首先,得明确一点,要在线clone,targetdb必须是archivelog模式才行。
另外,执行 rman target / auxiliary sys/oracle@orcl11g3里面执行active clone,会报ORA-17627: ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
这个修改为给用户和密码连接就可以
rman target sys/oracle@orcl11g auxiliary sys/oracle@orcl11g3
duplicate target database to orcl11g3 from active database;
这里我遇到了RMAN-05541: no archived logs found in target database错误,然后直接3次alter system switch logfile;产生archivelog后过去了。
对于异地的archive clone呢?这个就得赞了,完全一样,不用手动拷贝啥文件了。

另外,我试用了用EM来做clone,11g r2的EM DataControl的clone不支持 clone到别的机器,只能在一台机器做,网上search,据说grid control可以,就不知道了。
https://community.oracle.com/thread/379851

2015年4月14日星期二

oracle的checkpoint

前面测试noarchivelog模式下备份时,说到了正常showdown照理应该会发出checkpoint,所以感觉不必要再shutdown前alter system checkpoint;

追了一下checkpoint的知识。
先alter system set log_checkpoints_to_alert=true;后随便修改点啥commit后shutdown immediate,发现log里面的确没有checkpoint的信息,咋回事,需要琢磨琢磨了。

11g的em

http://docs.oracle.com/cd/B14099_19/manage.1012/b16242/structure.htm
11g的em有3个产品
1.Database Control,这个针对一个数据库的管理,可以rac
2.Application Server Control 可以管理多个application server
3.Grid Control,这个可以管理多个数据库和application server
Database Control安装是可以直接用,其他两个是单独安装。这里只对Database Control来说事。
   
11g的em是用一个oc4j(oracle container for j2ee)的application server(类似tomcat),程序在
$ORALCLE_HOME/oc4j 下。这个server是oc4j.jar,oc4j/j2ee/home/applications目录下放着应用,也其实Database Control只是oc4j的一个应用而已。配置文件是各自的ORACLE_UNQNAME目录下的server.xml。比如
/ORADATA/app/product/11.2.0/dbhome_1/oc4j/j2ee/OC4J_DBConsole_192.168.101.40_orcl11g/config/server.xml 。
所以,理论上,respo报错的db和要监控的target db可以不一样,但是实际是不可以的。

11g的em,Enterprise Manager Agent来收集数据,然后汇报给

如果开始没给db挂em,用这个
emca -config dbcontrol db -repos recreate

 emctl status dbconsole看状态,如果说没定义ORACLE_UNQNAME,那么设置环境变量,这个值是数据库的DB_UNIQUE_NAME参数,没修改一般就是ORACLE_SID。但是这个参数设置了,用在哪里还是不知道。
[oracle@NKV2DEVDB_O 192.168.101.40_orcl11g]$ emctl status dbconsole
Oracle Enterprise Manager 11g Database Control Release 11.2.0.1.0
Copyright (c) 1996, 2009 Oracle Corporation.  All rights reserved.
https://192.168.101.40:1158/em/console/aboutApplication
Oracle Enterprise Manager 11g is running.
------------------------------------------------------------------
Logs are generated in directory /ORADATA/app/product/11.2.0/dbhome_1/192.168.101.40_orcl11g/sysman/log  

这里可以看见em log的位置,这个是ORACLE_HOSTNAME_sid拼出来的,由于我的hostname里面有下划线,所以我单独定义了ORACLE_HOSTNAME。

 常用的命令
emctl start console  启动
emctl stop console 停止
emca -repos create创建repos库,这个是设置将repos保存在哪个数据库。会在这个库里增加sysman用户,会让设置sysman的密码,然后创建一堆表。
emca -repos recreate重新创建repos库 
emca -repos drop 删除repos库
emca -config dbcontrol db 配置Database Control要监控的target db,得先有repos才能配置,因为要输入创建repos时设置的sysman的密码
emca -deconfig dbcontrol db 删除Database Control
emca -reconfig ports 修改db control和agent的端口
或许要问为啥repos和dbconsole要分开配置,因为repos是一个大的仓库,而dbconsle指示仓库里面的一个物件罢了,repos还可以放很多别的东西。

cat $ORACLE_HOME/install/portlist.ini可以看到console和agent的端口分别是1158,3938。
这里看到了agent,agent是真正采集监控数据库的程序,它监控了target数据库的一切,然后将内容上载到oms,oms入repos。设计上,agent是完全可以独立于oms,这也是grid的设计思想。
可以
emctl status agent
查看agent的状态
可以看到这里
Agent URL         : https://192.168.101.40:3938/emd/main
Repository URL    : https://192.168.101.40:1158/em/upload/
所以agent其实也开了一个http的server,它同oms的heartbeat就靠这个了。进程是bin/emagent

emca -reconfig ports -dbcontrol_http_port 1159
emca -reconfig ports -agent_port 3939

一个em只能挂一个instance,grid的em才可以挂多个。
所以em只能管理自己 ,并且repos也只能存自己里面(以sysman用户)。一台机器可以启动多个instance,想来em也应该可以启动多个分别管理自己的instance,如何搞?我尝试了一下。
 其实oracle已经考虑到这个问题,直接执行
 emca -config dbcontrol db -repos create后,在sid的db里创建完库后,会根据当前的情况选择别的端口来进行配置。
 cat $ORACLE_HOME/install/portlist.ini可以得到
Enterprise Manager Console HTTP Port (orcl11g) = 1158
Enterprise Manager Agent Port (orcl11g) = 3938
Enterprise Manager Console HTTP Port (orcl11g2) = 5500
Enterprise Manager Agent Port (orcl11g2) = 1830

这也就是起了两个em,管理着两个instance了。但是emctl没有instance的参数啊,所以需要 ORACLE_SID(不是用ORACLE_UNQNAME)来切换着管理

 

2015年4月12日星期日

NOARCHIVELOG下的备份和恢复 -rman

一直以来,感觉到rman不可以给noarchivelog工作,因为书上说,noarchivelog要备份,就得停。而rman要求连接上数据库的。

noarchivelog下,open时执行backup database会直接
ORA-19602: cannot backup or copy active file in NOARCHIVELOG mode 

所以,要rman,就必须得mount,要留意的是停的时候不要abort停下来,比如用startup noforce是不行的。另外,shutdown 之前,最好执行一下 alter system checkpoint,将脏块内容(写到了redo log里面但是没写到datafile里)都写回到datafile,否则就算正常shutdown,执行时仍然会报ORA-19602。虽然说shutdown照理应该也会自动发出checkpoint,但是我的确遇到这样的问题。

run {
allocate channel oem_disk_backup device type disk;
recover copy of database with tag 'ORA_OEM_LEVEL_0';
backup incremental level 1 cumulative  copies=1 for recover of copy with tag 'ORA_OEM_LEVEL_0' database;
}
第一句是recover一下,如果没有对应的tag,啥也不干。
第二句直接下指示备份 level1的累积增量,没有level0时,rman会自动copy datafile来当做level0备份。
执行模拟
第一天, recovery啥也不干,backup 了full 的level0,是img copy。
第二天,recovery啥也不干(因为还没有增量),backup了增量,增量自然是bacupset。
第三天,recovery将第二天的增量反应进level0的dbf,backup了增量
这样下来,每天都得到了差一个增量的dbf。

这样rman备份的东西,就可以用rman恢复了

startup force nomount
如果没使用catalog管理,需要set dbid 972690783
restore controlfile from autobackup;
alter database mount;
restore database;
redolog丢失或者增量备份不能反映进redolog时,recover database noredo;
alter database open resetlogs;

我这样做了,也恢复了数据库,但是em却完蛋了
Service is not initialized correctly. The Em Key is not configured properly. Run "emctl status emkey" for more details
因为我测试时,是先backup,后再create的em的repos。
 测试了
[oracle@NKV2DEVDB_O config]$ emctl status emkey -sysman_pwd oracle
Oracle Enterprise Manager 11g Database Control Release 11.2.0.1.0
Copyright (c) 1996, 2009 Oracle Corporation.  All rights reserved.

The Em Key is not configured properly or is corrupted in the file system and does not exist in the Management Repository. To correct the problem:
1) Copy the emkey.ora file from another OMS or backup machine to the OH/sysman/config directory.
2) Configure the emkey.ora file by running "emctl config emkey -emkeyfile <emkey.ora file location>".
[oracle@NKV2DEVDB_O config]$ emctl config emkey -emkeyfile /ORADATA/app/product/11.2.0/dbhome_1/192.168.101.40_orcl11g/sysman/config/emkey.ora -force -sysman_pwd oracle
Oracle Enterprise Manager 11g Database Control Release 11.2.0.1.0
Copyright (c) 1996, 2009 Oracle Corporation.  All rights reserved.

The Em Key could not be configured. /ORADATA/app/product/11.2.0/dbhome_1/192.168.101.40_orcl11g/sysman/config/emkey.ora is corrupted or contains an invalid Em Key.
[oracle@NKV2DEVDB_O config]$ emctl config emkey -repos -sysman_pwd oracle -emkeyfile /ORADATA/app/product/11.2.0/dbhome_1/192.168.101.40_orcl11g/sysman/config/emkey.ora
Oracle Enterprise Manager 11g Database Control Release 11.2.0.1.0
Copyright (c) 1996, 2009 Oracle Corporation.  All rights reserved.

The Em Key could not be configured. The Em Key was not found in Management Repository.

都不灵,没法子,重新来过
emca -deconfig dbcontrol db -repos drop
emca -config dbcontrol db -repos create

NOARCHIVELOG下的备份和恢复

最基本的,当然是用OS命令来做
备份:正常停数据库,拷贝datafile和controlfile+(online redo可以选),startup。
恢复:
分两个情况,一是备份后,redo log没被覆盖过,这时,进mount模式后,将损失了的datafile only拷贝回去,然后recover datafile file#后,alter database open,就可以了,可以做到完全恢复。
另外一个是绝大多数情况,redo已经被覆盖了,没法子,停数据库,将所有文件(datafile+controlfile)拷贝回去,启动数据库。如果先前备份了online redo,那么启动不会出错。
如果没备份online redo,拷贝回去的datafile+controlfile和redo是对不上号,启动会出错(ORA-00338: log 1 of thread 1 is more recent than control file)后进不了open,这个时候就比较麻烦了。
 alter database clear logfile group 1 的语句可以清除掉非current的log,但是对current的log时清除不掉,直接报
ORA-01624: log 1 needed for crash recovery of thread 1。
由于没有任何其他备份,让current的redo log还原就很麻烦了。搞了好久,找到了一个未公开的参数_allow_resetlogs_corruption=TRUE。
操作方法如下
1. startup nomount
2.create pfile='/tmp/pfile.ora' from spfile;
3.再创建的pfile里面加上*._allow_resetlogs_corruption=TRUE;
4.再次startup mount pfile=' /tmp/pfile.ora'
5.今后show parameter _allow;看看是否设置上
6.recover database until cancel; 用cancel,这里会报错,无视。
7.alter database open resetlogs;这时就可以open了。
如果不设置_allow_resetlogs_corruption,7是open不了的。 这个方法针对current log丢失时又没备份时用。
看到这里,所以, NOARCHIVELOG下的手动备份还是建议将online redo也给备份一下

另外,这里我也开始尝试重新create controlfile了,结果mount都不行了,直接
ORA-01079: ORACLE database was not properly created, operation aborted


2015年4月10日星期五

控制文件全损的时候,如何恢复

控制文件没有了后,系统不会自己down,但是shutdown immedate时,就会报错了
ORA-00210: cannot open the specified control file
ORA-00202: control file: '/ORADATA/app/oradata/orcl11g/control01.ctl'
ORA-27041: unable to open file
直接shutdown abort;
然后startup nomount;
打算用rman来恢复
然后用set dbid xxxxxx来做,但是nomount下,v$database是看不见的。咋办,如何得到dbid? 怎么办

1.alter session set tracefile_identifier = arup;
2.alter system dump datafile '/ORADATA/app/oradata/orcl11g/system01.dbf' block min 1 block max 10;
3.去到trace的目录/ORADATA/app/diag/rdbms/orcl11g/orcl11g/trace,
ls *ARUP*
看到dump出来了system tablespace的头block文件trc
view orcl11g_ora_23536_ARUP.trc
往下找,可以找到
Start dump data block from file /ORADATA/app/oradata/orcl11g/system01.dbf minblk 1 maxblk 10
 V10 STYLE FILE HEADER:
        Compatibility Vsn = 186646528=0xb200000
        Db ID=972690783=0x39fa155f, Db Name='ORCL11G'
这里就找到了dbid了

赶紧在rman里面
set dbid  972690783
restore controlfile from autobackup;
如果不执行set dbid  972690783,会报

Starting restore at 10-APR-15
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=189 device type=DISK

recovery area destination: /ORADATA/app/flash_recovery_area
database name (or database unique name) used for search: ORCL11G
channel ORA_DISK_1: AUTOBACKUP /ORADATA/app/flash_recovery_area/ORCL11G/autobackup/2015_04_10/o1_mf_s_876691401_blhj5tm7_.bkp found in the recovery area
AUTOBACKUP search with format "%F" not attempted because DBID was not set
channel ORA_DISK_1: restoring control file from AUTOBACKUP /ORADATA/app/flash_recovery_area/ORCL11G/autobackup/2015_04_10/o1_mf_s_876691401_blhj5tm7_.bkp
channel ORA_DISK_1: control file restore from AUTOBACKUP complete
output file name=/ORADATA/app/oradata/orcl11g/control01.ctl
output file name=/ORADATA/app/flash_recovery_area/orcl11g/control02.ctl
Finished restore at 10-APR-1
虽然会报,但是其实控制文件还恢复成功了的,这是因为我用了catalog管理功能,如果没有catalog功能,不设置dbid是恢复不了的。

接着
alter database mount;
recover database;
alter  database open resetlogs;

done!

rman复习3

使用catalog来管理备份meta。catalog的database最好独立于target(放到targetdb里面,如果targetdb完蛋了哦,catalogdb也就完蛋了),磁盘占用很少,一个catalog db可以管理多个target db。

1。先在catalog db里面创建表空间,创建catalog的用户,分派权限
CREATE TABLESPACE rmancat DATAFILE '/ORADATA/app/oradata/orcl11g2/rmancat01.dbf' SIZE 15M

CREATE USER rcadmin IDENTIFIED BY rcadmin
DEFAULT TABLESPACE rmancat
QUOTA UNLIMITED ON rmancat;

GRANT recovery_catalog_owner TO rcadmin;

2。然后连接上catalog db创建 catalog
rman catalog rcadmin/rcadmin@orcl11g2
create catalog;
可以用drop catalog删除

3。然后同时连接上target和catalog,注册
rman target / catalog rcadmin/rcadmin@orcl11g2
register database;
可以用unregister database来注销登录
注册后,会同步目前的控制文件里面的backup meta到catalog db里

虽然有了catalog db,但是控制文件的backup meta还是会写,catalogdbl只是为了更长期的保存。默认情况下,控制文件里面的bacup meta保存7天(CONTROL_FILE_RECORD_KEEP_TIME),有了catalog,就可以一直保存了。
一直保存,用backup keep forever database。使用bacup keep指令后的备份,不在retention policy的管理范围。一般情况下,对特殊的日子,进行backup keep指令,比如设置保存1年。
backup keep until time 'sysdate+365' database;

如果catalogdb坏掉了,可以重新创建catalogdb,毕竟catalogdb不是很重要,但是控制文件里的信息只有7天,其他的不再控制文件的管理范围,这时,可以执行
CATALOG START WITH '/ORADATA/app/flash_recovery_area/ORCL11G';来将其他文件也加到catalog里。
catalog recovery area [noprompt]将flash领域的都给catalog化

如果出现不同步是,执行RESYNC CATALOG再次同步。

有了catalogdb,就可以将常用的rman命令,写成script存起来了,script分两种,global的可以给所有target用,local的只能给固定的targetdb用。
比如
create [global] script inc0{
  backup
  incremental level 0 database
  format '/ORADATA/backup/orcl11g/db0_%d_%s_%p_%t'
  tag = 'level_0';
}
也可以从文件创建
create [global] script inc1 from file '/tmp/rman_script_inc1.txt'
[oracle@NKV2DEVDB_O tmp]$ cat /tmp/rman_script_inc1.txt
{
backup incremental level 1 cumulative database format '/bakup/rman/backup/orcl/db1_%d_%s_%p_%t' tag='level_1';
}
执行script
run {
  execute [global] script inc0;
}
删除script
delete [global] script inc0;
显示script内容
print [global] script inc0;
print [global] script inc0 to file '/tmp/rman_script_inc0.txt'
查看script 的 list
list [global] script names;
更新script
replace [global] script inc0 {
  backup
  incremental level 0 database
  format '/ORADATA/backup/orcl11g/db0_%d_%s_%p_%t'
  tag = 'level_0';
}
另外,操作global的时候,rman只连接上catalogdb就可以。local的,需要同时连接上targetdb和catallogdb


既然一个catalogdb可以register多个targetdb,如果只用一个db用户(比如rcadmin)连接进来,岂不是大家都可以看到别的targetdb的内容了,为了隔离,oracle给大家想了一个vpc(virtual private catalog),方法如下
1。仍然需要创建database
2。仍然需要创建一个老大用户,比如rcadmin
3。给rcadmin赋予recovery_catalog_owner权限
4。rman连进catalogdb,create catalog,到此,创建了catalog,也就创建了东西。
现在要创建各自的用户
5。创建新用户 rcvpc
6。GRANT recovery_catalog_owner TO rcvpc到这里和创建rcadmin是一样的。
7。rman用rcadmin连接catalogdb进行权限分配
GRANT REGISTER DATABASE TO rcvpc让rcvpc可以reister,如果给了这个权限,就是注册register,并且是自己register targetdb的老大。
GRANT CATALOG FOR DATABASE orcl11g TO rcvpc;指定可以访问指定catalog。
这里说的访问,是指list incarnation是否看得见等。
8。先rman用rcvpc连接进catalogdb,然后create virutal catalog创建私有的catalogdb。
9。如果给了register database权限,那么可以同时连接上targetdb和catalogdb,进行register。
10。如果只给了catalog for database xxx的权限,那么只能看了。当然这两个权限是可以同时给一个人的。

同样,在rman里给出去的权限可以收回来
revoke register database from rcvpc
revoke catalog for database nkv2ddb from rcvpc
revoke all privileges from rcvpc
另外,rman的这个权限和oracle的权限有些不一样,不跟session走,是立刻反应的。
比如
有register权限rcvpc先连上了,然后register一个db,当然马上list incarnation看得见,不退出rman,
在另外一边取消掉rcvpc的权限,revoke catalog for database nkv2ddb from rcvpc后,前面的rcvpc就立刻看不久list incarnation并且也无法unregister自己register的database了。





2015年4月9日星期四

oracle的钱包

select * from v$encryption_wallet;
/ORADATA/app/admin/orcl11g/wallet

mkdir -p /ORADATA/app/admin/orcl11g/wallet

case 1.
orapki wallet create -wallet /ORADATA/app/admin/orcl11g/wallet
产生ewallet.p12
alter system set encryption wallet open identified by "password";
v$encryption_wallet里面状态是OPEN_NO_MASTER_KEY
alter system set encryption wallet  close identified by "password";
状态变成close
然后
alter system set encryption key authenticated by "open";
居然状态就open了

 case 2.
 orapki wallet create -wallet /ORADATA/app/admin/orcl11g/wallet  -auto_login_local
产生cwallet.sso
auto_login的,database开机会自动open,并且这个钱包是close不掉的。

要修改钱包密码
orapki wallet change_pwd -wallet /ORADATA/app/admin/orcl11g/wallet
这里会要求输入老密码

如果我将钱包目录的文件删除了会怎样?
instance可以起来,表内容读不出来,会直接ORA-28365: wallet is not open。将文件放回到该在的目录后,还需要重新启动instance才可以。

rman复习2

rman target / debug trace '/tmp/trace.trc' log='/tmp/rman.log'
打开了debug,设置了trace,然后输出到log。
这个log了后,stdout就没输出了,不爽。
rman target / | tee /tmp/rman.log,这样设置后 ,stdout的输出有了,然后rman.log里面也有了,但是输入的命令却在rman.log里面看不见。
可以这样 rman target / | tee /tmp/rman.log进去后,立刻执行set echo on,让回显stdin,这样输入的命令就可以输出到rman.log里了。但是回显会跟着回车走,也打乱输入run{这样的东西,也挺烦。

1.多重备份
rman可以一次指定备份到多个地方,叫【多重bacupset】,这个只能对backupset有效,对imgcopy备份类型无效。
用show all可以看到
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
这个后面的TO 1的1,默认值是备份到1个地方。如果TO 2了,就表示要备份到多个地方。另外,这两个地方不能一个是disk一个是type,必须一样。
这个值也可以被命令里指定的覆盖,比如
backup device type disk copies 2 datafile 4 format '/tmp/%u',/tmp/xxx/%u';

2.备份后backupset的再备份
对于disk类型的backupset,可以再备份
比如将所有的disk上的backpuset 备份到type上
backup device type sbt backupset all;
backup backupset all;

3。备份保存期限,也要archivebackup
可以设置备份的保存期限,这个设置比backup policyl(RETENTION POLICY)里的设置高。
run{
allocate channel c1 type disk format '/tmp/%U';
backup keep until time 'sysdate+365' database;
}
这个备份时,会将控制文件,spfiile,archivelog一起备份(全备份)。另外,keep时需要指定备份保存的地方,不能是默认的DB_RECOVERY_FILE_DEST地方。


4.多section备份
对于很大的表空间,一次要将内容搞到一个backupset里面,这个backupset的文件size会超大,所以可以将一个backupset分开来搞成多个backupset的piece。另外一方面,可以开区并行备份。
configure device type disk parallelism 2;
这样的话,会有两个channel来进行备份,每个channel写不同的piece,从而提高效率。

configure device type disk parallelism 2;
backup section size 250m database;

另外,也可一个直接设置一下一个piece的最大size
configure channel device type disk maxpiecesize = 600m;
然后如果直接backup database,虽然会有两个channel并行,但是是各自chanel各自备份不同的tablesspace,也会出现一个先完事一个后完事的情况。要两个channel能够同时备份一个tablespace的话,必须用backup section来搞。

5。压缩
11g以后的压缩,已经可以对hwm(最高水位)上下 都进行压缩,10g只能对hwm以上的【未使用领域】进行压缩。这里的压缩,其实是skip,因为bacupset本来就不包含未使用的block。
另外,压缩也可以进行二进制压缩,有两个压缩算法,bzip2和zlib。bzip2压缩率高但慢,zlib相反。默认是bzip2。
backup as compressed backupset database;
用configure compression algorithm 'zlib' 修改默认压缩算法。这个是针对11g R1的。
11g R2后,等级变成了basic, low, medium, high4个压缩等级,basic是没压缩。推荐是用low或者medium,因为相对于压缩率的增加,high太占cpu了太慢。另外测试发现low或者medium比basic(不压缩)还要快,世界真神奇。
configure compression algorithm 'HIGH',这里得注意,low,high,medium,basic在命令里都需要大写,否则em页面上显示会不一致。

6。加密
select * from v$rman_encryption_algorithms;知道可以支持的加密方式
加密有三种方式
a透明加密
透明加密,不需要密码,也叫钱包加密,一般只在本地用,也就是在本地备份本地恢复。
configure encryption for database on;
或者
set encryption on;
如果现在执行backup database,会报 ORA-28365: wallet is not open。
所以先要打开钱包,select * from v$encryption_wallet;看一下钱包的路径
比如是/ORADATA/app/admin/orcl11g/wallet,那么先
mkdir -p /ORADATA/app/admin/orcl11g/wallet
然后
orapki wallet create -wallet /ORADATA/app/admin/orcl11g/wallet
这里会要求输入两次密码,然后目录下面会看见 ewallet.p12的文件。
然后
alter system set encryption key authenticated by "zyz123456";设置maskterke?不设置这个会ORA-28361: master key not yet set。
alter system set encryption wallet open identified by "zyz123456";(这一步是不做也可)
引号里面是上一步创建钱包设置的密码
然后再rman里面backup database,就不会说钱包没打开了。
这个方式是,一次设置,以后都加密。
这样加密后的文件,在本地恢复时,也需要执行alter system set wallet open identified by "zyz123456"的,否则还是不让恢复,会报ORA-28361。这个是一次设定,以后都用,但是岂不是每次重新启动instance后都得执行一下alter system set encryption key authenticated by "zyz123456"?
这个嘛,在创建钱包的时候加上-auto_login_local就可以了,instance启动后会自己open wallet。

b密码加密
密码加密,就是在执行备份前设置一个密码,这个当然不要透明加密以前用
configure encryption for database off;
set encryption on identified by "zyz12345" only;
backup database
恢复是,需要先
set decryption identified by "zyz12345";
再恢复,否则也是ORA-28361。也就是每次你都得记住你压缩的密码才可以解压了。


c双模式加密
就是用上面两个法子加密。
set encryption on;
set encryption on identified by "zyz12345";
然后备份 ,恢复是也需要指定两次密码。当然,就算set encryption on了,只要在后面加上only,也就变成第二种了。
set encryption on identified by "zyz12345" only;  

7备份恢复时,除去某些表空间
CONFIGURE EXCLUDE FOR TABLESPACE 'users'  除去users
CONFIGURE EXCLUDE FOR TABLESPACE 'users'  CLEAR 恢复users
SHOW EXCLUDE查看设置













db_recovery_file_dest超过了db_recovery_file_dest_size怎么办

虽然flash领域是自己维护的,但是如果DELETION POLICY配置不当也会出现写满的情况,因为rman自己维护只会删除可以删的内容,一旦超过,比如不能archivelog了,instance就down了,alert.log里面出现
ORA-19809: リカバリ・ファイルの制限を超えています
ORA-19804: 16102912バイトのディスク領域を制限10737418240から再生できません

这个时候,

1.去os删除以前的archivelog文件
2.然后rman里面执行crosscheck archivelog all;
3.然后rman里delete expired archivelog all;

或者直接rman里面
delete archivelog until time 'sysdate-7';

平时要看flash空间使用情况
select * from v$flash_recovery_area_usage

另外,修改 db_recovery_file_dest_size大小也是可以的
alter system set DB_RECOVERY_FILE_DEST_SIZE=40G scope=both;

rman命令的复习1

rman的备份类型:
1.完全备份,默认情况下是as backupset,是full。这里的【完全备份】,不是【数据库的完全备份】,因为没包含spfile,controlfile,archivelog等。
report schema;
backup database
backup [full] datababase
backup as copy database
backup as backupset database
要包含archivelog的话,附加
backup database plus archivelog;
rman的元数据,没使用catalog的情况下,是写在controlfile里面,所以如果设置了controlfile自动备份,一旦执行rman后,controlf就会变,那么也就会立刻自动备份了。
执行的backup database plus archivelog;结尾有这样的内容。
Starting Control File and SPFILE Autobackup at 09-APR-15
piece handle=/ORADATA/app/flash_recovery_area/ORCL11G/autobackup/2015_04_09/o1_mf_s_876592596_bldhp5s4_.bkp comment=NONE
Finished Control File and SPFILE Autobackup at 09-APR-15
设置controlfile自动备份
configure controlfile autobackup on; 字面上只是controlfile,其实spfile也会跟着备份。
这个controlfile自动备份如果没指定db_recovery_file_dest,默认会备份到oraclehome的dbs目录下。

所以backup database plus archivelog;可以认为是【数据库的完全备份】。
backup database plus archivelog delete input; [delete input]指定可以删除已经备份了的archivelog(不是说备份进了backupset的archivelog,而是说log_archive_dest目录下的)。另外如果使用了db_recovery_file_dest,不指定也会自己删,想来因为有了全备份,还要外面的目前到为止的archivelog干啥,因为backupset里面已经有了。

2.增量
增量0
backup incremental level 0 database

增量1差分
backup incremental level 1 database
增量1累计差分
backup incremental level 1 cumulative database

为了增量备份跑得更快,可以打开block tracking功能更来记录block的改变
select * from v$block_change_tracking看是否enable 了block tracking
alter database enable block change tracking  using file '/ORADATA/app/oradata/orcl11g/tracking.dbf';来打开block tracking
这个tracking.dbf坏了的话,是没得救的,只得重新来过,也不是啥重要文件。
查看block tracking的效果,可以看v$backup_datafile表
  SELECT file#,
         AVG (datafile_blocks),
         AVG (blocks_read),
         AVG (blocks_read / datafile_blocks) * 100 AS pct_read_for_backup
    FROM v$backup_datafile
   WHERE used_change_tracking = 'YES' AND incremental_level > 0
GROUP BY file#

2015年4月7日星期二

alter tablespace begin backup时的逻辑

手动时备份,步骤一般是
1.alter tablespace tablespacexxx begin backup
2.!cp dbf文件
3.alter tablespace tablespacexxx end backup
4. alter system archive log current;

步骤是这样,这begin backup都干了啥

下了begin backup指示后,oracle会先触发一个checkpoint,将这个表空间的数据都写进去,然后锁定checkpong scn。以后发生的改变,仍然会写进datafile,但是文件头的scn却不变了。同时,在写datafile时,会将原来(下begin backup时)的数据,弄回进redo里。恢复的时候,再将redo的内容覆盖会datafile,这样来保证和scn的一致。

所以,begin backup后,redo会写得比平常多,可能延缓系统。

如果不下begin backup,恢复的时候可能会失败,因为os的block的写,比db的block的写是多个操作,完全有可能导致文件头的数据和文件内容不一致,以及同一个db block的数据里面的不同os block的数据不一致(cp出来的文件,同一个db block里的os block,一个是更新前一个更新后)。


姑且这么理解

这里有一个问题,那么恢复后的数据,到底是 alter tablespace tablespacexxx begin backup下指示时的,还是cp下指示时的?
其实,由于是archive模式,并且redo log没断的话,默认恢复后会到最后的scn,也就是所谓的【完全恢复】。

2015年4月3日星期五

Data Pump的TRANSPORT_TABLESPACES

11g,这个功能要求src和dst的系统是一样的(可以跨平台,但要求字节顺一样,不一样需要RMAN的Convert转换),不能跨oracle的版本,并且db的字符集也要求一样
1。准备
首先的确定支持的平台
select * from v$transportable_platform
select platform_name from v$database;
有就可以用。 
另外检查一下
select * from transport_set_violations;
有内容的话,就等等先。

2。  开始倒腾
a. 将源弄成只读
alter tablespace zyz read only;
b. expdp倒meta
expdp system dumpfile=expdat.dmp directory=data_pump_dir transport_tablespaces=zyz logfile=export.log;
c. 将文件dmp和dbf搞到目标机器导入meta就完事了
impdp system dumpfile=expdat.dmp directory=data_pump_dir transport_datafiles='/ORADATA/app/oradata/orcl11g/zyz01.dbf' logfile=import.log
d.最后恢复表空间读写
alter tablespace zyz read write;
 
data_pump_dir的目录可以select * from dba_directories找到,当然也可以随便指定目录

2015年4月2日星期四

ORA-25152,不让删TempFile

ASM的一个dg磁盘快到80%了,一看是Temp表空间文件太大了,打算切换文件后delete。由于是tempfile,所以必须先offline,再drop,不能像对普通datafile一样直接使用一个命令offline drop。

1。追加一tempfile进temp表空间
ALTER TABLESPACE TEMP ADD TEMPFILE  SIZE 100M AUTOEXTEND ON NEXT 2M MAXSIZE 2G;

2。SELECT * FROM  V$TEMPFILE;找到要offline的文件开始offline
ALTER DATABASE TEMPFILE '+DG_EM/ORCLEM/TEMPFILE/temp.268.865449357' OFFLINE;

3。打算删
ALTER DATABASE TEMPFILE '+DG_EM/ORCLEM/TEMPFILE/temp.268.865449357' DROP INCLUDING DATAFILES;
这里报错了ORA-25152,不让删,虽然offline了,但是还是不让删

4。找到谁在使用
SELECT S.SID, S.USERNAME, S.STATUS, U.TABLESPACE, U.SEGFILE#, U.CONTENTS, U.EXTENTS, U.BLOCKS
FROM V$SESSION S, V$SORT_USAGE U
WHERE S.SADDR=U.SESSION_ADDR
ORDER BY U.TABLESPACE, U.SEGFILE#, U.SEGBLK#, U.BLOCKS;

5。然后kill掉
SELECT SID,SERIAL# FROM V$SESSION WHERE SID = 249;
ALTER SYSTEM KILL SESSION '249,59266';

6。再删看看
ALTER DATABASE TEMPFILE '+DG_EM/ORCLEM/TEMPFILE/temp.268.865449357' DROP INCLUDING DATAFILES;

done!

Oracle ASM Configuration Assistant画面里面volumes是gray的?

这个时候,执行
acfsload start -s
启动acfs就可以了,因为默认安装下acfs没有启动