commit ae2f83f5787c4addf751d4293f40b758209fe820 Author: zeek <984294471@qq.com> Date: Sun Feb 23 22:23:40 2020 +0800 迁移仓库 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7057f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.idea +*.swp +*.class +*.out +~* +_book +node_modules +.ropeproject +*.target diff --git a/C_C++/.gitignore b/C_C++/.gitignore new file mode 100755 index 0000000..97a3b00 --- /dev/null +++ b/C_C++/.gitignore @@ -0,0 +1,6 @@ +tags +*/out/* +*/out/ +/out/* +*.o +*.out diff --git a/C_C++/README.md b/C_C++/README.md new file mode 100644 index 0000000..63c3dff --- /dev/null +++ b/C_C++/README.md @@ -0,0 +1 @@ +# C++ diff --git a/C_C++/make.sh b/C_C++/make.sh new file mode 100755 index 0000000..80914b9 --- /dev/null +++ b/C_C++/make.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +#author: lzh +#echo `pwd` +if test -z $1;then + echo "./make.sh -[sources]" + exit 1 +fi +echo "prepare" +if [ ! -d "./out" ];then + mkdir out + echo "mkdir out" +fi +echo "prepare finish \n compile" +resource="/sources/$1" +tmp=`echo ${resource} | sed -e "s:sources:out:g"` +out=`echo ${tmp} | sed "s:.c:\.o:g"` +outPath=`dirname ${out}` +if [ ! -d "`pwd`${outPath}" ];then + mkdir `pwd`${outPath} + echo "mkdir `pwd`${outPath}" +fi +gcc -g `pwd`${resource} -o `pwd`${out} +echo "finish" diff --git a/C_C++/sources/c_and_pointer/chapt2/practise/check.c b/C_C++/sources/c_and_pointer/chapt2/practise/check.c new file mode 100644 index 0000000..555810b --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt2/practise/check.c @@ -0,0 +1,44 @@ +#include +#include + +int main () +{ + char str[20]; + printf("输入文件名:"); + gets(str); + FILE *fp = fopen(str, "r"); + if (fp == NULL ) + { + printf("file open failed\n"); + return 1; + } + char buff[255]; + fgets(buff, 255, fp); + fclose(fp); + //printf("\n%s\n", buff); + int i = 0; + int left = 0, right = 0; + for ( i = 0 ; i < 255; i++ ) + { + if ( buff[i] == '\0' || left < right ) + { + break; + } + if ( buff[i] == '{' ) + { + left ++; + }else if ( buff[i] == '}' ) + { + right ++; + } + } + if ( left == right ) + { + printf("花括号成对出现\n"); + } + else + { + printf("花括号不成对出现\n"); + } + return 0; +} diff --git a/C_C++/sources/c_and_pointer/chapt2/practise/increment.c b/C_C++/sources/c_and_pointer/chapt2/practise/increment.c new file mode 100644 index 0000000..86a0a04 --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt2/practise/increment.c @@ -0,0 +1,10 @@ +#include + +/** + * 加1 + * + */ +int increment1 ( int num ) +{ + return num + 1; +} diff --git a/C_C++/sources/c_and_pointer/chapt2/practise/main.c b/C_C++/sources/c_and_pointer/chapt2/practise/main.c new file mode 100644 index 0000000..7bc39de --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt2/practise/main.c @@ -0,0 +1,10 @@ +#include +#include "increment.c" +#include "negate.c" + +int main() +{ + printf("increment(10) = %d\n", increment1(10)); + printf("negate(10) = %d\n", negate1(10)); + return 0; +} diff --git a/C_C++/sources/c_and_pointer/chapt2/practise/negate.c b/C_C++/sources/c_and_pointer/chapt2/practise/negate.c new file mode 100644 index 0000000..8d029e8 --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt2/practise/negate.c @@ -0,0 +1,10 @@ +#include + +/** + * + * 返回该数的负值 + */ +int negate1 ( int num ) +{ + return 0 - num; +} diff --git a/C_C++/sources/c_and_pointer/chapt2/squares.c b/C_C++/sources/c_and_pointer/chapt2/squares.c new file mode 100644 index 0000000..c1f0779 --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt2/squares.c @@ -0,0 +1,26 @@ +#include +/** + * + * 注释不能嵌套 + * + **/ + + +void squares ( int limit ) +{ + int i; /* loop counter */ + /* + * Print table of squares + */ + for (i = 0; i < limit ; i ++) + { + printf("%d %d0", i, i * i); + } + printf("\n"); +} + +int main() +{ + squares(7); + return 0; +} diff --git a/C_C++/sources/c_and_pointer/chapt4/test4_2.c b/C_C++/sources/c_and_pointer/chapt4/test4_2.c new file mode 100644 index 0000000..b522206 --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt4/test4_2.c @@ -0,0 +1,31 @@ +#include + +int prime(int num) +{ + if ( num <=2 ) return 0; + int i,result; + result = 0; + for ( i = 2; i < num ; i++ ) + { + if ( num%i == 0 ) + { + result = 1; + break; + } + } + return result; +} + +int main() +{ + int i; + for ( i = 0; i < 100 ; i++) + { + if ( prime(i) == 0 ) + { + printf("%d\t", i); + } + } + printf("\n"); + return 0; +} diff --git a/C_C++/sources/c_and_pointer/chapt4/test4_3.c b/C_C++/sources/c_and_pointer/chapt4/test4_3.c new file mode 100644 index 0000000..30d8fe8 --- /dev/null +++ b/C_C++/sources/c_and_pointer/chapt4/test4_3.c @@ -0,0 +1,54 @@ +#include + +/** + * + */ +void sort(int arr[],int len) +{ + int i; + for (i = 0; i < len - 1; i++) + { + int j; + for ( j = i+1 ;j < len ;j++ ) + { + if (arr[i] < arr[j]) + { + int tmp; + tmp = arr[i];arr[i] = arr[j]; arr[j] = tmp; + } + } + } +} + +int main(int argc,char *argv[]) +{ + if (argc != 4) + { + printf("error!\n"); + return 1; + } + int arr[3]; + arr[0] = atoi(argv[1]); + arr[1] = atoi(argv[2]); + arr[2] = atoi(argv[3]); + //printf("arr[0] = %d,arr[1] = %d,arr[2] = %d\n", arr[0],arr[1],arr[2]); + sort(arr,3); + //printf("arr[0] = %d,arr[1] = %d,arr[2] = %d\n", arr[0],arr[1],arr[2]); + if (arr[2] + arr[1] <= arr[0]) + { + printf("构不成三角形\n"); + } + else if ( arr[1] == arr[2]) + { + printf("等腰三角形\n"); + } + else if ( arr[0] == arr[1] && arr[1] == arr[2]) + { + printf("正三角形\n"); + } + else + { + printf("普通三角形\n"); + } + return 0; +} diff --git a/C_C++/sources/c_and_pointer/test1_1.c b/C_C++/sources/c_and_pointer/test1_1.c new file mode 100755 index 0000000..d278edd --- /dev/null +++ b/C_C++/sources/c_and_pointer/test1_1.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + printf("hello word %s\n", "zeekling"); + return 0; +} diff --git a/C_C++/sources/c_traps_and_pitfalls/test1/test.c b/C_C++/sources/c_traps_and_pitfalls/test1/test.c new file mode 100644 index 0000000..c5d0b0b --- /dev/null +++ b/C_C++/sources/c_traps_and_pitfalls/test1/test.c @@ -0,0 +1,16 @@ +#include +#include + +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: + * ===================================================================================== + */ +int main () +{ + char hello[] = {'h','e','l','l','o',' ','w','o','r','l','d','\n',0}; + printf("hello world\n"); + printf(hello); + return EXIT_SUCCESS; +} diff --git a/C_C++/sources/linux/test1.c b/C_C++/sources/linux/test1.c new file mode 100755 index 0000000..4c69836 --- /dev/null +++ b/C_C++/sources/linux/test1.c @@ -0,0 +1,18 @@ +#include +#include +#include + +int catch(int sign); + +int main(void){ + signal(SIGINT, catch);//将信号与catch函数关联 + printf("lingzhaohui \n"); + sleep(10); + printf("end\n"); + return 0; +} + +int catch(int sign){ + printf("\nyou pressed 'ctrl+c'\n"); + return 1; +} diff --git a/C_C++/sources/linux/test2.c b/C_C++/sources/linux/test2.c new file mode 100755 index 0000000..61510ec --- /dev/null +++ b/C_C++/sources/linux/test2.c @@ -0,0 +1,16 @@ +#include +#include + +int main(void) +{ + pid_t pid; + printf("father \n"); + printf("fork \n"); + pid = fork(); + if(!pid) + printf("child \n"); + else if(pid>0) + printf("i m the parent ,child pid %d\n",pid); + else + printf("fork failed \n"); +} diff --git a/C_C++/sources/offer/offer10.c b/C_C++/sources/offer/offer10.c new file mode 100755 index 0000000..3ef2b30 --- /dev/null +++ b/C_C++/sources/offer/offer10.c @@ -0,0 +1,16 @@ +#include + +int go(int n){ + int count = 0; + while(n){ + count ++; + n = (n-1) & n; + } + return count; +} + +int main(){ + int count = go(9); + printf("%d\n",count); + return 0; +} diff --git a/C_C++/sources/offer/offer11.c b/C_C++/sources/offer/offer11.c new file mode 100755 index 0000000..6411a67 --- /dev/null +++ b/C_C++/sources/offer/offer11.c @@ -0,0 +1,19 @@ +#include + +int power(double base, int expo){ + if(expo <= 0) return 1; + double result; + if((expo%2) == 0){ + result = power(base,expo>>1)*power(base,expo>>1); + }else{ + result = power(base,(expo-1)>>1)*power(base,(expo-1)>>1)*base; + } + return result; +} + + +int main(){ + double result = power(2,4); + printf("%f\n",result); + return 0; +} diff --git a/C_C++/sources/offer/test.c b/C_C++/sources/offer/test.c new file mode 100644 index 0000000..dc1d7e7 --- /dev/null +++ b/C_C++/sources/offer/test.c @@ -0,0 +1,10 @@ +#include +int main(){ + int y = 1,x,a[] ={2,4,6,8,10},*p; + p = &a[1]; + for(x = 0;x<3;x++){ + y = y + *(p+x); + } + printf("%d \n ",y); + return 0; +} diff --git a/C_C++/sources/test1/test1_1.c b/C_C++/sources/test1/test1_1.c new file mode 100755 index 0000000..e69de29 diff --git a/C_C++/sources/test1/test1_2.c b/C_C++/sources/test1/test1_2.c new file mode 100755 index 0000000..14adf08 --- /dev/null +++ b/C_C++/sources/test1/test1_2.c @@ -0,0 +1,11 @@ +#include +#include +#include + +char *reverse(char *str){ + +} + +int main(){ + char *str = "hello world null"; +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..239bba5 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ + +## 目录 + +* [ORACLE](http://www.zeekling.cn/gogs/zeek/study/src/master/oracle) +* [Linux](http://www.zeekling.cn/gogs/zeek/study/src/master/linux) +* [Java知识](http://www.zeekling.cn/gogs/zeek/study/src/master/java) +* [Mysql](http://www.zeekling.cn/gogs/zeek/study/src/master/mysql) +* [c语言](http://www.zeekling.cn/gogs/zeek/study/src/master/c) +* [计算机网络](http://www.zeekling.cn/gogs/zeek/study/src/master/network) +* [操作系统](http://www.zeekling.cn/gogs/zeek/study/src/master/computer) +* [个人简历](http://www.zeekling.cn/gogs/zeek/study/src/master/resume) + +## 结束语 + +一个爱学习,不怕孤单的小伙的读书笔记。 + +![呵呵呵,没看到图片吧](https://img.zeekling.cn/images/2020/02/22/1.md.png) + +风骚小书生,呵呵哒 diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..d7bda67 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,36 @@ +# Summary + +* [简介](README.md) + +* [java相关](java/README.md) + +* [linux相关](linux/README.md) + * [常见问题](linux/error.md) + * [树莓派使用](linux/树莓派使用教程.md) + * [awk详解](linux/awk/README.md) + * [Nginx参数调优](linux/nginx.md) + * [git详解](linux/git.md) + * [sed详解](linux/sed/README.md) + * [Linux常用命令](linux/commond.md) + * [centos相关](linux/centos/READMD.md) + * [centos问题总结](linux/centos/centos问题总结.md) + * [centos软件安装](linux/centos/hack软件安装.md) + +* [C/C++](C_C++/README.md) + +* [oracle相关](oracle/README.md) + * [docker下使用oracle](oracle/docker_oracle.md) + * [dual表的用途](oracle/dual表的用途.md) + * [oracle常用命令和函数](oracle/oracle常用命令和函数.md) + * [oracle常见问题](oracle/oracle常见问题.md) + * [oracle数据类型](oracle/oracle数据类型.md) + * [系统相关](oracle/sys/README.md) + * [dbms常用系统包详解](oracle/sys/dbms常用系统包详解.md) + * [oracle常见系统表的用法](oracle/sys/oracle常见系统表的用法.md) + +* [python相关](python/README.md) + +* [计算机网络](network/README.md) + +* [简历](resume/README.md) + * [我的简历--markdown版](resume/mine.md) diff --git a/basic/基础知识.docx b/basic/基础知识.docx new file mode 100755 index 0000000..e491d36 Binary files /dev/null and b/basic/基础知识.docx differ diff --git a/book.json b/book.json new file mode 100644 index 0000000..332cda5 --- /dev/null +++ b/book.json @@ -0,0 +1,75 @@ +{ + "root":"./", + "author":"小令童鞋", + "description":"没有到不了的明天,只有回不了的昨天", + "plugins":["github", + "-sharing", + "-search", + "sharing-plus", + "-highlight", + "expandable-chapters-small", + "mathjax", + "splitter", + "disqus", + "3-ba", + "theme-comscore", + "search-plus", + "prism", + "prism-themes", + "github-buttons", + "ad", + "tbfed-pagefooter", + "ga", + "alerts", + "anchors", + "include-codeblock", + "ace" + ], + "links":{ + "sidebar":{ + "主页":"http://www.zeekling.cn" + } + }, + "pluginsConfig":{ + "sharing":{ + "douban":false, + "facebook":false, + "qq":false, + "qzone":false, + "google":false, + "all": [ + "weibo","qq","qzone","google","douban" + ] + }, + "disqus":{ + "shortName":"zeekling" + }, + "ad":{ + + }, + "include-codeblock":{ + "template":"ace", + "unindent":true, + "theme":"monokai" + }, + "tbfed-pagefooter":{ + "Copyright":"© zeekling.cn", + "modify_label":"文件修改时间", + "modify_format":"YYYY-MM-DD HH:mm:ss" + }, + "3-ba":{ + "token":"zeekling" + }, + "ga":{ + "token":"zeekling", + "configuration":{ + "cookieName":"zeekling", + "cookieDomain":"book.zeekling.cn" + } + }, + "github":{"url":"http://www.zeekling.cn/gogs/zeek"}, + "theme-default": { + "showLevel": true + } + } +} diff --git a/computer/REAMME.md b/computer/REAMME.md new file mode 100755 index 0000000..d73147a --- /dev/null +++ b/computer/REAMME.md @@ -0,0 +1,2 @@ +# 计算机操作系统复习 + diff --git a/java/.gitignore b/java/.gitignore new file mode 100755 index 0000000..edfecb8 --- /dev/null +++ b/java/.gitignore @@ -0,0 +1,4 @@ +tags +*/out/* +*/out/ +/out/* diff --git a/java/README.md b/java/README.md new file mode 100644 index 0000000..a17ab56 --- /dev/null +++ b/java/README.md @@ -0,0 +1,262 @@ +# java 部分 + +## java基础知识 + +* 面向对象的三大特征 + * 继承:继承是类与类的一种关系,比较像集合中的从属于关系。 + * 封装:隐藏类的基本信息,不允许外部程序直接访问,而是通过该类的方法实现对隐藏信息的操作和访问。 + * 多态:方法的重写、重载与动态连接构成多态性; +* 面向对象的六大原则 【参考[设计模式](http://www.zeekling.cn/gogs/zeek/designPattern/src/master/principle)】 + * 单一职责原理:一个类只负责一项职责。 + * 里氏替换原则:劲量不要重写父类的已经实现了的方法,可以用接口等其他方法绕开。 + * 依赖倒置原则:高层模块不应该依赖底层模块,二者应依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。 + * 接口隔离原则:客户端不应该依赖其他不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 + * 迪米特法则:又叫做最小知道原则。就是一个类对自己依赖的类知道越少越好。 + * 开闭原则:尽量通过扩展软件实体行为来实现变化。 +* 数据类型 + * 基本数据类型 + * 数值类型 + * 整型:int(4字节)、short(2字节)、long(8字节)、char(2字节)、byte(1字节)、 + * 浮点型:float(4字节)、double(8字节) + * boolean: boolean(1字节) + * 引用数据类型:数组、对象 + * 强引用:用关键`new`出来的对象,强引用锁指向的对象在任何时候都不会被回收 + * 软引用:用来描述有用但非必须的对象,在内存不足的时候可以回收 + * 弱引用:用来描述非必须的对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发送之前。 + * 虚引用:虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个持有虚引用的对象,和没有引用几乎是一样的,随时都有可能被垃圾回收器回收。 +* java集合 + ![集合类总图](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/list.png) + * Collection:集合类的根接口,list和set都继承自此接口 + * List:有序,可以重复,一般用index标示顺序 + * LinkedList:底层用双链表实现:增加删除效率高 + * ArrayList:底层用数组实现:查找效率高 + * Vector:实现了一个动态数组。和ArrayList相似,但是有以下不同:vector是同步的; + vector包含了许多传统方法,或者只是需要一个可以改变大小的数组的情况。 + * Stack:先进后出 + * set:无序,不能有重复的元素 + * HashSet:HashSet不存入重复元素的规则.使用hashcode和equals + * LinkedHashSet:是对LinkedHashMap的简单包装,对LinkedHashSet的函数调用都会转换成合适的LinkedHashMap方法 + * TreeSet:让存入的元素自定义比较规则;给TreeSet指定排序规则 + * Queue + * Map:由键值对组成,和Collection完全不相干,是另一个接口 + * Hashtable:同步的、线程安全的,不能接受为null的键值,不到万不得已不要使用。 + * HashMap:非同步、线程不安全,一般不要求线程安全的情况下建议使用 + * LinkedHashMap: 是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。 + java 7 hashmap实现原理 + ![hashmap实现原理](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/hashmap1.jpeg) + java8 实现原理 + ![java8 实现原理](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/hashmap2.png) + * ConcurrentHsahMap:可以用来代替HashTable,而且比HashTable的扩展性好。 + ![ConcurrentHsahMap实现原理](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/ConcurrentHashMap.png) + * TreeMap:是一个有序的key-value集合,它是通过红黑树实现的。是SortedMap的一个实现类 + * WeakHashMap: + * IdentifyHashMap: + * 并发集合类 + * java.util.concurrent + * Executor:一个接口,其定义了一个接收Runnable对象的方法executor,其方法签名为executor(Runnable command), + * ExecutorService:是一个比Executor使用更广泛的子类接口,其提供了生命周期管理的方法,以及可跟踪一个或多个异步任务执行状况返回Future的方法 + * Future:callable实现的存在返回值的并发编程 + * CountDownLatch:可以用来在一个线程中等待多个线程完成任务的类 + * Vector +* io流 +![io详解](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/io.png) + * 根据处理数据的类型 + * 字节流:字节流因为操作的是字节,所以可以用来操作媒体文件。 + * 字符流:字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。字符流只用来处理文本数据,字节流用来处理媒体数据。 + * 根据数据流向 + * 输入流 + * 输出流 + * RandomAccessFile: + * 对象序列化 +* NIO(非阻塞IO) + * IO和NIO的区别 +![IO和NIO的区别](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/nio_and_io.png) +* AIO (异步IO) + +* 多线程 + * 多线程的实现方式 + * 继承自Thread类(不能线程共享) + * 实现Runnable接口(不可以返回值) + * 实现Callable接口(可以抛出异常、返回值) + * ThreadPoolExecutor + * ThreadPoolExecutor的策略 + * 线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务 + * 线程数量达到了corePools,则将任务移入队列等待 + * 队列已满,新建线程(非核心线程)执行任务 + * 队列已满,总线程数又达到了maximumPoolSize,就会(RejectedExecutionHandler)抛出异常 + * 常见四种线程池 + * CachedThreadPool:线程数无限制;有空闲线程则复用空闲线程,若无空闲线程则新建线程;一定程序减少频繁创建/销毁线程,减少系统开销. + * FixedThreadPool:可控制线程最大并发数(同时执行的线程数);超出的线程会在队列中等待 + * ScheduledThreadPool:支持定时及周期性任务执行。 + * SingleThreadExecutor:有且仅有一个工作线程执行任务;所有任务按照指定顺序执行,即遵循队列的入队出队规则 + * Executors + * 线程同步 + * 同步方法: + * 同步代码块:synchronized 关键字在编译之后会在同步块的前后加上monitorenter和monitorexit,在执行monitorenter时,需要获取锁,如果占用所得对象是自己则需要将锁计数器加1,monitorexit时将锁计数器减1,如果为0则释放锁 + * 关键字volatile: + * 防止指令重排 + * 编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序; + * 处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序; + * 实现可见性,不保证原子性 + * 可见性:volatile保证线程所在空间中的volatile修饰的变量的值是最新的; + * 不保证原子性:两个线程对volatile修饰的变量同时进行赋值操作,可能导致两个线程对该变量进行一次赋值。 + * Reentrantlock:可重入锁,synchronized和Reentrantlock都是重入锁,区别如下: + * synchronized: + 1. 依赖JVM实现,加入偏向锁之后性能和Reentrantlock差不多了; + 2. 使用比较方便简洁,由编译器去实现加锁和释放; + 3. 只能是非公平锁; + * Reentrantlock: + 1. 主要依赖代码控制实现,可以避免进入内核态的阻塞; + 2. 需要手动加锁和释放锁,容易由于忘记释放锁导致死锁; + 3. 既可以是公平锁也可以是非公平锁; + 4. 提供Condition类,可以分组唤醒线程; + 5. 能够中断等待线程; + * 使用局部变量实现线程的同步,如:ThreadLocal。 + * 相关名词 + * 对象锁、互斥锁、共享锁、公平锁、非公平锁([公平锁和非公平锁的比较](http://blog.csdn.net/fw0124/article/details/6672522))、 + * 偏向锁:它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向 + 锁的线程将永远不需要触发同步。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起, + JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。引入偏向锁是为了在无多线程竞争的情况下尽量 + 减少不必要的轻量级锁执行路径。 + * 原子操作、原子性、可见性 + * [悲观锁和乐观锁 ](http://www.hollischuang.com/archives/934) + * [共享锁和排他锁](http://www.hollischuang.com/archives/923) + * 线程的交互 + * notify()、 notifyAll()、wait() + +* 反射 + +## java虚拟机 +### 简述 +java虚拟机我看过周志明的《深入理解java虚拟机》和周志明等人翻译的《java虚拟机规范(java SE 8版)》 +### 结构 +* 内存管理 + * 虚拟机栈(非共享): + * 栈帧 + * 局部变量表:局部变量数组包含了方法执行过程中的所有变量,包括 this 引用、所有方法参数、其他局部变量。 + * 返回值: + * 操作数栈 + * 类当前方法的运行时常量池引用 + * java堆(共享):堆包括:新生代( Eden、Survivor(from)、Survivor(to) )、老年代。 + * 本地方法栈(非共享) + * 程序计数器(非共享) + * 方法区(共享):也可以说在堆中,方法区又叫非堆,用来区分对内存,在hotsport虚拟机中方法区又叫做永久带.用来存放类信息,常量等和类相关的数据. + * 元空间:1.8引入的,用来替换方法区(永久代);不再虚拟机中,使用的是本地内存,取决于电脑的内存大小 +***内存结构图*** + 1.7及以前版本java内存分布图: +![jvm内存管理](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/jvm.jpg) + 1.8 内存分布图: +![jvm内存管理](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/jvm.png)
+* 对象 + * 对象的创建 + * 对象的内存布局 + * 对象头 + * MarkWord:对象的MarkWord部分占4个字节,其内容是一系列的标记位,比如轻量级锁的标记位,偏向锁标记位等等。 + * Class对象指针:其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址. + * 实例数据:存放属性信息,包括父类的信息。 + * 对齐填充(有些对象没有,具体不太懂):Java对象在内存中将以8字节对齐,也就是对象的总大小必须是8字节的整数倍。 + * 对象的访问 + * 指针方式访问(hotspot 虚拟机用的就是指针方式访问):指针访问方式访问方式比句柄方式快,节省一次指正定位带来的时间开销。 + * 句柄方式访问(其他虚拟机):句柄池中存放的是稳定的句柄,当对象被移动时,只需要改变句柄的实例数据就行,不需要改变reference本身的值。 +***普通对象的内存分布*** + ![mei对象](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/object.JPEG) +***数组对象的内存分布*** + ![mei对象](http://www.zeekling.cn/gogs/zeek/study/raw/master/java/pics/object_arr.JPEG) +* 垃圾回收 + * 判断对象已死 + * 引用计数法(无法判断循环引用的对象是否已死):每个对象都有一个引用计数器,对象每被引用一次就加1,对象被释放就减1,引用计数为0表示可以被回收。 + * 可达分析法:如果对象能够到达root,就认为对象不可回收。root对象: + * 被启动类(bootstrap加载器)加载的类和创建的对象 + * jvm运行时方法区类静态变量(static)引用的对象 + * jvm运行时方法去常量池引用的对象 + * jvm当前运行线程中的虚拟机栈变量表引用的对象 + * 本地方法栈中(jni)引用的对象 + * 垃圾收集算法 + * 标记-清除算法(老年代,标记-清理算法容易产生碎片):标记阶段标记可回收的对象,请理阶段清理被标记的对象所占用的空间 + * 复制算法(新生代,由于新生代对象存活较少,利用复制算法效率较高):按内存将容量将内存分为等大小的两块,每次只使用其中的一块,当一块的内存满了之后将存活对象复制到另一块上面去。 + * 标记-整理算法(老年代):标记阶段标记可回收的对象,整理阶段将存活的对象移动到对象的另一边,清除边界以外的对象。 + * 分代收集算法:新生代用复制算法(新生代存活的对象比较少),老年代用标记-清除和标记-整理算法 + * 垃圾收集器(共六个垃圾收集器) + * 新生代收集器(新生代收集器一般都利用复制算法) + * Serial收集器(复制算法) + * ParNew收集器(复制算法) + * Parallel Scavenge收集器(复制算法) + * 老年代收集器 + * Serial Old 收集器(标记-整理算法) + * CMS收集器(标记-清除算法): 初始标记、 并发标记、 重新标记、 并发清除 + * Parallel Old 收集器(标记-整理算法) + * G1收集器 + * 步骤 : 初始标记、 并发标记、最终标记、筛选标记 + * 特点: 并行与并发、分代收集、空间整合、可预测停顿 +* class 文件 + * class文件的结构 + * 魔数:判断class文件是否被虚拟机接受的Class文件,魔术固定值是0xCAFEBABE + * 版本号(主版本号、次版本号):主板本和副版本共同构成了Java文件的格式版本 + * 访问标志(标识一些类或者接口的访问信息):用于表示某个类或者接口的访问权限及基础属性 + * 类索引(this_class):this_class的值必须是对constant_pool表中项目的一个有效索引值,表示这个Class文件所定义的类或接口。 + * 父类索引(super_class):对于类来说,super_class的值必须为0或者是对constant_pool表中项目的一个有效索引值。 + * 接口数/接口表: + * 字段计数器:它用于表示该类或接口声明的类字段或者实例字段。 + * 常量池计数器:constant_pool_count的值等于constant_pool表中的成员数加1。 + * 常量池(主要存放两大类常量),常量池的索引范围是1至constant_pool_count−1。 + * 字面量 + * 符号引用 + * 字段表集合(含有字段访问标志) + * 方法数/方法表: + * 属性数/属性表: +* 类加载机制 + * 类加载过程 + * 加载 + * 链接 + * 验证: + * 准备:为类变量等赋初始值。如:`public static int a = 123;` 初始值为0,不是123. + * 解析:将符号引用转化为直接引用的过程。 + * 初始化 + * 使用 + * 卸载 + * 双亲委派模型 + * 启动类加载器:加载`${JAVA_HOME}/jre/lib/`下面的jar包,所有以`java.*`的class都是由启动类加载器加载的。 + * 扩展类加载器:加载`${JAVA_HOME}/jre/ext/*.jar` + * 应用程序类加载器:用户指定的类。 + * 用户自定义类加载器: + * 破坏双亲委派模型 + * 线程上下文类加载器 +* 虚拟机字节码执行引擎(这部分还没有看懂,就不具体列提纲了) + * +* 高效并发 + * 内存间的交互 + * lock(锁定):作用于主存的变量 + * unlock(解锁):作用于主存的变量 + * read(读取):作用于主存的变量 + * load(载入):作用于工作内存的变量 + * use(使用):作用于工作内存的变量 + * assign(赋值):作用于工作内存的变量 + * store(存储):作用于工作内存的变量 + * write(写入):作用于主存的变量 + +## 算法部分 +### 简述 +java部分我主要看过[《剑指offer》](http://pan.baidu.com/s/1c1ZmCww)和[《程序员面试金典》](http://www.duokan.com/book/63706)两本书。感觉两本书都挺不错的。 + +### 《 剑指offer》 + +[剑指offer面试题目](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/offer) + +### 《 程序员面试金典》 + +#### 面试考题型目录 + +* [数组与字符串](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/test/test1) +* [链表](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker/test/test2) +* [栈与队列](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [树与图](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [位操作](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [智力题](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [数学与概率](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [面向对象设计](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [递归和动态规划](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [扩展性与存储限制](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) +* [排序与查找](https://github.com/lzh984294471/job/tree/master/job/java/com/thinker) + +### 脚本 +脚本compile.sh 没有完成 diff --git a/java/javaCompile.sh b/java/javaCompile.sh new file mode 100755 index 0000000..092fa16 --- /dev/null +++ b/java/javaCompile.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +################################################# +# author:lzh # +# usage:used for compile single java file # +################################################# + +if test -z $1;then + read -p "Please input your java file name:" file +else + file=$1 +fi +while test -z ${file} +do + echo -e "\033[31mYou input nothing!!!!!!\033[037m" + read -p "Please input your java file name:" file +done +files=`find -name "${file}.java"` +echo ${files} +if test -z ${files};then + echo -e "\033[31mDo not find java file\033[37m" + exit 1 +fi +javac -g -source 1.8 -target 1.8 -d ./out/ ${files} -encoding UTF-8 && +echo -e "\033[32mCompile finish *_*\033[0m \033[37m" || +echo -e "\033[31mCompile error \033[0m \033[37m" diff --git a/java/make.sh b/java/make.sh new file mode 100755 index 0000000..f7301b7 --- /dev/null +++ b/java/make.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +#author:zeekling + +echo "compiling" +if [ ! -d target ];then + mkdir target +else + rm -rf target/* +fi +file=`find -name "*.java"` +echo "copying file" +all=`find -name "*"` + +javac -g -source 8 -target 8 -d ./target/ ${file} -encoding UTF-8 && +echo -e "\033[32mcompile finish *_*\033[0m \033[37m" || +echo -e "\033[31mcompile error \033[0m \033[37m" diff --git a/java/maven/maven.md b/java/maven/maven.md new file mode 100644 index 0000000..72bdd52 --- /dev/null +++ b/java/maven/maven.md @@ -0,0 +1,2 @@ + +gpg maven 验证 diff --git a/java/pics/ConcurrentHashMap.png b/java/pics/ConcurrentHashMap.png new file mode 100644 index 0000000..f9735de Binary files /dev/null and b/java/pics/ConcurrentHashMap.png differ diff --git a/java/pics/handler.png b/java/pics/handler.png new file mode 100644 index 0000000..8e5d69e Binary files /dev/null and b/java/pics/handler.png differ diff --git a/java/pics/hashmap1.jpeg b/java/pics/hashmap1.jpeg new file mode 100644 index 0000000..6f9f0c8 Binary files /dev/null and b/java/pics/hashmap1.jpeg differ diff --git a/java/pics/hashmap2.png b/java/pics/hashmap2.png new file mode 100644 index 0000000..0c18897 Binary files /dev/null and b/java/pics/hashmap2.png differ diff --git a/java/pics/io.png b/java/pics/io.png new file mode 100644 index 0000000..6773b21 Binary files /dev/null and b/java/pics/io.png differ diff --git a/java/pics/jvm.jpg b/java/pics/jvm.jpg new file mode 100644 index 0000000..293f515 Binary files /dev/null and b/java/pics/jvm.jpg differ diff --git a/java/pics/jvm.png b/java/pics/jvm.png new file mode 100644 index 0000000..68fb14f Binary files /dev/null and b/java/pics/jvm.png differ diff --git a/java/pics/list.png b/java/pics/list.png new file mode 100644 index 0000000..de0dd81 Binary files /dev/null and b/java/pics/list.png differ diff --git a/java/pics/nio_and_io.png b/java/pics/nio_and_io.png new file mode 100644 index 0000000..4d17a5d Binary files /dev/null and b/java/pics/nio_and_io.png differ diff --git a/java/pics/object.JPEG b/java/pics/object.JPEG new file mode 100644 index 0000000..63e73a2 Binary files /dev/null and b/java/pics/object.JPEG differ diff --git a/java/pics/object_arr.JPEG b/java/pics/object_arr.JPEG new file mode 100644 index 0000000..96d6b5e Binary files /dev/null and b/java/pics/object_arr.JPEG differ diff --git a/java/pics/reference.png b/java/pics/reference.png new file mode 100644 index 0000000..b709a1b Binary files /dev/null and b/java/pics/reference.png differ diff --git a/java/redis.md b/java/redis.md new file mode 100644 index 0000000..c569b97 --- /dev/null +++ b/java/redis.md @@ -0,0 +1,31 @@ +## redis 复习 + +### redis 特点 +1. 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1) +2. 支持丰富数据类型,支持string,list,set,sorted set,hash +3. 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行 + - Multi-开启一个事务 + - exec-负责触发并执行事务中的所有命令 +4. 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除 + +### redis 提供 6种数据淘汰策略 +- voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 +- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 +- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 +- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 +- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰 +- no-enviction(驱逐):禁止驱逐数据 + +### Redis是单进程单线程的 +redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销 + +### redis的并发竞争问题如何解决 +1. 客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。 +2. 服务器角度,利用setnx实现锁 + - setnx(lockkey, 1) 如果返回0,则说明占位失败;如果返回1,则说明占位成功 + - expire()命令对lockkey设置超时时间,为的是避免死锁问题。 + - 执行完业务代码后,可以通过delete命令删除key + +### redis常见性能问题和解决方案 + + diff --git a/java/src/Program.java b/java/src/Program.java new file mode 100644 index 0000000..7f17045 --- /dev/null +++ b/java/src/Program.java @@ -0,0 +1,80 @@ +/** + * @author 令照辉 [zeekling@163.com] + * @version 1.0 + * @apiNote + * @since 2018-06-27 + */ +public class Program { + + /** + * + * @param arr 需要排序的数组 + */ + private static void mergeSort(int[] arr) { + int[] tmp = new int[arr.length]; + internalMergeSort(arr, tmp, 0, arr.length - 1); + } + + /** + * + * @param arr 需要排序的数组 + * @param tmp 暂时存放数据 + * @param left + * @param right + */ + private static void internalMergeSort(int[] arr, int[] tmp, int left, int right) { + if (left < right) { + int middle = (left + right) / 2; + internalMergeSort(arr, tmp, left, middle); + internalMergeSort(arr, tmp, middle + 1, right); + mergeArray(arr, tmp, left, middle, right); + } + } + + /** + * + * @param arr + * @param tmp + * @param left + * @param middle + * @param right + */ + private static void mergeArray(int[] arr, int[] tmp, int left, int middle, int right) { + int i = left, j = middle + 1, k = 0; + while (i <= middle && j <= right) { + if (arr[i] <= arr[j]) { + tmp[k++] = arr[i++]; + } else { + tmp[k++] = arr[j++]; + } + } + while (i <= middle) tmp[k++] = arr[i++]; + while (j <= right) tmp[k++] = arr[j++]; + for (i = 0; i < k; i++) + arr[left + i] = tmp[i]; + } + + + /** + * 输出格式:第11大的数,除前十个大数以外的所有数字的中位数 + * @param args + */ + public static void main(String[] args) { + if (args == null || args.length <= 10) return; + int[] arr = new int[args.length]; + for (int i = 0;i toIndex) { + return -1; + } + int mid = (fromIndex + toIndex) >> 1; + if(a[mid] < key) { + return search(a, mid + 1, toIndex, key); + } else if(a[mid] > key) { + return search(a, fromIndex, mid - 1, key); + } else { + return mid; + } + } + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int key = in.nextInt(); + int len = in.nextInt(); + int[] arr = new int[len]; + for(int i=0;i= 65 && (int)tmp[i] <= 90) || + ((int)tmp[i] >= 97 && (int)tmp[i] <= 122); + } + return result; + } + + /** + * @apiNote 利用递归判断当前字母表示的数字 + * @param str char[] + * @param curr 当前位置 + * @param flag 前一个是否为double + */ + private static void result(char[] str,int curr,boolean flag){ + if(!(curr= 65 && (int)s2 <= 90)flag = 1; + if((int)s2 >= 97 && (int)s2 <= 122) flag = 2; + for(int i=0;i=0;i--){ + if(str.charAt(i) != ' ')count += 1; + else break; + } + return count; + } + + public static void main(String[] args){ + Scanner in = new Scanner(System.in); + String inStr = in.nextLine(); + System.out.println(count(inStr)); + } +} diff --git a/java/src/com/thinker/bishi/huawei/HexChange.java b/java/src/com/thinker/bishi/huawei/HexChange.java new file mode 100644 index 0000000..7a1c334 --- /dev/null +++ b/java/src/com/thinker/bishi/huawei/HexChange.java @@ -0,0 +1,47 @@ +package com.thinker.bishi.huawei; + +import java.util.Scanner; + +/** + * @author lzh + * @apiNote 华为笔试第二道题,题目记得不太清楚 + */ +public class HexChange { + private static StringBuilder result = new StringBuilder(); + private static void hexChange(int num,int hex){ + if(hex == 0) return ; + int residue = num % hex; + num = num/hex; + result.append(residue); + if(num == 0) return; + hexChange(num,hex); + } + + private static int getResult(int num,int hex){ + hexChange(num,hex); + StringBuilder tmp = new StringBuilder(); + for(int i=0;i 0 && num <= 10){ + Integer sum = 0; + int hex = 2; + while (hex<=num){ + sum += getResult(num,hex); + hex ++; + } + System.out.println(sum); + }else { + System.out.println("error"); + } + } + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int num = in.nextInt(); + result(num); + } +} diff --git a/java/src/com/thinker/bishi/nanyang/Add.java b/java/src/com/thinker/bishi/nanyang/Add.java new file mode 100644 index 0000000..f2ceb3b --- /dev/null +++ b/java/src/com/thinker/bishi/nanyang/Add.java @@ -0,0 +1,29 @@ +package com.thinker.bishi.nanyang; + +import java.util.Scanner; + +/** + * @author lzh + *

a+b=?

+ */ +public class Add { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int a = in.nextInt(),b = in.nextInt(); + System.out.println(add(a,b)); + } + + /** + * a+b=? + * @param a a + * @param b b + * @return int + */ + private static int add(int a,int b){ + int t ; + while (b != 0){ + t = a^b;b = (a&b) << 1; a = t; + } + return a; + } +} diff --git a/java/src/com/thinker/bishi/offer/CheckSameSubString.java b/java/src/com/thinker/bishi/offer/CheckSameSubString.java new file mode 100644 index 0000000..f7fa55d --- /dev/null +++ b/java/src/com/thinker/bishi/offer/CheckSameSubString.java @@ -0,0 +1,24 @@ +package com.thinker.bishi.offer; + +/** + * @author lzh + * @apiNote 判断一个字符串中是否只含有相同的子字符串(子串长度>=2) + */ +public class CheckSameSubString { + + public static boolean go(String str){ + if(null == str || str.length() <= 2) return false; + for(int i=0;i= opts.length-1) { + if(result == EqualCount.realResult) + count += 1; + return; + } + if("+".equals(sym)) + result += opts[current]; + if("-".equals(sym)) + result -= opts[current]; + go(opts, result, current+1, "+"); + go(opts, result, current+1, "-"); + } + + public static void main(String[] args) { + int opts[] = new int[]{1,2,3,4,5,6,7,8,9}; + go(opts,opts[0],1,"+"); + go(opts,opts[0],1,"-"); + System.out.println(count); + } +} diff --git a/java/src/com/thinker/bishi/offer/LargeNumPlus.java b/java/src/com/thinker/bishi/offer/LargeNumPlus.java new file mode 100644 index 0000000..405dde1 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/LargeNumPlus.java @@ -0,0 +1,36 @@ +package com.thinker.bishi.offer; + +/** + * @author lzh + * @apiNote 大数相加 + */ +public class LargeNumPlus { + + private static String plus(String s1,String s2){ + if(s1 == null || s2 == null) return "0"; + StringBuilder result = new StringBuilder(); + int carry = 0; + int tmp ; + //plus + for(int i=s1.length()-1,j=s2.length()-1;i>=0 || j>=0;i--,j--){ + tmp = 0; + if(i>=0) tmp += s1.charAt(i)-48; + if(j>=0) tmp += s2.charAt(j)-48; + tmp += carry; + carry = tmp/10; + result.append(tmp%10); + } + //旋转 + for(int i=0;i 0){ + count++; + n = (n-1) & n; + } + return count; + } + + public static void main(String[] args) { + int result = go(9); + System.out.println(result); + } +} diff --git a/java/src/com/thinker/bishi/offer/Offer_11.java b/java/src/com/thinker/bishi/offer/Offer_11.java new file mode 100755 index 0000000..79e1199 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/Offer_11.java @@ -0,0 +1,25 @@ +package com.thinker.bishi.offer; + +/** + * @author lzh + */ +public class Offer_11 { + + public static double power(int expo,double base){ + if(expo <= 0){ + return 1; + } + double result; + if((expo%2) == 0){ + result = power(expo>>1, base)*power(expo>>1, base); + }else { + result = power((expo-1)>>1, base)*power((expo-1)>>1, base)*base; + } + return result; + } + + public static void main(String[] args) { + double result = power(3,3); + System.out.println(result); + } +} diff --git a/java/src/com/thinker/bishi/offer/Offer_3.java b/java/src/com/thinker/bishi/offer/Offer_3.java new file mode 100755 index 0000000..6657798 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/Offer_3.java @@ -0,0 +1,44 @@ +package com.thinker.bishi.offer; + +/** + * 剑指offer面试题三。 + * 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成 + */ +public class Offer_3 { + + private static int[][] arr= new int[][]{ + {1,2,8,9}, + {2,4,9,12}, + {4,7,10,13}, + {6,8,11,15} + }; + private static int rows = 0; + private static int lines = 0; + + public static void init(){ + lines = arr.length; + rows = arr[0].length; + } + + + public static boolean go(int find){ + boolean flag = false; + int i = 0,j = rows-1; + while (i=0){ + if(arr[i][j]==find){ + flag = true;break; + }else if(arr[i][j] > find){ + j--; + }else if(arr[i][j] < find){ + i++; + } + } + return flag; + } + + public static void main(String[] args) { + init(); + boolean exit = go(7); + System.out.println(exit); + } +} diff --git a/java/src/com/thinker/bishi/offer/Palindrome.java b/java/src/com/thinker/bishi/offer/Palindrome.java new file mode 100644 index 0000000..66195e8 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/Palindrome.java @@ -0,0 +1,20 @@ +package com.thinker.bishi.offer; + +/** + * @author lzh + * 回文数 + */ +public class Palindrome { + + private static boolean go(int[] arr){ + if(arr == null || arr.length ==0) return false; + for(int i=0,j=arr.length-1;j>=i;i++,j--){ + if(arr[i] != arr[j]) return false; + } + return true; + } + public static void main(String[] args) { + int[] arr = new int[]{1,2,2,1}; + System.out.println(go(arr)); + } +} diff --git a/java/src/com/thinker/bishi/offer/PrintListFromTailToHead.java b/java/src/com/thinker/bishi/offer/PrintListFromTailToHead.java new file mode 100755 index 0000000..5f1cfc3 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/PrintListFromTailToHead.java @@ -0,0 +1,39 @@ +package com.thinker.bishi.offer; + +import java.util.ArrayList; +import java.util.Stack; + +class ListNode { + int val; + ListNode next = null; + ListNode(int val) { + this.val = val; + } +} +public class PrintListFromTailToHead{ + + public static ArrayList printListFromTailToHead(ListNode listNode){ + ArrayList lists = new ArrayList(); + Stack stack = new Stack(); + while(listNode != null){ + stack.push(listNode.val);listNode = listNode.next; + } + while(!stack.isEmpty()){ + lists.add(stack.pop()); + } + + return lists; + } + + public static void main(String[] args){ + ListNode root = new ListNode(1); + root.next = new ListNode(2); + root.next.next = new ListNode(3); + ArrayList result = printListFromTailToHead(root); + for(int i=0;i < result.size();i++ ){ + System.out.print(result.get(i)+"\t"); + } + System.out.println(); + } +} + diff --git a/java/src/com/thinker/bishi/offer/README.md b/java/src/com/thinker/bishi/offer/README.md new file mode 100755 index 0000000..3a4acc0 --- /dev/null +++ b/java/src/com/thinker/bishi/offer/README.md @@ -0,0 +1,23 @@ +# 剑指offer面试题目 +## 简述 +**梅花香自苦寒来,宝剑锋从磨砺出。** + +## 面试题3 + +### 题目 +在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数, +输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
+**实现方式:** [java实现](https://github.com/lzh984294471/job/tree/master/java/com/thinker/offer/Offer_3.java) + +## 面试题10 +### 题目 +请实现一个函数,输入一个整数,输出给数在二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此 +如果输入9,该函数输出2。
+**实现方式:** [java实现](https://github.com/lzh984294471/job/tree/master/java/com/thinker/offer/Offer_10.java) + +## 面试题11 +### 题目 +实现函数double power(int expo,int base),求base的expo次方,不得使用库函数,同时不需要考虑大数的问题。
+**实现方式:** [java](https://github.com/lzh984294471/job/tree/master/java/com/thinker/offer/Offer_11.java) +和[c语言实现](https://github.com/lzh984294471/job/tree/master/c/sources/offer/offer11.c) + diff --git a/java/src/com/thinker/bishi/offer/ReconstructBinaryTree.java b/java/src/com/thinker/bishi/offer/ReconstructBinaryTree.java new file mode 100755 index 0000000..e9a2afb --- /dev/null +++ b/java/src/com/thinker/bishi/offer/ReconstructBinaryTree.java @@ -0,0 +1,40 @@ +package com.thinker.bishi.offer; + + +class TreeNode{ + int val; + TreeNode left; + TreeNode right; + TreeNode(int x){ val = x;} +} + +public class ReconstructBinaryTree{ + + public static TreeNode reConstructBinaryTree(int [] pre,int [] in) { + TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1); + return root; + } + + private static TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) { + + if(startPre>endPre||startIn>endIn) + return null; + TreeNode root=new TreeNode(pre[startPre]); + + for(int i=startIn;i<=endIn;i++){ + if(in[i]==pre[startPre]){ + root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1); + root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn); + } + } + return root; + } + + public static void main(String[] args){ + int[] pre = new int[]{1,2,4,7,3,5,6,8}; + int[] in = new int[]{4,7,2,1,5,3,8,6}; + TreeNode result = reConstructBinaryTree(pre,in); + System.out.println(result); + } + +} diff --git a/java/src/com/thinker/bishi/offer/ReplaceSpace.java b/java/src/com/thinker/bishi/offer/ReplaceSpace.java new file mode 100755 index 0000000..064279e --- /dev/null +++ b/java/src/com/thinker/bishi/offer/ReplaceSpace.java @@ -0,0 +1,41 @@ +package com.thinker.bishi.offer; +public class ReplaceSpace{ + + + public static String replaceSpace(StringBuffer str){ + if(str == null) return null; + StringBuilder tmp = new StringBuilder(); + for(int i = 0;i= 0;i--){ + if(str.charAt(i) == ' ') { + chars[j] = '0';chars[j-1] = '2';chars[j-2] = '%'; j -= 3; + }else{ + chars[j] = str.charAt(i); j--; + } + } + + return new String(chars); + + } + + + public static void main(String[] args){ + StringBuffer str = new StringBuffer("We Are Happy"); + System.out.println(go(str)); + } +} diff --git a/java/src/com/thinker/bishi/other/Main.java b/java/src/com/thinker/bishi/other/Main.java new file mode 100644 index 0000000..1588c32 --- /dev/null +++ b/java/src/com/thinker/bishi/other/Main.java @@ -0,0 +1,67 @@ +package com.thinker.bishi.other; + + +import java.util.*; + +/** + * @author lzh + */ +public class Main { + private static int last = 0; + private static List tmp = new ArrayList(); + private static List result ; + private static Map tmps = new HashMap<>(); + private static int check(int sum,int[] lines,int[] init){ + boolean flag = lines[1] <= init[1] && lines[0] == last; + if(flag){ + sum += lines[2]; + last = lines[1]; + tmp.add(last); + } + return sum; + } + public static void main(String[] args) { + Scanner in =new Scanner(System.in); + String[] first = in.nextLine().split(" "); + int[] init = new int[2]; + int sum = 0; + int index = 1; + for(int i=0;i<2;i++){ + init[i] = Integer.parseInt(first[i]); + } + last = init[0]; + tmp.add(last); + while (in.hasNextLine()){ + String[] lines = in.nextLine().split(" "); + int[] linesInt = new int[3]; + for(int i=0;i<3;i++){ + linesInt[i] = Integer.parseInt(lines[i]); + } + tmps.put(index,linesInt); + index += 1; + } + int min = 0; + for(int i=0;i"); + } + } + + + } +} diff --git a/java/src/com/thinker/bishi/other/StringRotation.java b/java/src/com/thinker/bishi/other/StringRotation.java new file mode 100644 index 0000000..a4ffa5c --- /dev/null +++ b/java/src/com/thinker/bishi/other/StringRotation.java @@ -0,0 +1,37 @@ +package com.thinker.bishi.other; + +import java.util.Scanner; + +public class StringRotation{ + + public static void main(String[] args){ + Scanner in = new Scanner(System.in); + String str = in.nextLine(); + String[] strs = str.split(","); + str = strs[0].substring(1,strs[0].length()-1); + int len = Integer.parseInt(strs[1]); + int loca = Integer.parseInt(strs[2]); + StringRotation s = new StringRotation(); + System.out.println(s.rotateString(str,len,loca)); + + } + + public String rotateString(String A, int n, int p){ + char[] a = A.toCharArray(); + rotate(a,0,p); + rotate(a,p+1,n-1); + rotate(a,0,n-1); + return new String(a); + } + + public void rotate(char[] a, int begin, int end){ + while(begin <= end){ + char tmp = a[begin]; + a[begin] = a[end]; + a[end] = tmp; + begin ++; + end --; + + } + } +} diff --git a/java/src/com/thinker/bishi/other/hh b/java/src/com/thinker/bishi/other/hh new file mode 100644 index 0000000..1094845 --- /dev/null +++ b/java/src/com/thinker/bishi/other/hh @@ -0,0 +1,48 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +/** + * @author lzh + */ +public class Main { + private static int last = 0; + private static List tmp = new ArrayList(); + private static int check(int sum,int[] lines,int[] init){ + boolean flag = lines[1] <= init[1] && lines[0] == last; + if(flag){ + sum += lines[2]; + last = lines[1]; + tmp.add(last); + } + return sum; + } + public static void main(String[] args) { + Scanner in =new Scanner(System.in); + String[] first = in.nextLine().split(" "); + int[] init = new int[2]; + int sum = 0; + for(int i=0;i<2;i++){ + init[i] = Integer.parseInt(first[i]); + } + last = init[0]; + tmp.add(last); + while (in.hasNextLine()){ + String[] lines = in.nextLine().split(" "); + int[] linesInt = new int[3]; + for(int i=0;i<3;i++){ + linesInt[i] = Integer.parseInt(lines[i]); + } + sum = check(sum,linesInt,init); + } + for(int i=0;i"); + } + } + + + } +} diff --git a/java/src/com/thinker/bishi/package-info.java b/java/src/com/thinker/bishi/package-info.java new file mode 100644 index 0000000..a89ae29 --- /dev/null +++ b/java/src/com/thinker/bishi/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

面试题练习

+ */ +package com.thinker.bishi; \ No newline at end of file diff --git a/java/src/com/thinker/bishi/quNaEr/Main.java b/java/src/com/thinker/bishi/quNaEr/Main.java new file mode 100644 index 0000000..a7d5c19 --- /dev/null +++ b/java/src/com/thinker/bishi/quNaEr/Main.java @@ -0,0 +1,39 @@ +package com.thinker.bishi.quNaEr; + + +import java.util.Arrays; +import java.util.Scanner; + +/** + * @author lzh + */ +public class Main { + + private static int main(int arr[], int sum) { + int count = 0; + if (arr[0] > sum) { + return -1; + } + for (int i = arr.length - 1; i >= 0; i--) { + if(arr[i] <= sum){ + sum -= arr[i]; + if (sum >= 0) { + count++; + } + else + break; + } + } + return count; + } + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + String[] tmp = sc.nextLine().split(" "); + int[] arr = new int[tmp.length - 1]; + int sum = Integer.parseInt(tmp[tmp.length - 1]); + for (int i = 0; i < arr.length; i++) arr[i] = Integer.parseInt(tmp[i]); + Arrays.sort(arr); + System.out.println(main(arr, sum)); + } +} diff --git a/java/src/com/thinker/bishi/saima/DiffDate.java b/java/src/com/thinker/bishi/saima/DiffDate.java new file mode 100644 index 0000000..33cc8ea --- /dev/null +++ b/java/src/com/thinker/bishi/saima/DiffDate.java @@ -0,0 +1,28 @@ +package com.thinker.bishi.saima; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Scanner; + +/** + * @author lzh + *

+ * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1649&konwledgeId=134 + *

+ */ +public class DiffDate { + + + public static void main(String[] args) throws Exception { + + Scanner sc = new Scanner(System.in); + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式 + Date date = df.parse(sc.nextLine()); + Date now = df.parse("2015-10-18"); + long l = date.getTime() - now.getTime(); + long day = l / (24 * 60 * 60 * 1000); + System.out.println(day); + } + + +} diff --git a/java/src/com/thinker/bishi/saima/JiGuChuanHua.java b/java/src/com/thinker/bishi/saima/JiGuChuanHua.java new file mode 100644 index 0000000..eba6ed8 --- /dev/null +++ b/java/src/com/thinker/bishi/saima/JiGuChuanHua.java @@ -0,0 +1,22 @@ +package com.thinker.bishi.saima; + +import java.util.Scanner; + +/** + * @author lzh + */ +public class JiGuChuanHua { + private static int count = 0; + private static void chuanHua(int curr){ + + } + private static void main(){ + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + int m = in.nextInt(); + + } + public static void main(String[] args) { + main(); + } +} diff --git a/java/src/com/thinker/bishi/saima/OverTurnArray.java b/java/src/com/thinker/bishi/saima/OverTurnArray.java new file mode 100644 index 0000000..cfae497 --- /dev/null +++ b/java/src/com/thinker/bishi/saima/OverTurnArray.java @@ -0,0 +1,53 @@ +package com.thinker.bishi.saima; + +import java.util.Scanner; + +/** + * @author lzh + *

+ * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1656&konwledgeId=134 + *

+ */ +public class OverTurnArray { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int len = in.nextInt(); + int[] arr = new int[len]; + for(int i=0;i arr[i+1]){ + begin = i;flag = true; + }else if(flag && arr[i] < arr[i+1]){ + end = i;break; + } + } + while (begin < end && begin >= 0 && end <=len-1){ + int tmp = arr[begin]; + arr[begin] = arr[end]; + arr[end] = tmp; + begin ++;end--; + } + flag = true; + for(int i=0;i arr[i+1]){ + flag = false; + } + } + if(flag){ + System.out.println("yes"); + }else { + System.out.println("no"); + } + } +} + + diff --git a/java/src/com/thinker/bishi/saima/PassWord.java b/java/src/com/thinker/bishi/saima/PassWord.java new file mode 100644 index 0000000..d71765d --- /dev/null +++ b/java/src/com/thinker/bishi/saima/PassWord.java @@ -0,0 +1,45 @@ +package com.thinker.bishi.saima; + +import java.util.Scanner; + +/** + * @author lzh + * @apiNote 题目描述: + *

+ * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1667&konwledgeId=134 + *

+ * + */ +public class PassWord { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int l = in.nextInt(); + int r = in.nextInt(); + int m = in.nextInt(); + if(l>r){ + System.out.println(-1); + return; + } + int count = 0; + for(int i=l;i<=r;i++){ + if(check(i,m)) count ++; + } + if(count == 0){ + System.out.println(-1); + }else { + System.out.println(count); + } + + } + + private static boolean check(int n,int m){ + while(n != 0){ + if((n&1) == 1) m--; + n = n >> 1; + } + if(m == 0){ + return true; + } + return false; + } +} diff --git a/java/src/com/thinker/bishi/saima/Stairs.java b/java/src/com/thinker/bishi/saima/Stairs.java new file mode 100644 index 0000000..a4996e3 --- /dev/null +++ b/java/src/com/thinker/bishi/saima/Stairs.java @@ -0,0 +1,41 @@ +package com.thinker.bishi.saima; + +import java.util.Scanner; + +/** + * @author lzh + *

+ * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1668&konwledgeId=134 + *

+ */ +public class Stairs { + private static int count = 0; + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + if(n <= 0) return; + for(int i=0;i + * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1500&konwledgeId=134 + *

+ * + */ +public class StreetLamp { + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int num = in.nextInt(); + int len = in.nextInt(); + int[] lamp = new int[num]; + for(int i=0;i max){ + max = diff; + } + } + double left = lamp[0]; + double right = len - lamp[num-1]; + if(left>right && left>max/2) System.out.printf("%.2f",left); + if(right>left && right>max/2) System.out.printf("%.2f",right); + else System.out.printf("%.2f",max/2); + } +} diff --git a/java/src/com/thinker/bishi/saima/Test.java b/java/src/com/thinker/bishi/saima/Test.java new file mode 100644 index 0000000..ca4e610 --- /dev/null +++ b/java/src/com/thinker/bishi/saima/Test.java @@ -0,0 +1,24 @@ +package com.thinker.bishi.saima; + +/** + * @author lzh + */ +public class Test { + + private static int count = 0; + private static void jump(int num,int jump){ + if((num - jump) > 0) count += jump; + else return; + num -= jump; + jump(num, 1); + jump(num, 2); + } + private static int jump(int num){ + jump(num ,1); + jump(num , 2); + return count; + } + public static void main(String[] args) { + System.out.println(jump(3)); + } +} diff --git a/java/src/com/thinker/bishi/saima/Test2.java b/java/src/com/thinker/bishi/saima/Test2.java new file mode 100644 index 0000000..64c0215 --- /dev/null +++ b/java/src/com/thinker/bishi/saima/Test2.java @@ -0,0 +1,49 @@ +package com.thinker.bishi.saima; + +import java.util.LinkedList; +import java.util.Scanner; + +/** + * @author lzh + */ +public class Test2 { + private LinkedList base = new LinkedList<>(); + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + String[] strings = new String[n]; + for (int i = 0; i < n; i++){ + strings[i] = in.next(); + } + + for(int i=0;i < n;i++) { + Test2 mainn = new Test2("abcdefghijkl"); + System.out.println(mainn.rankString(strings[i])); + } + + } + public Test2(String s){ + char[] chars = s.toCharArray(); + int n = chars.length; + for(int i = 0; i < n ; i++){ + base.add(chars[i]); + } + } + public int rankString(String target){ + int rank = 1; + int size = base.size(); + for(int i = 0; i + * http://exercise.acmcoder.com/online/online_judge_ques?ques_id=1677&konwledgeId=134 + *

+ * + */ +public class YueDeEr { + + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + String firstLine = in.nextLine(); + String secondLine = in.nextLine(); + firstLine = change(firstLine); + System.out.printf("%.2f%%",check(firstLine.toCharArray(),secondLine.toCharArray())); + } + + private static double check(char[] firstLine,char[] secondLine){ + double result = firstLine.length; + int count = 0; + for(int i=0;i=48 && tmp <= 57) || (tmp >=65 && tmp <= 90) || (tmp >=97 && tmp <= 122)){ + tmps[i] = (char)(1+48); + }else { + tmps[i] = (char)(48); + } + } + return new String(tmps); + } + +} diff --git a/java/src/com/thinker/bishi/toutiao/Main1.java b/java/src/com/thinker/bishi/toutiao/Main1.java new file mode 100644 index 0000000..710c984 --- /dev/null +++ b/java/src/com/thinker/bishi/toutiao/Main1.java @@ -0,0 +1,31 @@ +package com.thinker.bishi.toutiao; + +import java.util.Scanner; + +/** + * @author lzh + */ +public class Main1 { + + private static int[] changeToArray(String[] strArray, int len) { + int[] arr = new int[len]; + for (int i = 0; i < len; i++) { + arr[i] = Integer.parseInt(strArray[i]); + } + return arr; + } + + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + int len = Integer.parseInt(in.nextLine()); + String[] strArr = in.nextLine().split(" "); + int[] arr = changeToArray(strArr,len); + int count = 0; + for(int i=0;i m) count ++; + } + } + System.out.println(count); + } + public static void main(String[] args) { + Main2 main2 = new Main2(); + main2.main(); + } +} diff --git a/java/src/com/thinker/bishi/toutiao/Main3.java b/java/src/com/thinker/bishi/toutiao/Main3.java new file mode 100644 index 0000000..1376269 --- /dev/null +++ b/java/src/com/thinker/bishi/toutiao/Main3.java @@ -0,0 +1,27 @@ +package com.thinker.bishi.toutiao; + + +import java.util.Scanner; + +public class Main3 { + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int max = sc.nextInt(); + int k = sc.nextInt(); + int i=1,j=0,count = 0,result = 0,curr=i; + int tmp = 0; + while (count=k) break; + } + while (i*10>(j*10+i) && (j*10+i-1)<=max){ + result = j*10+i-1;j++;count++; + if(count>=k) break; + } + if(i*10>max && (j*10-curr) > max){curr ++;} + if(i*10>max || (j*10+curr)>max){j=0;curr = i;} + } + System.out.println(result); + } +} diff --git a/java/src/com/thinker/bishi/works/Main2.java b/java/src/com/thinker/bishi/works/Main2.java new file mode 100644 index 0000000..3a25f5f --- /dev/null +++ b/java/src/com/thinker/bishi/works/Main2.java @@ -0,0 +1,10 @@ +package com.thinker.bishi.works; + +/** + * @author lzh + */ +public class Main2 { + public static void main(String[] args) { + + } +} diff --git a/java/src/com/thinker/bishi/xiaomi/Binary.java b/java/src/com/thinker/bishi/xiaomi/Binary.java new file mode 100644 index 0000000..5810b41 --- /dev/null +++ b/java/src/com/thinker/bishi/xiaomi/Binary.java @@ -0,0 +1,38 @@ +package com.thinker.bishi.xiaomi; + +/** + * @author lzh + */ +public class Binary { + public int countBitDiff(int m, int n) { + int count = 0; + int len = 32; + while (len >= 0){ + if((1 & n) != (1 & m)) count ++; + n >>= 1;m >>= 1;len --; + } + return count; + } + public char findFirstRepeat(String A, int n) { + // write code here + char result = ' '; + boolean flag = false; + for(int i=0;i 0){ + String tmp = in.nextLine(); + while (tmp != null){ + for(int i=0;i=0;i--){ + System.out.print(strIn[i]+" "); + } + + } +} diff --git a/java/src/com/thinker/bishi/xiaomi/NiuShi.java b/java/src/com/thinker/bishi/xiaomi/NiuShi.java new file mode 100644 index 0000000..98a7c7f --- /dev/null +++ b/java/src/com/thinker/bishi/xiaomi/NiuShi.java @@ -0,0 +1,31 @@ +package com.thinker.bishi.xiaomi; + +import java.util.Scanner; + +public class NiuShi{ + + private static int in = 2; + private static int out = 1; + public static void main(String[] args){ + Scanner ins = new Scanner(System.in); + String str = ins.nextLine(); + String[] strs = str.split(","); + int[] prices = new int[strs.length]; + for(int i=0;i loadClass(String name) throws ClassNotFoundException { + return loadClass(name,false); + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if(null != super.findLoadedClass(name)) reload(name, resolve); + Class clazz = super.findClass(name); + if(resolve) super.resolveClass(clazz); + return clazz; + } + + public Class reload(String name ,boolean resolve) throws ClassNotFoundException{ + return new HotSwapClassLoader(super.getURLs(), super.getParent()).loadClass(name, resolve); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + return super.findClass(name); + } +} diff --git a/java/src/com/thinker/common/jvm/README.md b/java/src/com/thinker/common/jvm/README.md new file mode 100755 index 0000000..e69de29 diff --git a/java/src/com/thinker/common/nio/NioClient.java b/java/src/com/thinker/common/nio/NioClient.java new file mode 100644 index 0000000..c6fd184 --- /dev/null +++ b/java/src/com/thinker/common/nio/NioClient.java @@ -0,0 +1,69 @@ +package com.thinker.common.nio; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.util.Iterator; + +public class NioClient{ + //通道管理器 + private Selector selector; + public NioClient init(String ip, int port) throws IOException{ + //获取socket通道 + SocketChannel channel = SocketChannel.open(); + + channel.configureBlocking(false); + //获取通道管理器 + selector = Selector.open(); + + channel.connect(new InetSocketAddress(ip, port)); + + channel.register(selector, SelectionKey.OP_CONNECT); + return this; + } + + public void listen() throws IOException{ + System.out.println("client start"); + //轮询访问selector + while(true){ + //选择注册过io的事件(第一次为SelectionKey.OP_CONNECT) + selector.select(); + Iterator ite = selector.selectedKeys().iterator(); + while(ite.hasNext()){ + SelectionKey key = ite.next(); + ite.remove(); + if(key.isConnectable()){ + SocketChannel channel = (SocketChannel)key.channel(); + if(channel.isConnectionPending()){ + channel.finishConnect(); + } + channel.configureBlocking(false); + //send message to service + channel.write(ByteBuffer.wrap(new String("send message to service").getBytes())); + channel.register(selector, SelectionKey.OP_READ); + System.out.println("client connect success"); + }else if(key.isReadable()){//read message + SocketChannel channel = (SocketChannel) key.channel(); + ByteBuffer buffer = ByteBuffer.allocate(1024); + channel.read(buffer); + byte[] data = buffer.array(); + String message = new String(data); + System.out.println("receive message size:"+buffer.position()+"\tmessage:"+message); + try{ + Thread.sleep(1000); + }catch(InterruptedException e){ + e.printStackTrace(); + break; + } + channel.write(ByteBuffer.wrap(new String("hello ,service").getBytes())); + } + } + } + } + public static void main(String[] args) throws IOException{ + new NioClient().init("127.0.0.1",1994).listen(); + } +} diff --git a/java/src/com/thinker/common/nio/NioServer.java b/java/src/com/thinker/common/nio/NioServer.java new file mode 100644 index 0000000..9780a86 --- /dev/null +++ b/java/src/com/thinker/common/nio/NioServer.java @@ -0,0 +1,85 @@ +package com.thinker.common.nio; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Iterator; + +/** + * nio nio different from bio nio + * + * */ +public class NioServer{ + + private Selector selector; + /** + * + * @param port 监听端口 + * 初始化服务器 + * + * */ + private NioServer init(int port) throws IOException{ + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); + serverSocketChannel.configureBlocking(false); + serverSocketChannel.bind(new InetSocketAddress(port)); + selector = Selector.open(); + //将通道管理器与通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件 + //只有当该事件到达时Select.select()会返回,否则一直阻塞。 + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); + return this; + } + public void listen() throws IOException{ + System.out.println("service starting....."); + while(true){ + //当有注册事件到达时方法返回,否则阻塞 + selector.select(); + //获取selector中的迭代器,选中项为注册的事件 + Iterator ite = selector.selectedKeys().iterator(); + while(ite.hasNext()){ + SelectionKey key = ite.next(); + //删除已选key,防止重复处理 + ite.remove(); + //客户端连接事件 + if(key.isAcceptable()){ + ServerSocketChannel server = (ServerSocketChannel)key.channel(); + //获取客户端连接通道 + SocketChannel channel = server.accept(); + channel.configureBlocking(false); + channel.write(ByteBuffer.wrap(new String("send to client").getBytes())); + channel.register(selector, SelectionKey.OP_READ); + System.out.println("client connect"); + }else if(key.isReadable()){//有可读数据事件 + //获取客户端传输数据可读消息通道。 + SocketChannel channel = (SocketChannel)key.channel(); + //创建读取数据缓存器 + ByteBuffer buffer = ByteBuffer.allocate(1024); + int read = channel.read(buffer); + byte[] data = buffer.array(); + String message = new String(data); + + System.out.println("receive message from client, size:"+buffer.position()+"\tmessage:"+message); + try{ + Thread.sleep(1000); + }catch(InterruptedException e){ + e.printStackTrace(); + break; + } + ByteBuffer out = ByteBuffer.wrap(new String("hello world").getBytes()); + channel.write(out); + } + } + } + } + public static void main(String[] args) { + try{ + new NioServer().init(1994).listen(); + }catch(IOException e){ + e.printStackTrace(); + System.exit(0); + } + } +} diff --git a/java/src/com/thinker/common/package-info.java b/java/src/com/thinker/common/package-info.java new file mode 100644 index 0000000..b6e3bb7 --- /dev/null +++ b/java/src/com/thinker/common/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

简单的Java demo

+ */ +package com.thinker.common; \ No newline at end of file diff --git a/java/src/com/thinker/common/proxy/Father.java b/java/src/com/thinker/common/proxy/Father.java new file mode 100755 index 0000000..557e55c --- /dev/null +++ b/java/src/com/thinker/common/proxy/Father.java @@ -0,0 +1,8 @@ +package com.thinker.common.proxy; + +/** + * Created by lzh on 8/3/16. + */ +public interface Father { + void say(); +} diff --git a/java/src/com/thinker/common/proxy/FatherImpl.java b/java/src/com/thinker/common/proxy/FatherImpl.java new file mode 100755 index 0000000..2b10d48 --- /dev/null +++ b/java/src/com/thinker/common/proxy/FatherImpl.java @@ -0,0 +1,13 @@ +package com.thinker.common.proxy; + +/** + * Created by lzh on 8/3/16. + * 实现类 + * + */ +public class FatherImpl implements Father{ + @Override + public void say() { + System.out.println("Hello world"); + } +} diff --git a/java/src/com/thinker/common/proxy/Handler.java b/java/src/com/thinker/common/proxy/Handler.java new file mode 100755 index 0000000..0d3e65f --- /dev/null +++ b/java/src/com/thinker/common/proxy/Handler.java @@ -0,0 +1,29 @@ +package com.thinker.common.proxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * Created by lzh on 8/3/16. + * 利用反射调用实现类的方法,实现动态代理。 + * + */ +public class Handler implements InvocationHandler { + private Class t; + public Handler(Class t){ + this.t = t; + } + private void before(){ + System.out.println("before"); + } + private void after(){ + System.out.println("after"); + } + @Override + public Object invoke(Object obj, Method method, Object[] args) throws Throwable { + this.before(); + Object object = method.invoke(t.newInstance(),args); + this.after(); + return object; + } +} diff --git a/java/src/com/thinker/common/proxy/TestDynamicProxy.java b/java/src/com/thinker/common/proxy/TestDynamicProxy.java new file mode 100755 index 0000000..97b5515 --- /dev/null +++ b/java/src/com/thinker/common/proxy/TestDynamicProxy.java @@ -0,0 +1,28 @@ +package com.thinker.common.proxy; + +import java.lang.reflect.Proxy; + +/** + * Created by lzh on 8/3/16. + * 练习动态代理的使用 + * + */ +public class TestDynamicProxy { + + private static void dynamicProxy() throws IllegalAccessException, InstantiationException { + Handler log = new Handler<>(FatherImpl.class); + Father proxy = (Father) Proxy.newProxyInstance(Father.class.getClassLoader(), + FatherImpl.class.getInterfaces(),log); + proxy.say(); + } + + public static void main(String[] args) { + try { + dynamicProxy(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } + } +} diff --git a/java/src/com/thinker/common/test/Test.java b/java/src/com/thinker/common/test/Test.java new file mode 100755 index 0000000..a5bdf9f --- /dev/null +++ b/java/src/com/thinker/common/test/Test.java @@ -0,0 +1,13 @@ +package com.thinker.common.test; + +import java.util.HashMap; +import java.util.Map; + +public class Test{ + + public static void main(String[] args) { + System.out.println((char) ('B'+32)+"\t"); + Map map = new HashMap<>(); + map.put("hh",""); + } +} diff --git a/java/src/com/thinker/common/test/test1/Test1.java b/java/src/com/thinker/common/test/test1/Test1.java new file mode 100755 index 0000000..9f6119e --- /dev/null +++ b/java/src/com/thinker/common/test/test1/Test1.java @@ -0,0 +1,22 @@ +package com.thinker.common.test.test1; + +/** + * Created by lzh on 8/2/16. + */ + +public class Test1 { + public static void main(String[] args) { + int x = 0; + int y = 0; + int k = 0; + for (int z = 0; z < 5; z++) { + if ((++x > 2) && (++y > 2) && (k++ > 2)) + { + x++; + ++y; + k++; + } + } + System.out.println(x + "" +y + "" +k); + } +} diff --git a/java/src/com/thinker/common/test/test5/Test_5_2.java b/java/src/com/thinker/common/test/test5/Test_5_2.java new file mode 100755 index 0000000..8da9d2f --- /dev/null +++ b/java/src/com/thinker/common/test/test5/Test_5_2.java @@ -0,0 +1,45 @@ +package com.thinker.common.test.test5; + +/** + * + * 将double转化成二进制输出 + * + **/ +public class Test_5_2{ + + public static void main(String[] args){ + double target = 11.5; + String result = go(target); + System.out.println(target+":\t"+result); + System.out.println((byte)128); + } + public static String go(double num){ + double xiao = num % 1; + int zheng = (new Double(num)).intValue(); + String x = com.thinker.test.test5.Test_5_2.go(xiao); + StringBuffer result = new StringBuffer(); + result.append(zhengshu(zheng)); + result.append(x); + return result.toString(); + + } + /** + * + * 将整数转化成二进制输出 + * + **/ + public static StringBuffer zhengshu(int zheng){ + StringBuffer b = new StringBuffer(); + if(zheng > 0){ + int x = zheng % 2; + StringBuffer f = zhengshu(zheng >> 1); + b.append(f); + if(x >= 1){ + b.append(1); + }else{ + b.append(0); + } + } + return b; + } +} diff --git a/java/src/com/thinker/common/thread/ReentrantLockTest.java b/java/src/com/thinker/common/thread/ReentrantLockTest.java new file mode 100755 index 0000000..33faf9e --- /dev/null +++ b/java/src/com/thinker/common/thread/ReentrantLockTest.java @@ -0,0 +1,53 @@ +package com.thinker.common.thread; + +import java.util.concurrent.locks.ReentrantLock; + +/** + * Created by root on 7/20/16. + * 练习使用重入锁(ReentranLock) + */ +public class ReentrantLockTest { + public static class Domain { + private static int i = 0; + private static ReentrantLock lock = new ReentrantLock(false); + public static int addI() { + lock.lock(); + try { + i++; + } catch (Exception e) { + e.printStackTrace(); + } finally { + lock.unlock(); + } + return i; + } + } + + public class Thread1 extends Thread { + @Override + public void run() { + for(int i=0;i<20;i++){ + System.out.println(Thread.currentThread().getName()+"\t"+Domain.addI()); + } + } + } + + public class Thread2 extends Thread { + @Override + public void run() { + for(int i=0;i<20;i++){ + System.out.println(Thread.currentThread().getName()+"\t"+Domain.addI()); + } + } + } + + + public static void main(String[] args) { + ReentrantLockTest test = new ReentrantLockTest(); + ReentrantLockTest.Thread1 thread1 = test.new Thread1(); + Thread2 thread2 = test.new Thread2(); + thread1.start(); + thread2.start(); + } +} + diff --git a/java/src/com/thinker/common/thread/TestCountDownLatch.java b/java/src/com/thinker/common/thread/TestCountDownLatch.java new file mode 100755 index 0000000..2a541ce --- /dev/null +++ b/java/src/com/thinker/common/thread/TestCountDownLatch.java @@ -0,0 +1,80 @@ +package com.thinker.common.thread; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * 练习使用CountDownLatch。 + */ +public class TestCountDownLatch { + + private static int wait = 10; + private static boolean isGone = false; + private static int carWait = 5; + + public static void main(String[] args) throws IllegalAccessException, + InstantiationException, InterruptedException { + CountDownLatch countDownLatch = new CountDownLatch(wait); + new Thread(new GetOn(countDownLatch)).start(); + waitGetOn(countDownLatch); + go(); + } + + private static void waitGetOn(CountDownLatch countDownLatch) throws InterruptedException { + System.out.println("begin to get on"); + countDownLatch.await(carWait, TimeUnit.SECONDS); + } + + private static void go() { + System.out.println("go go"); + isGone = true; + } + + static class GetOn implements Runnable { + + private CountDownLatch countDownLatch; + + public GetOn(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + @Override + public void run() { + for (int i = 0; i < wait; i++) { + try { + if (isGone) { + System.out.println("students not go: " + countDownLatch.getCount()); + break; + } + boolean goSuccess = new Student(i + 1).geton(); + if (goSuccess) countDownLatch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (countDownLatch.getCount() != 0) { + System.out.println("students not go: " + countDownLatch.getCount()) ; + } else { + System.out.println("all is well "); + } + } + } + + static class Student { + private int num; + + public Student(int num) { + this.num = num; + } + + public boolean geton() throws InterruptedException { + Thread.currentThread().sleep(new Random().nextInt(2) * 1000); + if (isGone) { + return false; + } + System.out.println("student " + num + " get on"); + return true; + } + } +} diff --git a/java/src/com/thinker/common/thread/Volatile.java b/java/src/com/thinker/common/thread/Volatile.java new file mode 100644 index 0000000..745c11e --- /dev/null +++ b/java/src/com/thinker/common/thread/Volatile.java @@ -0,0 +1,26 @@ +package com.thinker.common.thread; + + +public class Volatile{ + + public static volatile int count = 0; + + public void increase(){ + count ++; + } + + public static void main(String[] args) { + final Volatile test = new Volatile(); + for (int i = 0;i < 10;i++){ + new Thread(() -> { + for (int j = 0;j < 1000;j++){ + test.increase(); + } + }).start(); + } + while (Thread.activeCount() > 1){ + Thread.yield(); + } + System.out.println(count); + } +} diff --git a/java/src/com/thinker/common/thread/lock/spinLock/SpinLock.java b/java/src/com/thinker/common/thread/lock/spinLock/SpinLock.java new file mode 100644 index 0000000..f8edae1 --- /dev/null +++ b/java/src/com/thinker/common/thread/lock/spinLock/SpinLock.java @@ -0,0 +1,35 @@ +package com.thinker.common.thread.lock.spinLock; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author lzh + * 自己写的自旋锁,可重入。 + * + * */ +public class SpinLock{ + + AtomicReference own = new AtomicReference(); + private int count = 0; + + public void lock(){ + Thread curr = Thread.currentThread(); + if(curr == own.get()){ + count ++; return; + } + while(!own.compareAndSet(null,curr)){ + System.out.println(curr.getName()); + } + } + + public void unlock(){ + Thread curr = Thread.currentThread(); + if(curr == own.get()){ + if(count > 0) + count -- ; + else + own.compareAndSet(curr,null); + } + } + +} diff --git a/java/src/com/thinker/common/thread/lock/spinLock/TestSpinLock.java b/java/src/com/thinker/common/thread/lock/spinLock/TestSpinLock.java new file mode 100644 index 0000000..b0cc37e --- /dev/null +++ b/java/src/com/thinker/common/thread/lock/spinLock/TestSpinLock.java @@ -0,0 +1,40 @@ +package com.thinker.common.thread.lock.spinLock; + +public class TestSpinLock implements Runnable{ + + + static int num; + private SpinLock lock; + + public TestSpinLock(SpinLock lock){ + this.lock = lock; + } + public SpinLock getLock(){ + return lock; + } + + @Override + public void run(){ + this.lock.lock(); + this.lock.lock(); + num ++; + this.lock.unlock(); + this.lock.unlock(); + } + public static void main(String[] args) { + SpinLock lock = new SpinLock(); + for(int i=0;i<10;i++){ + TestSpinLock test = new TestSpinLock(lock); + new Thread(test).start(); + } + try{ + Thread.currentThread().sleep(1000); + }catch(InterruptedException e){ + e.printStackTrace(); + }finally{ + System.out.println(num); + } + + } + +} diff --git a/java/src/com/thinker/common/thread/threadPool/TestCyclicBarrier.java b/java/src/com/thinker/common/thread/threadPool/TestCyclicBarrier.java new file mode 100755 index 0000000..6592f90 --- /dev/null +++ b/java/src/com/thinker/common/thread/threadPool/TestCyclicBarrier.java @@ -0,0 +1,10 @@ +package com.thinker.common.thread.threadPool; + +/** + * Created by lzh on 8/3/16. + */ +public class TestCyclicBarrier { + public static void main(String[] args) { + + } +} diff --git a/java/src/com/thinker/common/thread/threadPool/TestThreadPoolExecutor.java b/java/src/com/thinker/common/thread/threadPool/TestThreadPoolExecutor.java new file mode 100755 index 0000000..ef9373c --- /dev/null +++ b/java/src/com/thinker/common/thread/threadPool/TestThreadPoolExecutor.java @@ -0,0 +1,45 @@ +package com.thinker.common.thread.threadPool; + +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * @author lzh + * 主要是练习线程池ThreadPoolExecutor的使用 + * + **/ +public class TestThreadPoolExecutor{ + + private static final List l = new LinkedList(); + private static final int count = 10000; + private static void go(){ + long startTime = System.currentTimeMillis(); + ThreadPoolExecutor pool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue(count)); + final Random random = new Random(); + for(int i=0;i m) { + sum = arr[i];count ++; + }else{ + sum += arr[i]; + } + } + count ++; + System.out.println(count); + + } +} diff --git a/java/src/com/thinker/suanfa/dongtai/Dijkstra.java b/java/src/com/thinker/suanfa/dongtai/Dijkstra.java new file mode 100644 index 0000000..cdb2a75 --- /dev/null +++ b/java/src/com/thinker/suanfa/dongtai/Dijkstra.java @@ -0,0 +1,82 @@ +package com.thinker.suanfa.dongtai; + +/** + * @author lzh + */ +public class Dijkstra { + private final int max = Integer.MAX_VALUE; + private int[][] arr ; // 邻接矩阵 + private String[] edges;//边界 + private boolean[] visited;// 访问过的节点,false表示没有访问过 + private int size; + private int v0 = 0; + + /** + * init + */ + public void init(){ + arr = new int[][]{ + {0 ,7 ,9 ,0 ,0 ,14}, + {7 ,0 ,10,15,0 ,0 }, + {9 ,10,0 ,11,0 ,2 }, + {0 ,15,11,0 ,6 ,0 }, + {0 ,0 ,0 ,6 ,0 ,9 }, + {14,0 ,2 ,0 ,9 ,0 } + }; + edges = new String[]{"a","b","c","d","e","f"}; + size = edges.length; + visited = new boolean[size]; + for(int i=0;i动态规划问题

+ */ +package com.thinker.suanfa.dongtai; \ No newline at end of file diff --git a/java/src/com/thinker/suanfa/fenzhi/package-info.java b/java/src/com/thinker/suanfa/fenzhi/package-info.java new file mode 100644 index 0000000..1b53b71 --- /dev/null +++ b/java/src/com/thinker/suanfa/fenzhi/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

分治算法及其思想

+ */ +package com.thinker.suanfa.fenzhi; \ No newline at end of file diff --git a/java/src/com/thinker/suanfa/fenzhijiexian/package-info.java b/java/src/com/thinker/suanfa/fenzhijiexian/package-info.java new file mode 100644 index 0000000..9bc1608 --- /dev/null +++ b/java/src/com/thinker/suanfa/fenzhijiexian/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

分枝界限法

+ */ +package com.thinker.suanfa.fenzhijiexian; \ No newline at end of file diff --git a/java/src/com/thinker/suanfa/huisu/package-info.java b/java/src/com/thinker/suanfa/huisu/package-info.java new file mode 100644 index 0000000..eafda67 --- /dev/null +++ b/java/src/com/thinker/suanfa/huisu/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

回溯法

+ */ +package com.thinker.suanfa.huisu; \ No newline at end of file diff --git a/java/src/com/thinker/suanfa/package-info.java b/java/src/com/thinker/suanfa/package-info.java new file mode 100644 index 0000000..db405fc --- /dev/null +++ b/java/src/com/thinker/suanfa/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

主要算法的学习

+ */ +package com.thinker.suanfa; \ No newline at end of file diff --git a/java/src/com/thinker/suanfa/sort/BubbleSort.java b/java/src/com/thinker/suanfa/sort/BubbleSort.java new file mode 100644 index 0000000..9c7de0e --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/BubbleSort.java @@ -0,0 +1,37 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 冒泡排序, 小到达 + */ +public class BubbleSort { + + + /** + * 冒泡排序, 小到达 + * + * @param arr 需要排序的数组 + */ + private static void bubbleSort(int[] arr) { + for (int i = 0; i < arr.length; i++) { + for (int j = 0; j < arr.length - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + int tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + } + } + } + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + bubbleSort(arr); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/sort/DirectSort.java b/java/src/com/thinker/suanfa/sort/DirectSort.java new file mode 100644 index 0000000..0af66de --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/DirectSort.java @@ -0,0 +1,38 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 直接插入法,从小到大排序。 + */ +public class DirectSort { + + /** + * @param arr 需要排序的数组 + */ + private static void directSort(int[] arr) { + for (int i = 1; i < arr.length; i++) { + int tmp = arr[i]; + int k = i; + for (int j = i - 1; j >= 0; j--) { + if (arr[j] > tmp) { + arr[j + 1] = arr[j]; + k = j; + } else { + break; + } + } + arr[k] = tmp; + } + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + directSort(arr); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/sort/FastSort.java b/java/src/com/thinker/suanfa/sort/FastSort.java new file mode 100644 index 0000000..6ef031e --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/FastSort.java @@ -0,0 +1,52 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 快速排序,小到大 + */ +public class FastSort { + + /** + * @param arr arr + * @param low low + * @param high high + * @return int + * @apiNote get the location of arr[low] after sorted + */ + private static int getMiddle(int[] arr, int low, int high) { + int tmp = arr[low]; + while (low < high) { + while (low < high && arr[high] >= tmp) { + high--; + } + arr[low] = arr[high]; + while (low < high && arr[low] <= tmp) { + low++; + } + arr[high] = arr[low]; + } + arr[low] = tmp; + return low; + } + + private static void fastSort(int[] arr, int low, int high) { + + if (low < high) { + int middle = getMiddle(arr, low, high); + fastSort(arr, low, middle - 1); + fastSort(arr, middle + 1, high); + } + + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + fastSort(arr, 0, arr.length - 1); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/sort/HeapSort.java b/java/src/com/thinker/suanfa/sort/HeapSort.java new file mode 100644 index 0000000..0386a88 --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/HeapSort.java @@ -0,0 +1,50 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 堆排序,从小到大,建立最大堆 + */ +public class HeapSort { + + private static void swap(int[] arr, int i, int j) { + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + private static void maxHeap(int[] arr, int size, int index) { + int left = 2 * index + 1, right = 2 * index + 2; + int max = index; + if (left < size && arr[left] > arr[max]) max = left; + if (right < size && arr[right] > arr[max]) max = right; + if (max != index) { + swap(arr, max, index); + maxHeap(arr, size, max); + } + } + + private static void buildHeap(int[] arr) { + for (int i = arr.length / 2; i >= 0; i--) { + maxHeap(arr, arr.length, i); + } + } + + private static void heapSort(int[] arr) { + buildHeap(arr); + for (int i = arr.length - 1; i >= 1; i--) { + swap(arr, 0, i); + maxHeap(arr, i, 0); + } + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + heapSort(arr); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/sort/MergeSort.java b/java/src/com/thinker/suanfa/sort/MergeSort.java new file mode 100644 index 0000000..e171539 --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/MergeSort.java @@ -0,0 +1,67 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * 并归排序 + **/ +public class MergeSort { + + /** + * + * @param arr + */ + private static void mergeSort(int[] arr) { + int[] tmp = new int[arr.length]; + internalMergeSort(arr, tmp, 0, arr.length - 1); + } + + /** + * + * @param arr + * @param tmp + * @param left + * @param right + */ + private static void internalMergeSort(int[] arr, int[] tmp, int left, int right) { + if (left < right) { + int middle = (left + right) / 2; + internalMergeSort(arr, tmp, left, middle); + internalMergeSort(arr, tmp, middle + 1, right); + mergeArray(arr, tmp, left, middle, right); + } + } + + /** + * + * @param arr + * @param tmp + * @param left + * @param middle + * @param right + */ + private static void mergeArray(int[] arr, int[] tmp, int left, int middle, int right) { + int i = left, j = middle + 1, k = 0; + while (i <= middle && j <= right) { + if (arr[i] <= arr[j]) { + tmp[k++] = arr[i++]; + } else { + tmp[k++] = arr[j++]; + } + } + while (i <= middle) tmp[k++] = arr[i++]; + while (j <= right) tmp[k++] = arr[j++]; + for (i = 0; i < k; i++) + arr[left + i] = tmp[i]; + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + mergeSort(arr); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/sort/SelectSort.java b/java/src/com/thinker/suanfa/sort/SelectSort.java new file mode 100644 index 0000000..a3d655e --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/SelectSort.java @@ -0,0 +1,35 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 选择排序,从小到大 + */ +public class SelectSort { + + /** + * @param arr 需要排序的数组 + */ + private static void selectSort(int[] arr) { + for (int i = arr.length - 1; i >= 0; i--) { + int k = 0; + for (int j = 1; j <= i; j++) { + if (arr[k] < arr[j]) { + k = j; + } + } + if (k != i){ + int tmp = arr[k]; + arr[k] = arr[i]; + arr[i] = tmp; + } + } + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + selectSort(arr); + for (int i : arr) { + System.out.print(i + "\t"); + } + } +} diff --git a/java/src/com/thinker/suanfa/sort/ShellSort.java b/java/src/com/thinker/suanfa/sort/ShellSort.java new file mode 100644 index 0000000..830b4c9 --- /dev/null +++ b/java/src/com/thinker/suanfa/sort/ShellSort.java @@ -0,0 +1,37 @@ +package com.thinker.suanfa.sort; + +/** + * @author lzh + * @apiNote 希尔排序,从小到大 + */ +public class ShellSort { + + private static void shellSort(int[] arr, int step) { + for (; step > 0; step /= 2) { + for (int i = step; i < arr.length; i += step) { + int tmp = arr[i]; + int k = i; + for (int j = i - step; j >= 0; j -= step) { + if (arr[j] > tmp) { + arr[j + step] = arr[j]; + k = j; + } else { + break; + } + } + arr[k] = tmp; + } + } + } + + public static void main(String[] args) { + int[] arr = new int[]{4, 2, 6, 8, 9, 3, 1, 5}; + long begin = System.nanoTime(); + shellSort(arr, arr.length); + long end = System.nanoTime(); + for (int a : arr) { + System.out.print(a + "\t"); + } + System.out.println("\nrun time:" + (double) (end - begin) / 1000 + " ms"); + } +} diff --git a/java/src/com/thinker/suanfa/tanxin/package-info.java b/java/src/com/thinker/suanfa/tanxin/package-info.java new file mode 100644 index 0000000..ef9d4e1 --- /dev/null +++ b/java/src/com/thinker/suanfa/tanxin/package-info.java @@ -0,0 +1,5 @@ +/** + * @author lzh + *

贪心算法

+ */ +package com.thinker.suanfa.tanxin; \ No newline at end of file diff --git a/java/src/com/thinker/test/test1/Test_1_1.java b/java/src/com/thinker/test/test1/Test_1_1.java new file mode 100755 index 0000000..3f61400 --- /dev/null +++ b/java/src/com/thinker/test/test1/Test_1_1.java @@ -0,0 +1,42 @@ +package com.thinker.test.test1; + +/** + * 实现一个算法,确定一个字符串是否全都不同。假使不允许使用额外的数据结构,又该如何处理。 + */ +public class Test_1_1{ + + private static boolean isUnique1(String str){ + if(str.length() > 256) return false; + boolean[] bool = new boolean[256]; + for(int i=0;i 256) return false; + int check = 0; + for(int i=0;i 0){ + return false; + } + check |= (1 << tmp); + } + return true; + } + + private static boolean isUnique3(String str){ + return !str.matches(".*(.)(.*\\1.*)"); + } + public static void main(String[] args){ + System.out.println("第一种方法:"+isUnique1("dkeohsalh")); + System.out.println("第二种方法:"+isUnique2("dkeohsalh")); + System.out.println("第三种方法:"+isUnique3("dkeohsalh")); + } +} diff --git a/java/src/com/thinker/test/test1/Test_1_4.java b/java/src/com/thinker/test/test1/Test_1_4.java new file mode 100755 index 0000000..f92a767 --- /dev/null +++ b/java/src/com/thinker/test/test1/Test_1_4.java @@ -0,0 +1,42 @@ +package com.thinker.test.test1; +/** + * 编写一个方法,将字符串中的全部替换为"%20",假定该字符串尾部有足够空间存放新增字符 + * 并且知道字符串的真实长度。 + */ +public class Test_1_4{ + + private static void doSomething(){ + String str = "Mr John Smith"; + int num = 0; + char[] c = new char[str.length()]; + System.out.print("origin str:"+str+"\n"); + for(int i=0;i=0;i--){ + if(str[i] == ' '){ + tmp[newLength-1] = '0'; + tmp[newLength-2] = '2'; + tmp[newLength-3] = '%'; + newLength -= 3; + }else { + tmp[newLength - 1] = str[i]; + newLength -= 1; + } + } + return tmp; + } + + public static void main(String[] args) { + System.out.println(replace("hello world".toCharArray())); + } +} diff --git a/java/src/com/thinker/test/test1/Test_1_6.java b/java/src/com/thinker/test/test1/Test_1_6.java new file mode 100755 index 0000000..1f5547c --- /dev/null +++ b/java/src/com/thinker/test/test1/Test_1_6.java @@ -0,0 +1,46 @@ +package com.thinker.test.test1; + +public class Test_1_6{ + + + /** + * + * 题目:有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存 + * 空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度。 + * 给定一个NxN的矩阵,和矩阵的阶数N,请返回旋转后的NxN矩阵,保证N小于等于500,图像元素小于等于256 + * + **/ + public static int[][] rotate(int[][] mat,int n){ + for(int layer=0;layer row = new LinkedList(); + List line = new LinkedList(); + for(int i=0;i=arr.length){ + return null; + } + Node node = new Node(arr[i]); + Node newNode = init(i+1); + if(newNode != null){ + node.next = newNode; + } + return node; + } + public static Node find(int k){ + if(k<0) return null; + Node font = root; + Node last = root; + for(int i=0;i=1?1:0); + return result; + + } + + public static void main(String[] args){ + ListNode a = new ListNode(7); + a.next = new ListNode(1); + a.next.next = new ListNode(6); + ListNode b = new ListNode(5); + b.next = new ListNode(9); + b.next.next = new ListNode(2); + ListNode result = go(a,b,0); + System.out.println(result); + } +} diff --git a/java/src/com/thinker/test/test2/Test_2_5_2.java b/java/src/com/thinker/test/test2/Test_2_5_2.java new file mode 100755 index 0000000..4fe8cf0 --- /dev/null +++ b/java/src/com/thinker/test/test2/Test_2_5_2.java @@ -0,0 +1,60 @@ +package com.thinker.test.test2; + +import java.util.Stack; + +/** + * @author lzh + */ +public class Test_2_5_2 { + + static class ListNode{ + public ListNode(){} + public ListNode(int data){ + this.data = data; + } + ListNode next; + int data; + int sign; + } + + public static ListNode go(ListNode a, ListNode b){ + if(a == null && b == null){ + return null; + } + int sum = 0; + if(a != null){ + sum += a.data; + } + if(b != null){ + sum += b.data; + } + + ListNode result = new ListNode(); + result.next = go(a==null?null:a.next,b==null?null:b.next); + if(result.next != null){ + result.data = (sum%10+result.next.sign)%10; + if(sum/10>=1 || (sum%10==9&&result.sign==1)){ + result.sign = 1; + } + }else { + result.data = sum%10; + if(sum/10>=1){ + result.sign = 1; + } + } + return result; + + } + + public static void main(String[] args) { + Stack stack = new Stack(); + ListNode a = new ListNode(6); + a.next = new ListNode(1); + a.next.next = new ListNode(7); + ListNode b = new ListNode(2); + b.next = new ListNode(9); + b.next.next = new ListNode(5); + ListNode result = go(a,b); + System.out.println(result); + } +} diff --git a/java/src/com/thinker/test/test4/Test_4_1.java b/java/src/com/thinker/test/test4/Test_4_1.java new file mode 100755 index 0000000..8cec4e7 --- /dev/null +++ b/java/src/com/thinker/test/test4/Test_4_1.java @@ -0,0 +1,34 @@ +package com.thinker.test.test4; + +public class Test_4_1 { + + static class Tree { + Tree left; + Tree right; + int obj; + public Tree(int obj){ + this.obj = obj; + } + + } + + public static int checkHeight(Tree tree) { + if (tree == null) return 0; + int left = checkHeight(tree.left); + if (left == -1) return -1; + int right = checkHeight(tree.right); + if (right == -1) return -1; + if (Math.abs(left - right) > 1) return -1; + else return Math.max(left, right) + 1; + } + + public static void main(String[] args) { + Tree root = new Tree(1); + root.left = new Tree(3); + root.right = new Tree(4); + root.left.left = new Tree(6); + root.left.left.left = new Tree(7); + int result = checkHeight(root); + System.out.println(result); + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_1.java b/java/src/com/thinker/test/test5/Test_5_1.java new file mode 100755 index 0000000..7d7a94e --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_1.java @@ -0,0 +1,26 @@ +package com.thinker.test.test5; + +public class Test_5_1{ + + /** + * 题目: + * 给定两个32位的整数N和M以及表示比特位置的i和j。编写一个方法,将M插入N使得M从N的第 + * j位开始,到第i位结束。假定从j位到i位足以容纳M也即若M=10011,那么j和i之间至少可容 + * 纳5个位。例如,不可能出现j=3和i=2的情况,因为第3位和第二位之间放不下M。 + * + * + **/ + public static void main(String[] args){ + System.out.println(go(32,5,4,1)); + } + public static int go(int n, int m, int i, int j){ + int h = ~0; + int right = h << (j+1); + int left = (1 << i) - 1; + int mask = left | right; + int clear = n & mask; + int m_h = m << i; + int result = clear | m_h; + return result; + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_2.java b/java/src/com/thinker/test/test5/Test_5_2.java new file mode 100755 index 0000000..77fb3cc --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_2.java @@ -0,0 +1,31 @@ +package com.thinker.test.test5; + +public class Test_5_2{ + + /** + * 题目: + * 给定一个介于0和1之间的实数(如:0.27),类型位double,打印他的二进制 + * 表示。如果该数字无法精确地用32位以内的二进制表示,则打印"ERROR"。 + * + **/ + public static void main(String[] args){ + String result = go(0.5); + System.out.println(result); + } + public static String go(double num){ + if((num < 0) || (num >1) ) return "error"; + StringBuffer b = new StringBuffer(); + b.append("."); + while(num > 0){ + if(b.length() >= 32) return "error"; + num *= 2; + if(num >= 1) { + b.append("1"); + num -= 1; + }else{ + b.append("0"); + } + } + return b.toString(); + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_3.java b/java/src/com/thinker/test/test5/Test_5_3.java new file mode 100755 index 0000000..6d35d2c --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_3.java @@ -0,0 +1,16 @@ +package com.thinker.test.test5; +public class Test_5_3{ + + /** + * + * 题目: + * 给定一个正整数,找出与其二进制表示中1的个数相同,且大小最相近的 + * 那两个数(一个略大,一个略小)。 + * + **/ + public static void main(String[] args){ + + + } + +} diff --git a/java/src/com/thinker/test/test5/Test_5_4.java b/java/src/com/thinker/test/test5/Test_5_4.java new file mode 100755 index 0000000..dfda1c5 --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_4.java @@ -0,0 +1,19 @@ +package com.thinker.test.test5; +public class Test_5_4{ + + /** + * + * 题目: + * 解释代码(n & (n-1) == 0)的具体意义。 + * 答案:(n & (n-1) == 0) 成立说明n是2的某次方。 + * + **/ + public static void main(String[] args){ + for(int i=1;i<10;i++){ + System.out.println(i+":"+go(i)); + } + } + public static int go(int n){ + return (n & (n-1)); + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_5.java b/java/src/com/thinker/test/test5/Test_5_5.java new file mode 100755 index 0000000..e1db7f9 --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_5.java @@ -0,0 +1,38 @@ +package com.thinker.test.test5; + +public class Test_5_5{ + + /** + * + * 题目: + * 编写一个函数确定需要改变的几位,才能将整数A转为整数B。 + * + **/ + public static void main(String[] args){ + System.out.println("a = 2,b = 3:\t"+go(2,3)); + System.out.println(extend(3)); + } + public static int go(int a, int b){ + int count = 0; + for(int c = a^b;c != 0;c = c & (c-1)){ + count ++; + } + return count; + } + /** + * + * 判断某个整数的二进制表示中有几个1 。 + * + **/ + public static int extend(int n){ + int count = 0; + while(true){ + if(n == 0){ + break; + } + n = n & (n-1); + count ++; + } + return count; + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_6.java b/java/src/com/thinker/test/test5/Test_5_6.java new file mode 100755 index 0000000..3eaf125 --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_6.java @@ -0,0 +1,21 @@ +package com.thinker.test.test5; + +public class Test_5_6{ + + /** + * + * 题目: + * 编写程序,交换某个程序的奇数位和偶数位,使用的指令越少越好 + * (也就是说,位0与位1交换,位2与位3交换,依次类推)。 + * + **/ + public static void main(String[] args){ + int n = 33; + System.out.println(com.thinker.common.test.test5.Test_5_2.zhengshu(n).toString()); + System.out.println(n + ":\t" + go(n)); + System.out.println(com.thinker.common.test.test5.Test_5_2.zhengshu(go(n)).toString()); + } + public static int go(int n){ + return ( ((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1) ); + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_7.java b/java/src/com/thinker/test/test5/Test_5_7.java new file mode 100755 index 0000000..7bfe10b --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_7.java @@ -0,0 +1,17 @@ +package com.thinker.test.test5; + +public class Test_5_7{ + + /** + * + * 题目: + * 数组A包含0到n的所有整数,但其中缺了一个。在这个问题中,只用了一次操作无法 + * 取得数组A里某个整数的完整内容。此外,数组A的元素皆以二进制表示,唯一可用 + * 的访问操作是“从A[i]取出第i位数据”,该操作的时间复杂度为常数。请编写代码找出 + * 那个缺失的整数。你有办法在O(n)时间内完成吗? + * + **/ + public static void main(String[] args){ + + } +} diff --git a/java/src/com/thinker/test/test5/Test_5_8.java b/java/src/com/thinker/test/test5/Test_5_8.java new file mode 100755 index 0000000..aac7171 --- /dev/null +++ b/java/src/com/thinker/test/test5/Test_5_8.java @@ -0,0 +1,8 @@ +package com.thinker.test.test5; + +public class Test_5_8{ + + public static void main(String[] args){ + + } +} diff --git a/java/src/com/thinker/test/test8/Test_8_1.java b/java/src/com/thinker/test/test8/Test_8_1.java new file mode 100755 index 0000000..1df80e8 --- /dev/null +++ b/java/src/com/thinker/test/test8/Test_8_1.java @@ -0,0 +1,11 @@ +package com.thinker.test.test8; + +public class Test_8_1{ + + + + public static void main(String[] args){ + + + } +} diff --git a/java/src/com/thinker/thread/ThreadPoolTest.java b/java/src/com/thinker/thread/ThreadPoolTest.java new file mode 100644 index 0000000..2a7b3a6 --- /dev/null +++ b/java/src/com/thinker/thread/ThreadPoolTest.java @@ -0,0 +1,40 @@ +package com.thinker.thread; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPoolTest{ + + static class MyThread implements Runnable{ + + private String name; + + public MyThread(String name){ + this.name = name; + } + + @Override + public void run(){ + try{ + Thread.sleep(1000); + System.out.println(name + " finished job!"); + }catch(InterruptedException e){ + e.printStackTrace(); + } + } + } + + + public static void main(String[] args){ + BlockingQueue queue = new LinkedBlockingQueue(); + ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 5, TimeUnit.SECONDS, queue, new ThreadPoolExecutor.AbortPolicy()); + for (int i=0; i< 10; i++){ + System.out.println("当前线程池大小[" + threadPool.getPoolSize() + "],当前队列大小[" + queue.size() + "]"); + threadPool.execute(new MyThread("Thread" + i)); + } + threadPool.shutdown(); + } + +} diff --git a/java/src/用例1.txt b/java/src/用例1.txt new file mode 100644 index 0000000..70c200e --- /dev/null +++ b/java/src/用例1.txt @@ -0,0 +1 @@ +0 1 2 3 4 5 7 6 4 3 \ No newline at end of file diff --git a/java/src/用例2.txt b/java/src/用例2.txt new file mode 100644 index 0000000..09faefd --- /dev/null +++ b/java/src/用例2.txt @@ -0,0 +1 @@ +0 1 2 3 4 5 6 5 4 3 1115 5 4 -999 \ No newline at end of file diff --git a/java/src/用例3.txt b/java/src/用例3.txt new file mode 100644 index 0000000..50c2875 --- /dev/null +++ b/java/src/用例3.txt @@ -0,0 +1 @@ +0 -1 -2 -3 4 -5 -6 -5 -4 -3 -1115 -5 -4 -999 \ No newline at end of file diff --git a/java/src/用例4.txt b/java/src/用例4.txt new file mode 100644 index 0000000..0d129fa --- /dev/null +++ b/java/src/用例4.txt @@ -0,0 +1 @@ +-1 -1 -2 -3 4 -5 -6 -5 -4 -3 -1115 -5 -4 -999 \ No newline at end of file diff --git a/java/src/用例5.txt b/java/src/用例5.txt new file mode 100644 index 0000000..2cb068c --- /dev/null +++ b/java/src/用例5.txt @@ -0,0 +1 @@ +0 1 2 3 4 5 6 5 4 3 1115 5 4 -999 0 \ No newline at end of file diff --git a/linux/README.md b/linux/README.md new file mode 100644 index 0000000..9d5640b --- /dev/null +++ b/linux/README.md @@ -0,0 +1,275 @@ +## 简介 +本人之前用的是debian系列的Linux,从2017.06开始使用centos发行版的Linux,所以之后会添加一些关于centos的知识点。 + +## 基本知识 +### linux 常用的命令 +简单的就不解释了 +```sh +cd、ls、mkdir、tar、rmdir、rm、mv、cp、cat +``` +1. `ipcs` 用于显示进程间的通信设备,比如共享内存、信号量。 + +#### 管道命令 +前一个命令的结果作为后一个命令的输入到第二个命令
+注意
+1. 管道命令只处理前一个命令正确输出,不处理错误输出 +2. 管道命令右边命令,必须能够接收标准输入流命令才行。 + +#### 输出重定向 +1. `command > file` 将输出重定向到file +2. `command >> file` 讲输出以追加的方式重定向到file +3. `2 > file ,2 >> file` 将stderr重定向到file中 +4. `1 > file 1 >> file` 将stdout重定向到file中 +5. `command > file 2>&1,command >> file 2>&1` 将 stdout 和 stderr 合并后重定向到 file + +#### 输入重定向 +与输出重定向相似 + +#### /dev/null 文件 +```sh +command > /dev/null +``` +`/dev/null` 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。 +但是 `/dev/null` 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。 + +
注意
+0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。 + +#### 文件时间 +##### mtime 修改时间 +当该文件的“内容数据”更改时,就会更新这个时间。内容数据指的是文件的内容,而不是文件的属性。 + +##### ctime 状态时间 +当该文件的”状态(status)”改变时,就会更新这个时间,举例来说,更改了权限与属性,就会更新这个时间。 + +#### atime 存取时间 +当“取用文件内容”时,就会更新这个读取时间。举例来说,使用cat去读取 `~/.bashrc`,就会更新atime了。 +![看不见](http://www.zeekling.cn/gogs/zeek/study/raw/master/linux/pics/view.jpeg) +![看不见](http://www.zeekling.cn/gogs/zeek/study/raw/master/linux/pics/view2.jpeg) + +## vim 用法 + [配置方法及其详细用法](http://www.zeekling.cn/gogs/zeek/vim_config) + +## 目录结构 +```sh +/bin:常用命令 +/boot:启动程序 +/dev:设备文件 +/etc:启动,关闭,配置程序与文件 +/home:用户工作根目录 +/lib:共享连接库 +/root:超级用户的工作目录 +/sbin:系统管理员常用管理程序 +/tmp:临时文件 +/lost+found:系统出现异常时,用于保存部分资料 +/mnt:光驱,硬盘等的挂载点 +/media:光驱的自动挂载点 +/proc:操作系统的实时信息 +/sys:系统中的硬件设备信息 +/srv:服务器启动后需要的提取的信息 +/var:某些大文件的溢出区,比方说各种服务的日志文件 +/usr/bin:众多的应用程序 +/usr/sbin:超级用户的一些管理程序 +/opt:第三方软件 +``` + +## 权限管理 +```sh +➜ ~ ll +total 56K +drwxr-xr-x 2 lzh lzh 4.0K Oct 27 22:37 Desktop +drwxr-xr-x 10 lzh lzh 4.0K Jan 6 21:10 Documents +drwxr-xr-x 9 lzh lzh 4.0K Jan 8 01:30 Downloads + +文件权限 - 连接数 - 文件所有者 - 文件所属用户组 - 文件大小 - 文件最后时间 - 文件名字 +文件类型1 - 用户权限3 - 用户组权限3 - 其他用户权限3 +``` + +### 权限 +* ACL权限 + * 用户 + * 用户组 + * 默认属性 +* 特殊权限 + * SUID权限(对单个用户有效)4: 作用于可执行文件,执行者将均有改程序所有者的权限,本权限只在执行过程中有效 + * SGID权限(对用户组有效)2:可作用于可执行文件和目录 + * 对于文件夹: + 1. 使用者若对于此目录具有 r 与 x 的权限时,该使用者能够进入此目录; + 2. 使用者在此目录下的群组将会变成该目录的群组; + 3. 若使用者在此目录下具有 w 的权限(可以新建文件),则使用者所创建的新文件,该新文件的群组与此目录的群组相同。 + * 对于文件: + 1. SGID 对二进制可执行文件有效; + 2. 程式执行者对于该文件来说,需具备 x 的权限; + 3. 执行者在执行的过程中将会获得该文件群组的支援。 + * SBIT权限(只针对目录有效)1: + 1. 只针对目录有效; + 2. 设置了sbit的文件夹下,用户自己新建的文件只有root和自己能对文件进行操作。 + +## 文件系统 +* ext2,ext3.ext4 +* inode + +![inode节点示意图](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/inode1.gif) + +1. 软连接 +2. 硬链接 + +## linux 启动过程 +### 一般操作系统的启动流程 +***通电***-->***BIOS***-->***主引导记录***-->***操作系统*** + +### 加载内核 +操作系统接管硬件以后,首先读入/boot目录下的内核文件。 +***操作系统***-->***/boot***--> +如/boot文件夹下面: +```sh +➜ /boot ls +config-4.3.0-kali1-amd64 grub +initrd.img-4.6.0-kali1-amd64 System.map-4.6.0-kali1-amd64 +vmlinuz-4.6.0-kali1-amd64 config-4.6.0-kali1-amd64 +initrd.img-4.3.0-kali1-amd64 System.map-4.3.0-kali1-amd64 +vmlinuz-4.3.0-kali1-amd64 +``` +### 启动初始化进程 +内核文件加载以后,就开始运行第一个程序`/sbin/init`,他的作用是初始化系统环境。 +***操作系统***-->***/boot***-->***init进程***-->  +由于init是第一个运行的程序,他的进程编号(pid)就是1。其他所有进程都从它衍生,都是他的子进程。 + +### 确认运行等级 +许多程序需要开机启动。他们在Windows叫做服务,在Linux叫做守护进程。 +init进程的一大任务就是去运行这些开机启动的程序。但是,不同的场合需要启动不同的程序,比如:作为服务器需要启动 +Apache,其桌面就不需要。linux允许为不同的场合,分配不同的开机启动程序,这就叫做运行级别。也就是说启动的时候根 +据运行级别,确认运行那些程序。 +***操作系统***-->***/boot***-->***init进程***-->***运行级别***--> +Linux预置七种运行级别(0-6)。一般来说,0是关机,1是单一用户模式(也就是维护模式),6是重启。运行级别2-5,各个发行 +版不太一样。init进程首先读取文件/etc/inittab,他是运行级别的设置文件。但是我在我的kali linux 上面就没有看到这个 +文件不知道他去哪儿了,书上全都是骗人的。 +

运行级别

+1. init 0 关机 +2. init 1 单用户模式纯命令行界面 +3. init 2 不完全多用户模式,不含NFS模式,纯命令行 +4. init 3 完全多用户模式,服务正常开启,使我们服务器的默认运行模式 +5. init 4 未分配 +6. init 5 图形界面 +7. init 6 重启 + +### 加载开机启动程序 +***操作系统***-->***/boot***-->***init进程***-->***运行级别***-->***/etc/init.d***--> +```sh + ➜ ~ ll /etc/rc2.d + 总用量 4.0K + lrwxrwxrwx 1 root root 17 8月 13 00:09 K01apache2 -> ../init.d/apache2 + lrwxrwxrwx 1 root root 29 8月 15 01:51 K01apache-htcacheclean -> ../init.d/apache-htcacheclean + lrwxrwxrwx 1 root root 16 8月 13 00:09 K01atftpd -> ../init.d/atftpd + lrwxrwxrwx 1 root root 18 8月 13 00:09 K01beef-xss -> ../init.d/beef-xss + lrwxrwxrwx 1 root root 19 8月 13 00:09 K01bluetooth -> ../init.d/bluetooth + lrwxrwxrwx 1 root root 17 8月 13 00:09 K01couchdb -> ../init.d/couchdb +``` +这样做的好处就是如果你要手动关闭或者重启某个进程,直接到目录/etc/init.d中寻找启动脚本即可,比如,重启 +Apache服务器,就运行下面命令: + +```sh +sudo /etc/init.d/apache2 restart +``` + +### 用户登陆 +开机启动程序加载完毕以后,就要让用户登陆了。 +***操作系统***-->***/boot***-->***init进程***-->***运行级别***-->***/etc/init.d***-->***用户登录***--> +一般来说用户登陆方式有三种: +1. 命令行登陆 +2. ssh登陆 +3. 图形界面登陆 + +### 进入login shell +所谓的shell,简单说就是命令行界面,让用户直接和操作系统对话。用户登陆时打开shell,就叫做login shell 。 +***操作系统***-->***/boot***-->***init进程***-->***运行级别***-->***/etc/init.d***-->***用户登录***--> +***Login shell***--> +1. 命令行模式登陆:首先读入/etc/profile,这是对所有用户都有效的配置;然后依次寻找下面三个文件,这是针对当前用 +户的配置(我用的是zsh,所以,这些文件前两个对我没有作用) +``` +~/.bash_profile +~/.bash_login +~/.profile +``` +2. ssh登陆:与第一种情况完全相同。 +3. 图形界面登陆:只加载/etc/profile和~/.profile。也就是说,~/.bash_profile不管有没有,都不会运行。 + +### 打开non-login shell +上一步完成以后,Linux的启动过程就算结束了,用户已经命令行提示符或者图形界面了 +用户进入操作系统后常常会在打开开启一个shell。这个shell 就叫做non-login shell ,意思就是他不同于登陆时出现的那 +个shell不读取/etc/profile和.profile等配置文件。 +***操作系统***-->***/boot***-->***init进程***-->***运行级别***-->***/etc/init.d***-->***用户登录***--> +***Login shell***-->***Non-login shell*** +### 注意 +#### login shell 和no-login shell +login shell 每次打开是都要进行登录,no-login shell不用每次都登陆。 + + +### kali linux 源 +```sh +deb http://ftp.cn.debian.org/debian jessie main non-free +deb http://http.kali.org/kali kali-rolling main non-free contrib +deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib +deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib +deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib +deb http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free +deb-src http://mirrors.aliyun.com/kali-security kali-rolling/updates main contrib non-free +deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib +deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib +deb http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free +deb-src http://mirrors.ustc.edu.cn/kali-security kali-current/updates main contrib non-free +``` + +## linux 内存管理 +### Linux内存地址空间 +#### 内存地址——用户态&内核态 +* 用户态:Ring3 运行于用户态的代码则要受到处理器的诸多 +* 内核态:Ring0 在处理器的存储保护中,核心态 +* 用户态切换到内核态的 3 种方式:系统调用、异常、外设中断 +* 区别:每个进程都有完全属于自己的,独立的,不被干扰的内存空间;用户态的程序就不能随意操作内核地址空间,具 + 有一定的安全保护作用;内核态线程共享内核地址空间; +![linux](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/linux2.png) + +#### 内存地址——MMU 地址转换 +* MMU 是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件 +* 分段机制把一个逻辑地址转换为线性地址 +* 分页机制把一个线性地址转换为物理地址 +![分页](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/linux_page.png) + +#### 内存地址——分段机制 +* 段选择符 + * 为了方便快速检索段选择符,处理器提供了 6 个分段寄存器来缓存段选择符,它们是: cs,ss,ds,es,fs 和 gs + * 段的基地址(Base Address):在线性地址空间中段的起始地址 + * 段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量 +* 分段实现 + * 逻辑地址的段寄存器中的值提供段描述符,然后从段描述符中得到段基址和段界限,然后加上逻辑地址的偏移量,就得到了线性地址 + +![段](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/linux_duan.png) + +#### 内存地址——分页机制(32 位) +* 分页机制是在分段机制之后进行的,它进一步将线性地址转换为物理地址 +* 10 位页目录,10 位页表项, 12 位页偏移地址 +* 单页的大小为 4KB +![分页机制](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/linux_page32.png) + +#### 用户态地址空间 +![用户态地址空间](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/user_space.jpg) +* TEXT:代码段可执行代码、字符串字面值、只读变量 +* DATA:数据段,映射程序中已经初始化的全局变量 +* BSS 段:存放程序中未初始化的全局变量 +* HEAP:运行时的堆,在程序运行中使用 malloc 申请的内存区域 +* MMAP:共享库及匿名文件的映射区域 +* STACK:用户进程栈 + +#### 内核态地址空间 +![内核态地址空间](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/kernel_space.jpg) +* 直接映射区:线性空间中从 3G 开始最大 896M 的区间,为直接内存映射区 +* 动态内存映射区:该区域由内核函数 vmalloc 来分配 +* 永久内存映射区:该区域可访问高端内存 +* 固定映射区:该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如: ACPI_BASE 等 + +#### 进程内存空间 +* 用户进程通常情况只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址 +* 内核空间是由内核负责映射,不会跟着进程变化;内核空间地址有自己对应的页表,用户进程各自有不同额页表 +![进程内存空间](http://www.zeekling.cn/gogs/zeek/study/raw/master/pics/jingcheng.jpg) + diff --git a/linux/awk/README.md b/linux/awk/README.md new file mode 100644 index 0000000..83a1b56 --- /dev/null +++ b/linux/awk/README.md @@ -0,0 +1,10 @@ + +* 获取比较两个文件的相同行 +```sh +awk 'NR==FNR{a[$1]++} NR!=FNR{if($1 in a){print}}' text1.txt text2.txt +``` +* 打印行数大于n的内容 +```sh +awk 'NR >= n' filename +``` + diff --git a/linux/awk/awk使用.md b/linux/awk/awk使用.md new file mode 100644 index 0000000..29b235f --- /dev/null +++ b/linux/awk/awk使用.md @@ -0,0 +1,5 @@ +1. 打印行数大于n的内容 +```sh +awk 'NR >= n' filename +``` + diff --git a/linux/centos/READMD.md b/linux/centos/READMD.md new file mode 100644 index 0000000..9ba905b --- /dev/null +++ b/linux/centos/READMD.md @@ -0,0 +1,3 @@ +# centos相关 + +在使用centos的时候遇到的问题 diff --git a/linux/centos/centos问题总结.md b/linux/centos/centos问题总结.md new file mode 100644 index 0000000..c2bccf2 --- /dev/null +++ b/linux/centos/centos问题总结.md @@ -0,0 +1,23 @@ +## 简介 +总结在使用centos的过程遇到的问题 + +## unix高级编程`apue.h` 找不到问题 + +在[http://www.apuebook.com/ ](http://www.apuebook.com/)网站根据自己书的版本下载对应的源码并且解压编译 + +```sh +make +``` + +编译完成之后执行 +```sh +sudo cp ./include/apue.h /usr/local/include/ +sudo cp ./lib/libapue.a /usr/local/lib/ +``` + +### 编译出现barrier.c:.text+0x80):对‘heapsort’未定义的引用 + +在终端中下执行 +```sh +sudo yum install libbsd libbsd-devel -y +``` diff --git a/linux/centos/hack软件安装.md b/linux/centos/hack软件安装.md new file mode 100644 index 0000000..8257ce1 --- /dev/null +++ b/linux/centos/hack软件安装.md @@ -0,0 +1,91 @@ +## 简介 +本人最近学习hack相关知识,就在自己的centos上安装一些hack软件(主要是kali上面的一些软件)玩玩,玩游戏输了一天,不开心。 + +## 信息分析工具类 + +### DNS分析工具 +1. dnsenum 、dnsmap +```sh +yum install dnsenum dnsmap lbd +yum install "dns*" +``` +### IDS/IPS识别工具 + +### smb分析包含如下工具 + +``` +yum install swaks +``` + +### SSL分析 + +``` +yum install ssldump sslh sslscan sslsplit stunnel tlssled -y +``` + +### 存活主机识别包含的工具 +``` +yum install hping3 fping nmap-ncat dhcping tcping -y +``` + +### 流量分析 +``` +yum install tcpflow wireshark -y +``` + +### 情报分析 + + +### 网络 + +``` +yum install fusioninventory-agent-task-network -y +``` + +### 系统指纹识别 + +## 漏洞分析 + +### Cisco工具集 +``` +yum install "*cisco*" -y +``` + +### OpenVAS + + + +### 扫描工具集 + +``` +yum install lynis lynis +``` +### 数据库评估软件 + +``` +yum install mdbtools-gui mdbtools +``` + +### Web程序 + + + +## 社会工程学攻击 + +``` +yum update -y && yum install python-pexpect python-crypto python-openssl python-pefile +git clone https://github.com/trustedsec/social-engineer-toolkit/ set/ +cd set +python setup.py install +``` + +### nessus 安装 +去nessus官网上下载rpm包安装,安装之后的位置在`/opt/nessus/` +1. update nessus :`` + + +### w3af +去[https://github.com/andresriancho/w3af](https://github.com/andresriancho/w3af)下载w3af, +按照[http://docs.w3af.org/en/latest/](http://docs.w3af.org/en/latest/) 上的文档安装w3af + + diff --git a/linux/common/Linux 笔记.doc b/linux/common/Linux 笔记.doc new file mode 100644 index 0000000..9bdb07f Binary files /dev/null and b/linux/common/Linux 笔记.doc differ diff --git a/linux/common/linux入门.pptx b/linux/common/linux入门.pptx new file mode 100644 index 0000000..622301c Binary files /dev/null and b/linux/common/linux入门.pptx differ diff --git a/linux/commond.md b/linux/commond.md new file mode 100644 index 0000000..cdafc44 --- /dev/null +++ b/linux/commond.md @@ -0,0 +1,13 @@ +# linux常用命令 + +- sudo 免密码使用 +```sh +visudo +# 在最后面加入 +your_user_name ALL=(ALL) NOPASSWD: ALL +``` + +- 查看最近一次重启时间 +```sh +last reboot +``` diff --git a/linux/docker/test/Dockerfile b/linux/docker/test/Dockerfile new file mode 100644 index 0000000..72ac383 --- /dev/null +++ b/linux/docker/test/Dockerfile @@ -0,0 +1,4 @@ +# this is a commit +FROM ubuntu:latest +MAINTAINER zeek +CMD echo 'hello from my image from Dockerfile' diff --git a/linux/error.md b/linux/error.md new file mode 100644 index 0000000..879151a --- /dev/null +++ b/linux/error.md @@ -0,0 +1,7 @@ +# Linux常见错误解决方案 +## sudo apt install -f修复失败 +执行以下语句就可以解决: +```sh +sudo rm -rf /var/cache/apt/archives && sudo apt update && sudo apt install -f +``` + diff --git a/linux/git.md b/linux/git.md new file mode 100644 index 0000000..0f8c3a8 --- /dev/null +++ b/linux/git.md @@ -0,0 +1,29 @@ +# git使用教程 + +## 常用命令 + +- 克隆项目 +```sh +git clone git@www.zeekling.cn:deep-learn/papers.git +git clone git@www.zeekling.cn:deep-learn/papers.git location # 克隆到指定文件夹 +``` + +- 版本回退 +```sh +# 此为默认方式,不带任何参数的git reset,这种方式,它回退到某个版本,只保留源码,回退commit和index信息 +git reset -mixed head file + #回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可 +git reset -soft head file +#彻底回退到某个版本,本地的源码也会变成为上一个版本的内容 +git reset -hard head file +``` +- https保存密码 +```shell +git config --global credential.helper store +``` + +## 常见问题 +1. 添加了秘钥但是克隆项目或者提交代码的时候显示没有权限 +```shell +ssh-add ~/.ssh/github +``` diff --git a/linux/linux_c/progess/exec.c b/linux/linux_c/progess/exec.c new file mode 100644 index 0000000..bf4734f --- /dev/null +++ b/linux/linux_c/progess/exec.c @@ -0,0 +1,31 @@ +#include +#include +#include + +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: + * fork()和 execl() 联合使用 + * ===================================================================================== + */ +int main () +{ + int pid,status; + pid = fork(); + switch(pid){ + case -1: + perror("fork failed"); + exit(1); + case 0: + execl("/bin/ls","ls","-l","--color",NULL); + perror("execl failed"); + exit(1); + default: + wait(&status); + printf("ls completed\n"); + printf("status = %d\n",status); + exit(0); + } + return EXIT_SUCCESS; +} diff --git a/linux/linux_c/progess/fork.c b/linux/linux_c/progess/fork.c new file mode 100644 index 0000000..58183d5 --- /dev/null +++ b/linux/linux_c/progess/fork.c @@ -0,0 +1,18 @@ +#include +#include +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: + * ===================================================================================== + */ +int main() +{ + pid_t pid = 0; + printf("One\n"); + pid = fork(); + printf("Two\n"); + printf("pid:%d\n",pid); +// printf("%d\n",0xFF); + return 0; +} /* ---------- end of function main ---------- */ diff --git a/linux/linux_c/progess/proc_file.c b/linux/linux_c/progess/proc_file.c new file mode 100644 index 0000000..d915d1f --- /dev/null +++ b/linux/linux_c/progess/proc_file.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +/** + * 打印错误信息,并且退出 + **/ +void failed(char* s); + +/** + * 移动读取文件的位置 + * */ +void printpoc(char* string,int fildes); + +int main(void) +{ + int fd; + int pid; + char buf[10]; + if ((fd = open("test.c",O_RDONLY)) < 0) { + failed("open failed"); + } + read(fd,buf,10);/* */ + printpoc("Before fork",fd); + if ((pid = fork()) < 0) { + failed("fork failed"); + }else if(!pid){ + printpoc("child before read",fd); + read(fd,buf,10); + printpoc("child after read",fd); + }else{ + wait(NULL); + printpoc("parent after read",fd); + } + return 0; +} +void failed(char* s){ + perror(s); + exit(1); +} + +void printpoc(char * string,int fildes){ + long pos; + if ((pos = lseek(fildes,0L,1)) < 0L) { + failed("lseek failed"); + } + printf("%s:%ld\n",string,pos); +} diff --git a/linux/linux_c/progess/test.c b/linux/linux_c/progess/test.c new file mode 100644 index 0000000..6306f53 --- /dev/null +++ b/linux/linux_c/progess/test.c @@ -0,0 +1,8 @@ +#include +#include "apue.h" + +int main(void) +{ + printf("uid = %d, gid = %d\n",getuid(),getgid()); + return 0; +} diff --git a/linux/linux_c/progess/wait.c b/linux/linux_c/progess/wait.c new file mode 100644 index 0000000..68feb05 --- /dev/null +++ b/linux/linux_c/progess/wait.c @@ -0,0 +1,40 @@ + +#include +#include +#include +#include +/* + * === FUNCTION ====================================================================== + * Name: main + * Description: + * ===================================================================================== + */ +int main (void) +{ + int pid,status,exit_status; + if ((pid = fork()) < 0){ + perror("fork failed!"); + exit(1); + } + if (!pid){ + sleep(4); + exit(6); + } + /* 父进程 */ + if ((wait(&status)) < 0){ + perror("wait failed"); + exit(1); + } + /* 用来测试status的低八位是否为0 */ + if (status & 0xFF){ + printf("低八位不为0"); + }else{ + printf("status:%d\n",status); + /* 将status的高八位放置到exit_status当中 */ + exit_status = status >> 8; + exit_status &= 0xFF; + /* 用来输出子进程的结束的状态 */ + printf("exit status from %d is %d\n",pid,exit_status); + } + return EXIT_SUCCESS; +} /* ---------- end of function main ---------- */ diff --git a/linux/nginx.md b/linux/nginx.md new file mode 100644 index 0000000..ebfd217 --- /dev/null +++ b/linux/nginx.md @@ -0,0 +1,47 @@ +# 进程数 +Nginx 有 master 和 worker 两种进程,master 进程用于管理 worker 进程,worker 进程用于 Nginx 服务。 +```sh +grep -c processor /proc/cpuinfo # 查看cpu核数 +``` +根据CPU核数设置worker_processes +``` +worker_processes 4; +``` +# 绑定 Nginx 进程到不同的 CPU 上 +``` +worker_processes 2; # 2核CPU的配置 +worker_cpu_affinity 01 10; + +worker_processes 4; # 4核CPU的配置 +worker_cpu_affinity 0001 0010 0100 1000; + +worker_processes 8; # 8核CPU的配置 +worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 1000000; +``` + +# 开启高效文件传输模式 +``` +http { + include mime.types; + default_type application/octet-stream; + + sendfile on; # 开启文件的高效传输模式 + tcp_nopush on; # 激活 TCP_CORK socket 选择 + tcp_nodelay on; # 数据在传输的过程中不进缓存 +} +``` + +# gzip +``` +http { + gzip on; # 开启压缩功能 + gzip_min_length 1k; # 允许压缩的对象的最小字节 + gzip_buffers 4 32k; # 压缩缓冲区大小,表示申请4个单位为32k的内存作为压缩结果的缓存 + gzip_http_version 1.1; # 压缩版本,用于设置识别HTTP协议版本 + gzip_comp_level 9; # 压缩级别,1级压缩比最小但处理速度最快,9级压缩比最高但处理速度最慢 + gzip_types text/plain application/x-javascript text/css application/xml; # 允许压缩的媒体类型 + gzip_vary on; # 该选项可以让前端的缓存服务器缓存经过gzip压缩的页面,例如用代理服务器缓存经过Nginx压缩的数据 +} +``` + + diff --git a/linux/pics/view.jpeg b/linux/pics/view.jpeg new file mode 100644 index 0000000..a64f085 Binary files /dev/null and b/linux/pics/view.jpeg differ diff --git a/linux/pics/view2.jpeg b/linux/pics/view2.jpeg new file mode 100644 index 0000000..3280061 Binary files /dev/null and b/linux/pics/view2.jpeg differ diff --git a/linux/raspberry_pi_vultr.md b/linux/raspberry_pi_vultr.md new file mode 100644 index 0000000..b57bc0f --- /dev/null +++ b/linux/raspberry_pi_vultr.md @@ -0,0 +1,49 @@ +## How to use the vultr server to build an outline (or shadowsocks) service + +### Introduction +This tutorial is for countries with a firewall like China.And ,I hope this tutorial can help you. + +### First ,you should get a vultr serve +1. Register an account on [https://www.vultr.com ](https://www.vultr.com/?ref=7747795),enter your email address and password to + create a account. And you'll receive an email to verify Your email is ok. +![register](http://www.zeekling.cn/gogsPics/study/linux/0.png) +2. Billing. click "Billing" and select one of payment. I thinker Alipay is a great payment for chinese person. +![register](http://www.zeekling.cn/gogsPics/study/linux/1.png) +3. create VPS + 1. select Servers ,click "+" to create VPS +![register](http://www.zeekling.cn/gogsPics/study/linux/2.png) + 2. select Location + select nearest node. for example,I'm a chinese, so, I select an Japan node for me.If you want to known access to the + node you selected. You can visit + [https://www.vultr.com/faq/#downloadspeedtests ](https://www.vultr.com/faq/#downloadspeedtests) and ping the Looking + Glass + ![register](http://www.zeekling.cn/gogsPics/study/linux/3.png) + And I pinged The node in Japan.The result is showed in below figure: + ![register](http://www.zeekling.cn/gogsPics/study/linux/4.png) + 3. select server and server size, The below figure show mine selection. + ![register](http://www.zeekling.cn/gogsPics/study/linux/5.png) + 4. click "Deplay Now" + + #### Install docker and start `Jigsaw-Code/outline-server` + 1. Uninstall the old docker + ```sh + apt-get -y remove docker docker-engine docker.io + ``` + 2. Install docker + ```sh + curl -sS https://get.docker.com/ | sh + ``` + 3. Pull ourline docker image and start + ![https://since1989.org/wp-content/uploads/2018/04/outline-manager-script.png ](https://since1989.org/wp-content/uploads/2018/04/outline-manager-script.png) + command: + ```sh + wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh | bash + ``` + Copy the generated api field to the outline manager manager and click DONE to complete it. +Click 'add new key ' to generate a new key ,and click share icon to get ss account +![http://www.zeekling.cn/gogsPics/study/linux/7.png ](http://www.zeekling.cn/gogsPics/study/linux/7.png) +Then , Open the outline client, copy your ss account link, and click CONNECT to connect. +![https://since1989.org/wp-content/uploads/2018/04/outline-manager-key.png ](https://since1989.org/wp-content/uploads/2018/04/outline-manager-key.png) + +The end,Open the Chrome browser and you can access the Twitter/Youtube videos. + diff --git a/linux/sed/README.md b/linux/sed/README.md new file mode 100644 index 0000000..e69de29 diff --git a/linux/shell/README.md b/linux/shell/README.md new file mode 100644 index 0000000..79b5013 --- /dev/null +++ b/linux/shell/README.md @@ -0,0 +1,25 @@ +## 简介 + +用来存放平时用的一些`shell`脚本,用来减少不必要的麻烦,平时可以少敲一点命令行 + +## 脚本详情及其用法 + +### mygit.sh +用來將本地修改的代码全部提交到gitgub上 + +参数1表示分支,参数二表示提交时的备注 + +### sqlbackup.sh +用来备份mysql数据库的内容,缺点:一次只能备份一个数据库的数据 + +### make.sh +用来编译普通的java项目,会显示编译所用的时间。 + +### getTime.sh +用来获取时间差 + +### complie.sh +用来编译`maven` web项目,并且部署到本地的`tomcat`部署路径之下,这个脚本有一点瑕疵 + + + diff --git a/linux/shell/docker/cadvisor.sh b/linux/shell/docker/cadvisor.sh new file mode 100755 index 0000000..9079b1c --- /dev/null +++ b/linux/shell/docker/cadvisor.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +docker pull google/cadvisor +docker stop cadvisor +docker rm cadvisor +docker run -m 80m \ + --volume=/:/rootfs:ro \ + --volume=/var/run:/var/run:rw \ + --volume=/sys:/sys:ro \ + --volume=/var/lib/docker/:/var/lib/docker:ro \ + --volume=/dev/disk/:/dev/disk:ro \ + --publish=8088:8080 \ + --detach=true \ + --name=cadvisor \ + google/cadvisor diff --git a/linux/shell/docker/clean.sh b/linux/shell/docker/clean.sh new file mode 100755 index 0000000..f7126cc --- /dev/null +++ b/linux/shell/docker/clean.sh @@ -0,0 +1,8 @@ +sync +apt clean +echo 3 > /proc/sys/vm/drop_caches +echo "" > /var/log/btmp +cd /var/log/nginx && rm -rf *.gz && rm -rf *.1 +cd /var/log/ && rm -rf *.gz && rm -rf *.1 +cd /var/log && rm -rf auth.log-* + diff --git a/linux/shell/docker/gogs-restart.sh b/linux/shell/docker/gogs-restart.sh new file mode 100755 index 0000000..10984a4 --- /dev/null +++ b/linux/shell/docker/gogs-restart.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# docker pull gogs/gogs +docker stop gogs +docker rm gogs +#docker run -d --name gogs -m 500m -p 2222:22 -p 3000:3000 \ +# -v /dockerData/gogs/conf:/data/gogs/conf \ +# -v /dockerData/gogs/gogs-repositories:/home/git/gogs/gogs-repositories \ +# -v /dockerData/gogs/upload:/home/git/gogs/upload \ +# -v /dockerData/gogs/log:/home/git/gogs/log \ +# gogs/gogs +# diff --git a/linux/shell/docker/huginn-start.sh b/linux/shell/docker/huginn-start.sh new file mode 100755 index 0000000..3dab2d5 --- /dev/null +++ b/linux/shell/docker/huginn-start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# docker pull huginn/huginn +docker stop huginn +docker rm huginn +docker run --detach --name huginn --network=host -m 100m \ + -e MYSQL_PORT_3306_TCP_ADDR=127.0.0.1 \ + -e HUGINN_DATABASE_NAME=huginn \ + -e HUGINN_DATABASE_USERNAME=root \ + -e HUGINN_DATABASE_PASSWORD=94adg2011 \ + huginn/huginn diff --git a/linux/shell/docker/lute-http-start.sh b/linux/shell/docker/lute-http-start.sh new file mode 100755 index 0000000..cf966b6 --- /dev/null +++ b/linux/shell/docker/lute-http-start.sh @@ -0,0 +1,4 @@ +#!/bin/bash +docker pull b3log/lute-http +docker stop lute-http +docker run --detach --rm --network=host --name lute-http -m 80M b3log/lute-http diff --git a/linux/shell/docker/mysql.sh b/linux/shell/docker/mysql.sh new file mode 100755 index 0000000..e97b24a --- /dev/null +++ b/linux/shell/docker/mysql.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# docker pull mysql +docker stop mysql +docker rm mysql +docker run -d --name=mysql -m 300m\ + --env=MYSQL_ROOT_PASSWORD=94adg2011 \ + -p 3306:3306 \ + -v /dockerData/mysql:/var/lib/mysql \ + mysql --default-authentication-plugin=mysql_native_password diff --git a/linux/shell/docker/owncloud.sh b/linux/shell/docker/owncloud.sh new file mode 100755 index 0000000..aa0a721 --- /dev/null +++ b/linux/shell/docker/owncloud.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +docker stop owncloud +docker start owncloud +#docker rm owncloud +#docker run -d --name owncloud -m 400m \ +# -v /dockerData/owncloud:/var/www/html/data \ +# --link mysql:mysql \ +# -p 8000:80 owncloud +# diff --git a/linux/shell/docker/solo-restart.sh b/linux/shell/docker/solo-restart.sh new file mode 100755 index 0000000..c0f1d91 --- /dev/null +++ b/linux/shell/docker/solo-restart.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# +# Solo docker 更新重启脚本 +# +# 1. 请注意修改参数 +# 2. 可将该脚本加入 crontab,每日凌晨运行来实现自动更新 +# +docker pull b3log/solo +docker stop solo +docker rm solo +docker run --detach --name solo --network=host -m 500m \ + --env RUNTIME_DB="MYSQL" \ + --env JDBC_USERNAME="root" \ + --env JDBC_PASSWORD="94adg2011" \ + --env JDBC_DRIVER="com.mysql.cj.jdbc.Driver" \ + --env JDBC_URL="jdbc:mysql://127.0.0.1:3306/solo?useUnicode=yes&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC" \ + --volume /dockerData/solo/skins/solo-nexmoe:/opt/solo/skins/solo-nexmoe \ + b3log/solo --listen_port=8080 --server_scheme=https --server_host=www.zeekling.cn \ + --lute_http=http://127.0.0.1:8249 + + #b3log/solo --listen_port=8080 --server_scheme=https --server_host=www.zeekling.cn \ +##--env JDBC_URL="jdbc:mysql://172.27.0.17:3306/solo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC" \ +#docker start solo diff --git a/linux/shell/git/add-ssh-key.sh b/linux/shell/git/add-ssh-key.sh new file mode 100755 index 0000000..0aea0c7 --- /dev/null +++ b/linux/shell/git/add-ssh-key.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# 此脚本只对本人有效,带完善 +# add ssh-key + +cd ~/.ssh && +ssh-add lab +ssh-add github +ssh-add code diff --git a/linux/shell/git/mygit.sh b/linux/shell/git/mygit.sh new file mode 100755 index 0000000..b743f07 --- /dev/null +++ b/linux/shell/git/mygit.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# 本脚本用于提交所有代码到远程仓库的脚本,简化操作 +# 脚本使用: +# 1. 将脚本放到/usr/bin下面: sudo mv ./mygit.sh /usr/bin/mygit +# 2. 在当前git项目路径下执行:mygit branch(分支名称) msg(提交信息) +# author: zeekling + +BRANCH=master +if ! test -z $1;then + BRANCH=$1 +fi +# 修复以前提示信息不能传入空格的bug +shift 1 +if test -z $*;then + git add -A + git commit && + git pull origin ${BRANCH} && git push origin ${BRANCH} + exit 0 +else + git add -A + git commit -m "$*" && + git pull origin ${BRANCH} && git push origin ${BRANCH} + exit 0 +fi diff --git a/linux/shell/java/complie.sh b/linux/shell/java/complie.sh new file mode 100755 index 0000000..c79b746 --- /dev/null +++ b/linux/shell/java/complie.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +#author: lzh +echo "compiling......................" +mvn compile +if [ ! $0 ];then + echo "compile failed" + exit 1 +fi +echo "compile finish.........." +mvn package -DskipTests +if [ ! $0 ];then + echo "package failed" + exit 1 +fi +echo "package finish" +if test -z $1;then + echo "please input your project name" + exit 1 +fi +if test -z $2;then + echo "please input your tomcat home" + exit 1 +else + echo $1 + echo $2 + cp `pwd`/target/$1 $2/webapps/ + exit 0 +fi + diff --git a/linux/shell/java/make.sh b/linux/shell/java/make.sh new file mode 100755 index 0000000..9a7575b --- /dev/null +++ b/linux/shell/java/make.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +#author:lzh +# 用来编译普通的java 项目,不适合于web等项目 +function getTime() +{ + START_S=$(echo $1 | cut -d '.' -f 1) + START_NS=$(echo $1 | cut -d '.' -f 2) + END_S=$(echo $2 | cut -d '.' -f 1) + END_NS=$(echo $2 | cut -d '.' -f 2) + TIME=$[(10#$END_S - 10#$START_S) * 1000 + (10#$END_NS - 10#$START_NS) / 1000000] + echo $TIME +} + +SOURCE="1.8" +TARGET="1.8" +OUT="target" +echo -e "开始查找jar包" +LIB=`find -name "*.jar"` +echo "查找jar包结束" +if [ ! -d $OUT ];then + mkdir $OUT +else + rm -rf $OUT/* +fi +echo "开始查找java文件" +FILES=`find -name "*.java"` +ALL=`find -name "*"` +echo "查找java文件结束" +echo "开始编译java文件" +START=$(date +%s.%N) +javac -g -source $SOURCE -target $TARGET -d ./$OUT/ $FILES -encoding UTF-8 && +echo -e "\033[32m编译成功 *_* \033[37m" || +echo -e "\033[31m编译出错了 \033[0m \033[37m" +END=$(date +%s.%N) +DIFF=$(getTime $START $END) +echo -e "\033[33m编译耗时:"$DIFF"ms \033[37m" + diff --git a/linux/shell/mysql/sqlbackup.sh b/linux/shell/mysql/sqlbackup.sh new file mode 100755 index 0000000..5de1fef --- /dev/null +++ b/linux/shell/mysql/sqlbackup.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +##################################################################### +# 用来备份当前项目的数据库,以免错误操作导致数据丢失 # +# author 令照辉 # +# 写这个脚本的原因: # +# 懒得用图形化界面备份,还有就是图形化界面备份的小哥我不满意 # +# 脚本写的简单仅供自己使用 # +##################################################################### + +# 默认数据 +IP="127.0.0.1" +DATABASE="mysql" +BACKUPDIR=`pwd` + +# read ip +read -p "请输入mysql所在服务器的ip地址(默认为127.0.0.1):" inip +if test -z ${inip};then + echo "您输入的ip是 ${IP}" +else + IP=${inip} + echo "您输入的ip是 ${IP}" +fi + +# read database +read -p "请输入需要备份的数据库名称:" indatabse +if test -z ${indatabse};then + echo -e "\033[32m您没有输入数据库名称! \033[37m" + exit 1 +else + DATABASE=${indatabse} + echo "您输入的数据库名称是 ${DATABASE}" +fi + +# read back fold +read -p "请输入备份文件夹位置(当前文件夹):" inbackup +if test -z ${inbackup};then + echo "备份文件夹位置 ${BACKUPDIR}" +else + BACKUPDIR=${inbackup} + echo "您的备份文件夹位置 ${BACKUPDIR}" +fi + +if [ ! -d ${BACKUPDIR} ];then + echo "目录${BACKUPDIR} 不存在,新建${BACKUPDIR}" + mkdir ${BACKUPDIR} -p +fi + +# backup +cd ${BACKUPDIR} && echo "进入${BACKUPDIR}目录成功" || echo "进入${BACKUPDIR}目录失败" +NOW=`date +"%Y-%m-%d--%H:%M:%S"` +FILE=${NOW}.sql +mysqldump -u root -h ${IP} -p ${DATABASE} > ${FILE} && + echo "备份成功" || echo "备份失败,请重试" diff --git a/linux/shell/oracle/execOra.sh b/linux/shell/oracle/execOra.sh new file mode 100755 index 0000000..018f604 --- /dev/null +++ b/linux/shell/oracle/execOra.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# 执行ORACLE sql文件 +# sqlplus eode/foo +# export NLS_LANG="AMERICAN_AMERICA.AL32UTF8" +# 当执行脚本中有select时会在控制台打印两次结果,当在select语句前加了prompt 时会在控制台打印两次查询结果 +# 执行过程中遇到的问题: +# 1. 执行sql脚本的时候 prompt如果是以中文结尾的时候,脚本报错,造成原因是编码问题,未解决 +# 2. 在执行sql脚本中有需要输入参数时,用这个脚本执行sql时,会默认传入0,达不到效果 found:2017-12-03 +# 修改日期 修改人 修改原因 +# 20180109 zeekling 添加远程时需要打印的数据 +# 20171008 zeekling + + +USER_NAME="eoda" +PASSWD="foo@pdb" +if test -z $1; then + echo "请输入SQL文件的位置!" + exit 1 +fi + +if [ "$2" != "" ]; then + USER_NAME=$2 +fi + +if [ "$3" != "" ]; then + PASSWD=$3 +fi + +SQL_PATH=$1 +sqlplus -S "${USER_NAME}/${PASSWD}" << EOF + set long 5000 + set linesize 190 + set autotrace on + set timing on + set pagesize 9999 + set serveroutput on + column plan_plus_exp format a80 + set feedback off + set echo off + @${SQL_PATH} + exit; +EOF diff --git a/linux/shell/other/findHost.sh b/linux/shell/other/findHost.sh new file mode 100755 index 0000000..8f7de98 --- /dev/null +++ b/linux/shell/other/findHost.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# +# 此脚本用于查找可用ip + +find_ip="www.baidu.com" +ok="false" +ok_ip="127.0.0.1" +count=1 +read -p "please input ip:" find_ip +while [[ "${ok}" == "false" ]] +do + echo "开始第${count}次查找" + result=`nslookup ${find_ip} 74.82.42.42` + tmp=`echo ${result} | sed "s/: /:/g" | + awk '{split($0,arr," "); for (i = 0;i < length(arr);i++){ if(match(arr[i],"Address:") ){ if (i>4){print arr[i] } } } }' | + awk '{split($0,arr,":"); print arr[2] }'` + for arr in $tmp + do + ping=`ping -c 1 ${arr} | awk 'NR==5 {print $4}'` + echo begin${ping}end + if [ "${ping}" != "" ] + then + ok="true"; + ok_ip=${arr}; + break; + else + echo "${arr} is not available!" + fi + done + echo "第${count}次查找结束" + count=$[${count}+1] +done +echo ${find_ip},${ok_ip} diff --git a/linux/shell/other/freshHost.sh b/linux/shell/other/freshHost.sh new file mode 100755 index 0000000..8ce28ab --- /dev/null +++ b/linux/shell/other/freshHost.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env +# 用于定时刷洗新hosts文件 + diff --git a/linux/shell/other/getTime.sh b/linux/shell/other/getTime.sh new file mode 100755 index 0000000..f24e235 --- /dev/null +++ b/linux/shell/other/getTime.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# 用于获取时间差 + +function getTime() +{ + START_S=$(echo $1 | cut -d '.' -f 1) + START_NS=$(echo $1 | cut -d '.' -f 2) + END_S=$(echo $2 | cut -d '.' -f 1) + END_NS=$(echo $2 | cut -d '.' -f 2) + TIME=$[(10#$END_S - 10#$START_S) * 1000 + (10#$END_NS - 10#$START_NS) / 1000000] + echo $TIME +} + +START=$(date +%s.%N) +ls >& /dev/null +END=$(date +%s.%N) +DIFF=$(getTime $START $END) +echo $DIFF"ms" diff --git a/linux/shell/other/natapp b/linux/shell/other/natapp new file mode 100755 index 0000000..c0f4c06 Binary files /dev/null and b/linux/shell/other/natapp differ diff --git a/linux/shell/other/shadowsocks.sh b/linux/shell/other/shadowsocks.sh new file mode 100755 index 0000000..03f4403 --- /dev/null +++ b/linux/shell/other/shadowsocks.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd ~/software/shell && ./Shadowsocks-Qt5-3.0.1-x86_64.AppImage > /dev/null 2>&1 & + diff --git a/linux/shell/other/startSunny.sh b/linux/shell/other/startSunny.sh new file mode 100755 index 0000000..80e199c --- /dev/null +++ b/linux/shell/other/startSunny.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# 用来检查内网穿透是否断开,断开则会重新连接,可与cron结合使用,定期检查内网穿透软件是否断开 + +#./sunny clientid d6e99e5b056d9016 +count=`ps aux | grep natapp | wc -l` +if [ "${count}" == "1" ]; then + ./natapp -authtoken=4c329f21d364bf71 & +else + echo "已经启动内网穿透软件" +fi diff --git a/linux/shell/other/switch.sh b/linux/shell/other/switch.sh new file mode 100755 index 0000000..1d1a88b --- /dev/null +++ b/linux/shell/other/switch.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# A touch-switch control program. + +# the Raspberry Pi GPIO input pin number, namely the pin connected to the signal output pin of the toch-switch module +GPIO_PORT=8 + +# set the specified GPIO port to INPUT mode +gpio mode $GPIO_PORT in + +while true +do + SWITCH_STATUS=`gpio read $GPIO_PORT` + if [ $SWITCH_STATUS -eq 1 ]; then + echo "Pressed @ `date +\"%F %T\"`" + fi + sleep 0.01 +done diff --git a/linux/shell/other/wechat.sh b/linux/shell/other/wechat.sh new file mode 100755 index 0000000..3824a00 --- /dev/null +++ b/linux/shell/other/wechat.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +wechat_home="/home/zeek/software/electronic-wechat" +cd $wechat_home && npm start &> /dev/null diff --git a/linux/shell/other/wgetPic.sh b/linux/shell/other/wgetPic.sh new file mode 100755 index 0000000..74f9f1e --- /dev/null +++ b/linux/shell/other/wgetPic.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# +# 用来获取图片,并且自动命名的脚本,解放劳动力 +# +DIR_HOME=`pwd` +echo $DIR_HOME +endStr=".png" +FILES=`ls $DIR_HOME` +max=0 +for fileName in $FILES +do + len=`expr ${#fileName} - ${#endStr}` + tmpStr=${fileName:0:len} + expr $tmpStr "+" 1 &> /dev/null + if [ $? -eq 0 ];then + if [ $tmpStr -gt $max ];then + max=$tmpStr + fi + fi +done +max=`expr $max + 1` +filePath=`echo $max$endStr` +if test -z $1;then + exit +fi +if [ ! -d $filePath ];then + wget $1 -O "$filePath" +else + echo $filePath "is not exist" +fi diff --git a/linux/shell/pi/reloadFrpc.sh b/linux/shell/pi/reloadFrpc.sh new file mode 100755 index 0000000..1423fd9 --- /dev/null +++ b/linux/shell/pi/reloadFrpc.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +frp=`ps -ef | grep "./frpc -c ./frpc.ini" | wc -l` +if [ "${frp}" -eq "1" ];then + cd /home/pi/frp_0.26.0_linux_arm && ./frpc -c ./frpc.ini > /tmp/frpc.log 2>&1 & + echo "\n\n" >> /tmp/frpc.log + exit 0 +fi + +deadline=`tail -n 2 /tmp/frpc.log | grep "deadline reached" | wc -l` +pids=`pgrep -f "./frpc -c ./frpc.ini"` +if [ "${deadline}" -eq "1" ];then + for pid in ${pids} + do + kill ${pid} + done + cd /home/pi/frp_0.26.0_linux_arm && ./frpc -c ./frpc.ini > /tmp/frpc.log 2>&1 & + echo "\n\n" >> /tmp/frpc.log + exit 0 +fi diff --git a/linux/shell/pi/runNatapp.sh b/linux/shell/pi/runNatapp.sh new file mode 100755 index 0000000..9aaf249 --- /dev/null +++ b/linux/shell/pi/runNatapp.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +./natapp -authtoken=4c329f21d364bf71 >/dev/null 2>&1 & + + +./natapp -authtoken=e5d919065204ce4e >/dev/null 2>&1 & diff --git a/linux/shell/pi/start.sh b/linux/shell/pi/start.sh new file mode 100755 index 0000000..b5f56b8 --- /dev/null +++ b/linux/shell/pi/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +sudo mount /dev/sda1 /media/pi/zeekling + +sudo ln -s /media/pi/zeekling /media/pi/1E652FD63A1A5238 diff --git a/linux/shell/test/test1.sh b/linux/shell/test/test1.sh new file mode 100755 index 0000000..66b4bb1 --- /dev/null +++ b/linux/shell/test/test1.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +echo param number is:$# +shift 1 +echo $* diff --git a/linux/software.md b/linux/software.md new file mode 100644 index 0000000..b4f3115 --- /dev/null +++ b/linux/software.md @@ -0,0 +1,5 @@ +## Linux 下面常用软件 +1. xfce4 桌面安装 +```shell +apt install xfce4 +``` diff --git a/linux/树莓派使用教程.md b/linux/树莓派使用教程.md new file mode 100644 index 0000000..7372e7c --- /dev/null +++ b/linux/树莓派使用教程.md @@ -0,0 +1,56 @@ + +## 搭建树莓派环境 +硬件设备 +1. 树莓派、tf卡、电源,其他的可以与电脑的共用(没有显示屏的话,建议买一个) + + +## 搭建git私服 + +### 简介 +对于树莓派来讲,虽然可以安装`gitlab`,但是需要占用的资源比较多,不太划算,而`gogs`刚好占用的资源比较少, +功能对于个人来讲已经可以了,所以是一个比较可以的选择。 + +### 安装 + +1. 安装需要用到的软件 +```sh +sudo apt install ngnix git +``` +2. 去`https://gogs.io/`官网上下载客户端,如果用的是树莓派的话建议下载`arm`版的 +3. 加压完了之后执行`./gogs web` +4. 在浏览器中打开`http://host/install`进行安装,我安装的时候没有用`mysql`数据库,所以不需要安装`mysql`数据库。 + +## 搭建`tor`中继 +暂无 + +## 监视软件 + +### 安装netdata +1. 下载 +```sh +git clone https://github.com/firehol/netdata.git --depth=1 +``` +2. 安装 +```sh +./netdata-installer.sh +``` + +## 摄像头 + +启动 +```sh +raspistill --nopreview -q 5 -o /home/pi/tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0 & +mjpg_streamer -i "input_file.so -f /home/pi/tmp/stream -n pic.jpg" -o "output_http.so -w /home/pi/mjpg-streamer/mjpg-streamer-experimental/www" +``` + +## 挖矿机 +下载地址`http://ck.kolivas.org/apps/cgminer/`,我下载的是4.9版本 +执行下面命令 +```sh +./configure --enable-cpumining +sudo make +sudo make install +``` +#### bitcoin钱包 + + diff --git a/mysql/README.md b/mysql/README.md new file mode 100644 index 0000000..ef20d64 --- /dev/null +++ b/mysql/README.md @@ -0,0 +1,18 @@ +# 数据库复习题纲 + +### [三范式](https://github.com/lzh984294471/job/tree/master/job/mysql/三范式.md) + +### [数据库基本操作](https://github.com/lzh984294471/job/tree/master/job/mysql/数据库的基本操作.md) + +### [触发器](https://github.com/lzh984294471/job/tree/master/job/mysql/触发器.md) + +### [索引](https://github.com/lzh984294471/job/tree/master/job/mysql/索引.md) + +### [事务](https://github.com/lzh984294471/job/tree/master/job/mysql/事务.md) + +### [三级模式和两级映像](https://github.com/lzh984294471/job/tree/master/job/mysql/三级模式和二级映像.md) + +### [数据库底层原理](https://github.com/lzh984294471/job/tree/master/job/mysql/数据库索引的底层原理.md.md) + +## TIPS +数据库是弱项,有好多知识点都不太懂。 diff --git a/mysql/docker_mysql.md b/mysql/docker_mysql.md new file mode 100644 index 0000000..b826983 --- /dev/null +++ b/mysql/docker_mysql.md @@ -0,0 +1,6 @@ +## 安装启动`mysql` + +```sh +docker pull mysql +docker run -h "mysql" --name "mysql" -p 12345:3306 -e MYSQL_ROOT_PASSWORD=zeekling -d mysql +``` diff --git a/mysql/三级模式和二级映像.md b/mysql/三级模式和二级映像.md new file mode 100644 index 0000000..2529ca6 --- /dev/null +++ b/mysql/三级模式和二级映像.md @@ -0,0 +1,34 @@ +## 三级模式 +DBS采用三级模式结构,那就是外模式、模式、内模式。这是DBMS的内部结构。主流DB在结构上都具有这三个特征,即采用三级模式并且提供两级映像功能。 + +### 模式 +模式也叫逻辑模式,是对DB中全体数据的逻辑结构和特征的总体描述,位于DBS的中间层,不关乎应用程序或者程序语言,仅仅涉及到对型的描述。是数据在逻辑上的视图, +记住:***一个DB只有一个 +模式。模式的一个具体值为一个实例,一个模式可以多个实例。*** + +### 外模式 +也称子模式(Subschema)或用户模式,是数据库用户(包括应用程序员和最终用户)能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图, +是与某一应用有关的数据的逻辑表示。
+理解: ① 一个数据库可以有多个外模式; ② 外模式就是用户视图; ③ 外模式是保证数据安全性的一个有力措施。 + +### 内模式 +定义:也称存储模式(Storage Schema),它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式(例如,记录的存储方式是顺序存储、按照B树结构 +存储还是按hash方法存储;索引按照什么方式组织;数据是否压缩存储,是否加密;数据的存储记录结构有何规定)。
+理解: ① 一个数据库只有一个内模式; ② 一个表可能由多个文件组成,如:数据文件、索引文件。 它是数据库管理系统(DBMS)对数据库中数据进行有效组织和管理 +的方法 其目的有: ① 为了减少数据冗余,实现数据共享; ② 为了提高存取效率,改善性能。 + +![外模式、模式、内模式的关系图](http://img.blog.csdn.net/20160314135557419) + +## 两级模式映像功能与数据独立性 +两层映像保证了数据库系统中的数据能够具有较高的逻辑独立性和物理独立性,使数据库应用程序不随数据库数据的逻辑或存储结构的变动而变动。 + +### 外模式/模式映像 +模式描述的是数据的全局逻辑结构,外模式描述的是数据的局部逻辑结构。对应于同一个模式可以有多个外模式。对于每个外模式,都有一个从外模式到模式的映像, +该映像定义了外模式与模式之间的对应关系。这些映像定义通常包含在各自的外模式描述中。
+当模式发生变化时(如增加新的关系、新的属性或改变属性的数据类型等),可以通过外模式定义语句,调整外模式/模式映像定义,从而保持外模式不变。由于应用 +程序是依据数据的外模式编写的,因此应用程序也不必修改,从而保证了程序与数据的逻辑独立性,简称为数据的逻辑独立性。 + +### 模式/内模式映像 +模式/内模式映像定义了数据库的逻辑结构与存储结构之间的对应关系。当数据库的存储结构发生改变,比如选择了另一种存储结构,只需要对模式/内模式映像做相应 +的调整,就可以保持模式不变,从而使应用程序也不必修改。因此,保证了数据与程序的物理独立性,简称为数据的物理独立性。 + diff --git a/mysql/三范式.md b/mysql/三范式.md new file mode 100644 index 0000000..ae9e019 --- /dev/null +++ b/mysql/三范式.md @@ -0,0 +1,12 @@ +## 三范式 +### 第一范式 +第一范式就是无重复属性的的列 + +### 第二范式 +第二范式是在第一范式的基础上建立起来的,即满足第二范式的必须先满足第二范式。第二范式要求数据库表中的每个实例或行必须可以被唯一的区分。为实现区分通常需要为 +表上加上一列,以存储各个实例的唯一标识。这个唯一属性列被称为主关键字或主键、主码。
+第二范式要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个 +新的实体,新实体和原始体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识,简而言之,第二范式就是属性完全依赖于主键。 + +### 第三范式 +满足第三范式必须满足第二范式。简而言之,第三范式要求一个数据库表中不包括已包括的非主关键字信息。简而言之,第三范式就是属性不依赖与其他非主属性。 diff --git a/mysql/事务.md b/mysql/事务.md new file mode 100644 index 0000000..a9d865d --- /dev/null +++ b/mysql/事务.md @@ -0,0 +1,14 @@ +## 事务 +事务,一般是指要做的或者所做的事。在计算机术语中是指访问并可能跟新数据库中各种数据项一个程序单元(unit)。在计算机术语中,事务通常就是 +数据库事务。
+当一个事务被提交给了DBMS(数据库管理系统),则DBMS需要确保该事务中的所有操作都成功完成且其结果被永远保存在数据库中,如果事务有的操作没有完成,则事务 +中有的操作没有成功完成,则事务中所有的操作都需要被回滚,回到事务执行前的状态(要么全执行,要么全都不执行);同时,该事务对数据库或者其他事务的执行无 +影响,所有的事务都好像在独立的运行。
+ +### 事务的特性 +并非任意的对数据库的操作序列都是数据库事务。事务应该具有四个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 
+ +1. 原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。 +2. 一致性:事务应确保数据库的状态从一个一致转变为另一个状态。一致状态的含义是数据库中的数据应满足[完整性约束](http://baike.baidu.com/view/4168062.htm)。 +3. 隔离性:多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 +4. 持久性:一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。 diff --git a/mysql/数据库并发问题.md b/mysql/数据库并发问题.md new file mode 100644 index 0000000..2474ece --- /dev/null +++ b/mysql/数据库并发问题.md @@ -0,0 +1,76 @@ +# 数据库并发问题 + +## 多事务运行时的并发问题 + +### 第一类丢失跟新 +撤销一个事务时,把其他事务已提交的跟新数据覆盖 + +### 脏读 +一个事务读到另一个事务未提交的跟新数据 + +### 虚读 +一个事务读到另一个事务已提交的新插入的数据; + +### 不可重新读 +一个事务读到另一个事务已提交的跟新数据; + +### 第二类丢失跟新 +这是不可重复读中的特例,一个事务覆盖另一个事务已提交的跟新数据。 + +## 数据库锁 + + + + + + + + + + + + + + + + + + + + + + + + +
资源上已放置的锁第二个事务读操作第二个食物跟新操作
立即获取锁立即获取锁
共享锁立即获取共享锁等待第一个事务解除共享锁
独占锁等待第一个事务解除独占锁等待第一个事务解除独占锁
+ +## 共享锁 +用于读数据操作,他是非独占的,允许其他事务同时读取其锁定的资源,但不允许其他事务更新他。 +1. 加锁条件:当一个事务执行select语句时。 +2. 解锁条件:默认情况下,数据读取后,数据库系统立即释放共享锁。 +3. 兼容性:放置共享锁后还可放置共享锁和更新锁。 +4. 并发性:具有良好的并发性能。当多个事务读取相同的数据时,每个事务都会获得一把共享锁,因此可以同时读锁定的数据。 + +## 独占锁 +也叫排他锁,使用与修改数据的场合。他锁定的资源,其他事务不能进行读写。 +1. 加锁条件:当一个事务执行insert,update,delete时,数据库系统会自动对被操作的数据使用独占锁。如果该数据已有其他锁存在,则不能放置独占锁。 +2. 解锁条件:事务结束。 +3. 兼容性:不和其他锁兼容。 +4. 并发性:并发性差,只允许有一个事务访问锁定数据。其他事务需等待,直到当前事务结束。 + +## 跟新锁 +更新操作的初始阶段用来锁定可以能要被修改资源的锁。更新锁可避免使用共享锁造成的死锁现象。 +1. 加锁条件:当执行update时,数据库系统会先为事务分配一个更新锁。 +2. 解锁条件:当读取数据完毕,执行更新操作时,更新锁升级为独占锁。 +3. 兼容性:与共享锁兼容。一个资源可同时放置更新锁和共享锁,但只能放置一把更新锁。 +4. 并发性:允许多个事务同时读锁定的资源,但不允许其他事务修改。 + +## 其他锁 +1. [悲观锁和乐观锁 ](http://www.hollischuang.com/archives/934)
+2. [共享锁和排他锁](http://www.hollischuang.com/archives/923)
+3. 意向锁
+ 1. 意向排他锁 + 2. 意向共享锁 + +## 推荐文章 +1. [MySQL锁(InnoDB存储引擎)](http://www.jianshu.com/p/6809adb3e9e7)
diff --git a/mysql/数据库的基本操作.md b/mysql/数据库的基本操作.md new file mode 100644 index 0000000..efe5000 --- /dev/null +++ b/mysql/数据库的基本操作.md @@ -0,0 +1,41 @@ +## 数据库操作 + +* 创建 + * 创建数据库 `CREATE DATABASE database_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;` + * 创建表: + * 创建视图: + * 创建schema: + * schema 和database的区别: +* 插入 +* 查询 + * 条件查询 + * 联合查询 + * join 查询 + * 内联接`inner join` + * 外联结`outer join` + * 左外联结`left join or left outer join` + * 右外联结`right join or right outer join` + * 完全外部联接`full join or full outer join` + * 交叉联接`cross join` 等价于`select * from table1,table2` + * union 查询 + * 子查询 + * where 型子查询 + * from 型子查询 + * exits 型子查询 + * 模糊查询`like` + * sql函数 + * avg()、count()、first()、last()、max()、min()、sum()、group by()、ucase()。 +* 删除 +* 备份`mysqldump -u username -p dbname table1 table2 ...-> BackupName.sql` + * 冷备份 + * 温备份 + * 热备份 +* 恢复`mysql -u root -p [dbname] < backup.sql` +* 约束 + * NOT NULL + * UNIQUE + * PRIMARY KEY + * FOREIGN KEY + * CHECK + * DEFAULT + diff --git a/mysql/数据库索引的底层原理.md b/mysql/数据库索引的底层原理.md new file mode 100644 index 0000000..ec65abb --- /dev/null +++ b/mysql/数据库索引的底层原理.md @@ -0,0 +1,4 @@ +### 数据库底层原理 + +* 数据库索引的底层原理 + * B-Tree 和 B+Tree diff --git a/mysql/索引.md b/mysql/索引.md new file mode 100644 index 0000000..96a3914 --- /dev/null +++ b/mysql/索引.md @@ -0,0 +1,27 @@ +## 索引 +### 概念 +在数据库中,索引用于提高数据库表数据访问速度的数据库对象。 +1. 索引可以避免全表扫描。多数查询可以扫描少量索引页及数据页,而不是遍历所有数据页。 +2. 对于非聚集索引,有些查询可以不访问数据页。 +3. 聚集索引可以避免数据插入操作集中于表的最后一个数据页。 +4. 一些情况下,索引还可以避免排序操作。 + +### 索引的类型 +#### 聚集索引 +表数据按照索引的顺序来存储的。对于聚集索引,叶子节点即存储了真实的数据行,不会再有另外的数据页。 + +#### 非聚集索引 +表数据存储顺序与索引顺序无关,对于非聚集索引,叶节点包含索引字段值及指向数据页数据的逻辑指针,该层紧邻数据页,其行数量与数据表行数量一致。 + +### 索引优点 +1. 可以通过创建唯一索引,保证数据库表中每一行数据的唯一性。 +2. 可以大大加快数据的检索速度,这也是创建索引的主要原因。 +3. 可以加速表与表之间的连接,特别是在实现数据的参考完整性方面特别有意义。 +4. 在使用分组和排序、子句进行数据检索时,同样可以显著减少查询中的分组和排序时间。 +5. 通过使用索引,可以在查询过程中,使用优化隐藏器,提高系统性能。 +### 索引缺点 +1. 创建索引和维护索引需要耗费时间,这种时间随着数据量的增加而增加。 +2. 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚族索引,那么需要的空间就会更大。 +3. 当对表中的数据进行增加、删除和修改的时候,索引也需要动态的维护,这样就降低了数据的维护速度。 + +聚集索引和非聚集索引的区别详见:[聚集索引和非聚集索引的区别](https://github.com/lzh984294471/job/tree/master/sql/聚集索引和非聚集索引的区别.md) diff --git a/mysql/聚集索引和非聚集索引的区别.md b/mysql/聚集索引和非聚集索引的区别.md new file mode 100644 index 0000000..0f4cf6b --- /dev/null +++ b/mysql/聚集索引和非聚集索引的区别.md @@ -0,0 +1,9 @@ +# 聚集索引和非聚集索引的区别 +聚集索引和非聚集索引的根本区别是排列顺序是否一致,
+***聚集索引***表记录的排列顺序与索引的排列顺序一致,优点是查询速度快,因为一旦具有第一个索引值的记录被找到,具有连续索引值的记录也一定物理的紧跟 +在其后
+聚集索引的缺点是对表的修改速度比较慢,这是为了保证表中的记录的物理顺序一致,而是把记录插入到数据页面的相应位置,必须在数据页面中数据重排,降低了 +执行速度。 
+***非聚集索引***指定了表中记录的逻辑顺序,但记录的物理顺序和索引的顺序不一致,聚集索引和非聚集索引都采用了***B+树***的结构,但非聚集索引的叶子层 +并不不与实际的数据想重叠,而是采用叶子层包含着一个指向表中的记录在数据页中的方式。非聚集索引比聚集索引层次多,添加记录不会引起数据顺序的重组。 + diff --git a/mysql/触发器.md b/mysql/触发器.md new file mode 100644 index 0000000..5d96b45 --- /dev/null +++ b/mysql/触发器.md @@ -0,0 +1,43 @@ +### 触发器 +触发器是一种与表操作有关的数据库对象,当触发器所在的表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行。
+***触发器的创建***
+``` +CREATE TRIGGER 触发器名称 BEFORE|AFTER 触发事件 +ON 表名 FOR EACH ROW +BEGIN +触发器程序体 +END + +-- 触发器名称,它和MySQL中其他对象的命名方式 +-- {BEFORE|AFTER} 触发器触发的时机 +-- {INSERT|UPDATE|DELETE} 触发器事件 +-- FOR EACH ROW 子句通知触发器每隔一行执行一次动作,而不是对整个表执行一次。 +-- (针对insert和delete语句,每一行都触发) +``` +***查看触发器***
+`show triggers;`
+***删除触发器***
+`drop trigger trigger_name;`
+***触发器中new和old的作用***
+1. 针对update操作,new表示的是更新后的值,old表示的是原来的数据。 +2. 针对insert操作,new表示插入的值。 +3. 针对delete操作,old表示的是删除后的值。
+ +***触发器特性*** 
+触发器可以禁止或者回滚违反引用完整性的更改,从而取消所尝试的数据修改。 + +### 触发器的作用 +1. 允许/限制对表的修改 +2. 自动生成派生列,比如自增字段 +3. 强制数据一致性 +4. 提供审计和日志记录 +5. 防止无效的事务处理 +6. 启用复杂的业务逻辑 + +### 触发器类型 +1. ***语句触发器***:是在表上或者某些情况下的视图上执行的特定语句或者语句组上的触发器。能够与 INSERT 、 UPDATE 、 DELETE 或者组合上进行关联。但是无论 +使用什么样的组合,各个语句触发器都只会针对指定语句激活一次。 比如,无论 update 多少行,也只会调用一次 update 语句触发器。 +2. ***行触发器***:是指为受到影响的各个行激活的触发器 +3. ***INSTEAD OF 触发器***:instead of 触发器,可以实现 : 不执行导致 trigger 触发的语句,而只执行触发器 . +5. ***用户事件触发器***:用户事件:用户登陆、注销, CREATE / ALTER / DROP / ANALYZE / AUDIT / GRANT / REVOKE / RENAME / TRUNCATE / LOGOFF + diff --git a/network/README.md b/network/README.md new file mode 100755 index 0000000..f7fb770 --- /dev/null +++ b/network/README.md @@ -0,0 +1,116 @@ +# 计算机网络复习题纲 + +## OSI分层 +* 物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)。 +* 数据链路层:将比特组装成帧和点到点传递(帧Frame)。 +* 网络层:负责数据包从源到宿的传递和网际互连。 +* 传输层:提供端到端的可靠报文传递和错误恢复。 +* 会话层:建立、管理和终止回话。 +* 表示层:对数据进行翻译、加密和压缩。 +* 应用层:允许访问OSI环境的手段。 + +## TCP/IP 分层 +* 网络接口层: +* 网际层: +* 运输层: +* 应用层: + +## 五层协议 +* 物理层: +* 数据链路层: +* 网络层: +* 运输层: +* 应用层: + +### ARP协议 +地址协议:每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系。 + +### ICMP协议 +因特网控制报文协议。他是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 + +### TFTP协议 +是TCP/IP协议族中的一个用来在客户机和服务器之间进行简单文件传输的协议,提供不复杂,开销不大的文件传输服务。 + +### HTTP协议 +超文本传输协议,是一个属于应用层的面向对象的协议,由于其简洁、快速的方式,适用于分布式超媒体信息系统。 + +### DHCP协议 +动态主机协议,是一种让系统得以连接到网络上,并获取所需的配置参数的手段。 + +### NAT协议 +网络地址转换属接入广域网(WAN)技术,是一种将私有(保留)地址转化成合法IP地址的转换技术。 + +### + +### RARP协议 +RARP是逆地址解析协议,作用是完成地址到IP地址的映射,主要用于无盘工作站,因为无盘工作站配置的IP地址不能保存。 + +## TCP三次握手和四次挥手的全过程 + +### 三次握手 +#### 第一次 +客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认。 + +#### 第二次 +服务器收到syn包,必须等待客户端的SYN(ack = x + 1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态; + +#### 第三次 +客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1)。此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 + +### 四次握手 + +#### 第一次挥手 +主动关闭方发送一个FIN,用来关闭主动到被动方的数据传送,也就是主动关闭方告诉被动方关闭方:我已经不会再给你数据了(当然,在FIN +包之前发送出去的数据,如果没有收到对应的ACK确认报文,主动关闭方依然会重新发送这些数据),但是,此时主动关闭可以接受数据。 + +#### 第二次挥手 +被关闭方收到FIN包,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。 + +#### 第三次挥手 +被关闭方发送完一个FIN包,用来关闭被关闭方到主动方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会给你发送数据了。 + +#### 第四次挥手 +主动方收到FIN后,发送一个ACK给被关闭方,确认收到序号+1,至此,完成四次握手。 + +### 三次握手和四次挥手的图解 + +![三次握手和四次挥手的图解](http://images0.cnblogs.com/blog2015/621032/201508/092017231747399.jpg) + +## TCP和UDP + +### TCP和UDP的区别 +1. TCP是提供面向连接诶、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。 +2. TCP传输单位是TCP报文,UDP传输单位称为用户数据包。 +3. TCP注重数据安全性,UDP数据传输快,因为不需要等待连接,少了许多操作,但是安全性确一般。 +### TCP对应的协议和UDP对应的协议 + +#### TCP对应的协议 +1. FTP:定义了文件传输协议,使用了21端口。 +2. Telnet:远程登陆协议。 +3. SMTP:邮件传输协议,用于发送邮件。 +4. POP3:与SMTP对应,POP3用于接受邮件。 +5. HTTP:超文本传输协议。 + +#### UDP对应的协议 +1. DNS:用于域名解析。 +2. SNMP:简单网络管理协议。 +3. TFTP:简单文件传输协议。 + +## 相关概念 +### 交换机 +在计算机网络中,交换机是针对共享模式的弱点推出的。交换机工作于OSI参考模型的第二层,即数据链路层。交换机广泛应用于二层网络交换 +俗称"二层交换机"。 +### 路由器 +路由器是一种计算机网络设备,提供了路由与转送两种机制,可以决定数据包从来源端到目的端所经过的路由路径(host到host之间的传输路径), +这个过程称为路由;将路由输入端的数据包移送至适当的路由输出端(在路由器内部进行),这称为转送。路由工作在OSI模型的第三层——即网络 +层,例如网际协议。
+***路由器的一个作用是连接不同的网络,另一个作用是选择信息传递的线路。*** 路由器与交换机的差别,路由器是属于OSI的第三层产品,交 +换机是OSI第二层的产品(这里特指第二层交换机)。 + +### 网关 +网关就是连接两个网络设备,区别于路由器(由于历史的原因,许多有关TCP/IP的文献曾经把网络层使用的路由器叫做网关,在今天很多局域网 +采用的都是路由器来接入网络,因此现在通常指的网关就是路由器的IP),经常在家庭中或者中小型企业网络中使用,使用于连接局域网和 +Internet。网关也常指把一种协议转成另一种协议设备,比如语音网关。
+在传统TCP/IP术语中,网络设备只分成两种,一种是网关,另一种是主机。网关能在网络间转递数据包,但是主机不能转送数据包。在主机(又 +称终端系统)中,数据包需经过TCP/IP四层协议处理,但是网关只需要到达网际层,决定路径之后就可以转送。
+在现代网络术语中,网关与路由的定义不同。网关能在不同协议间移动数据,而路由器是在不同的网络间移动数据。 diff --git a/oracle/Oracle知识详解.doc b/oracle/Oracle知识详解.doc new file mode 100644 index 0000000..4b17f4d Binary files /dev/null and b/oracle/Oracle知识详解.doc differ diff --git a/oracle/README.md b/oracle/README.md new file mode 100644 index 0000000..f2aa9d9 --- /dev/null +++ b/oracle/README.md @@ -0,0 +1,9 @@ +## 目录 + +* [oracle常用命令和函数](https://github.com/lzh984294471/study/blob/master/oracle/oracle%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E5%92%8C%E5%87%BD%E6%95%B0.md) + +* [oracle系统相关函数等用法](https://github.com/lzh984294471/study/tree/master/oracle/sys) + +* [oracle编程艺术读书笔记](https://github.com/lzh984294471/study/tree/master/oracle/oracle%E7%BC%96%E7%A8%8B%E8%89%BA%E6%9C%AF) + +* [plsql编程相关](https://github.com/lzh984294471/study/tree/master/oracle/plsql) diff --git a/oracle/bak/README.md b/oracle/bak/README.md new file mode 100644 index 0000000..5c38485 --- /dev/null +++ b/oracle/bak/README.md @@ -0,0 +1,3 @@ + +## 简介 +备份一些之前用过和`oracle`相关的配置文件 diff --git a/oracle/bak/listener.ora b/oracle/bak/listener.ora new file mode 100644 index 0000000..7fe0649 --- /dev/null +++ b/oracle/bak/listener.ora @@ -0,0 +1,21 @@ +STENER = + (DESCRIPTION_LIST = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = zeek)(PORT = 1521)) + (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) + ) + ) + +SID_LIST_LISTENER = + (SID_LIST = + (SID_DESC = + (GLOBAL_DBNAME = ORAL) + (SID_NAME = ORAL) + ) + + (SID_DESC = + (GLOBAL_DBNAME = orcl) + (SID_NAME = orcl) + ) +) +ADR_BASE_LISTENER = /home/u01/app/oracle diff --git a/oracle/bak/tnsnames.ora b/oracle/bak/tnsnames.ora new file mode 100644 index 0000000..ec79abe --- /dev/null +++ b/oracle/bak/tnsnames.ora @@ -0,0 +1,25 @@ +# tnsnames.ora Network Configuration File: /home/u01/app/oracle/product/12.1.0/dbhome_1/network/admin/tnsnames.ora +# Generated by Oracle configuration tools. + +ORAL = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = zeek)(PORT = 1521)) + (CONNECT_DATA = + (SERVER = DEDICATED) + (SERVICE_NAME = ORAL) + ) + ) + +LISTENER_ORCL = + (ADDRESS = (PROTOCOL = TCP)(HOST = zeek)(PORT = 1521)) + + +ORCL = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = zeek)(PORT = 1521)) + (CONNECT_DATA = + (SERVER = DEDICATED) + (SERVICE_NAME = orcl) + ) + ) + diff --git a/oracle/docker_oracle.md b/oracle/docker_oracle.md new file mode 100644 index 0000000..0b6fc80 --- /dev/null +++ b/oracle/docker_oracle.md @@ -0,0 +1,124 @@ +## 简介 +在`debian`中安装`docker`,并且在`docker`环境下使用`oracle`。 + +### docker安装 +在`https://docs.docker.com/engine/installation/#desktop` +或者去`https://download.docker.com/linux/static/stable`网址里面下载,下载完了解压到`/usr/bin/`下面(或者解压到其他地方,然后将解压路径添加到`PATH`里面)即可,在`~/.zshrc`中添加 +```sh +alias docker="sudo docker" # 不想每次都输入sudo,也不想切换到root用户 +# alias dockerd="sudo docker" # 在非root下面执行dockerd &可能不会生效 +``` + +#### 注意 +如果你的根目录所在的分区空间不是特别大的话,我并不建议解压到`/usr/bin/`下面。可以解压到其他位置(docker_path),将`docker_path`添加到`PATH`: +```sh +vi ~/.zshrc +# 或者打开 +# vi ~/.bashrc +# 在~/.zshrc 或者~/.bashrc中添加下面语句 +export $DOCKER_PATH="docker_path" +export $PATH=$PATH:$DOCKER_PATH +``` + +### 安装 启动oracle + +1. 安装启动 + * 标准版安装 + ```sh + dockerd & + docker pull sath89/oracle-12c # 12c + docker pull sath89/oracle-xe-11g # 11g + docker pull chameleon82/oracle-xe-10g # 10g + docker run -h "oracle12c" --name "oracle12c" -d -p 49160:22 -p 49161:1521 -p 49162:8080 \ + sath89/oracle-12c + docker run -h "oracle11g" --name "oracle11g" -d -p 49163:22 -p 49164:1521 -p 49165:8080 \ + sath89/oracle-xe-11g + docker run -h "oracle10g" --name "oracle10g" -d -p 49166:22 -p 49167:1521 -p 49168:8080 \ + chameleon82/oracle-xe-10g + ``` + * 企业版安装 + 下载企业版oracle,克隆项目[https://github.com/oracle/docker-images ](https://github.com/oracle/docker-images) 到本地,将oracle拷贝到在`OracleDatabase/dockerfiles/`下面,执行 + ```sh + sudo ./buildDockerImage.sh -v 12.2.0.1 -e + docker run -h "oracle12c-ee" --name "oracle12c-ee" -d -p 49170:22 -p 49171:1521 \ + -p 49172:5500 -p 49173:8080 -e ORACLE_SID=orcl -e ORACLE_PDB=pdb -e ORACLE_PWD=zeekling \ + oracle/database:12.2.0.1-ee + ``` + * 重新打开oracle容器 + ```sh + docker restart oracle12c + ``` + * tip + `docker run`是new 一个新的容器出来,名字是不能重复的 +2. 查看oracle启动日志 +```sh + docker logs -f oracle12c +``` +3. 进入镜像的bash +```sh + docker exec -it oracle12c /bin/bash +``` +默认登进去是`root`用户,`oracle`安装在`oracle`用户下面,所以进去是要切换用户的;切换用户时,默认不需要密码。 +4. 查看docker容器ip +```sh + docker inspect oracle12c | grep IPAddress +``` +5. 连接数据库 +切换到oracle用户,在`~/.bashrc`里面添加 +```sh +export ORACLE_HOME=/u01/app/oracle/product/12.1.0/xe +export PATH=$PATH:$ORACLE_HOME/bin +export $ORACLE_SID=xe +``` +这样就不用切换到`oracle`的`bin`目录下面执行`sqlplus / as sysdba`了 + +6. 图形化界面安装和启动 +在`root`用户下执行 +```sh +curl -s https://shipyard-project.com/deploy | bash -s +``` +在浏览器中打开[http://127.0.0.1:8080](http://127.0.0.1:8080),输入用户名/密码:`admin/shipyard` +再次启动`docker` 时,图形界面会随着容器启动,不用用命令启动 +可以将`https://shipyard-project.com/deploy`中的脚本保存下来,下次安装的时候使用 +```sh +curl https://shipyard-project.com/deploy > /usr/bin/dockerdeploy +# 下次执行下面语句 +dockerd & +su root +dockerdeploy +``` +7. 安装`oracle`客户端 +在[http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html ](http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html) +下载oracle客户端,建议下载rpm包,在debian系列linux上可以转成deb包,下载下面几个包就行了 +```sh +-rw-r--r-- 1 root root 42M Dec 14 22:22 oracle-instantclient12.2-basic_12.2.0.1.0-2_amd64.deb +-rw-r--r-- 1 root root 551K Dec 14 22:22 oracle-instantclient12.2-devel_12.2.0.1.0-2_amd64.deb +-rw-r--r-- 1 root root 1.5M Dec 14 22:22 oracle-instantclient12.2-jdbc_12.2.0.1.0-2_amd64.deb +-rw-r--r-- 1 root root 633K Dec 14 22:23 oracle-instantclient12.2-sqlplus_12.2.0.1.0-2_amd64.deb +-rw-r--r-- 1 root root 795K Dec 14 23:17 oracle-instantclient12.2-tools_12.2.0.1.0-2_amd64.deb +``` +安装完了之后在`~/.zshrc`或者`~/.bashrc`或者`/etc/profile`(第三个需要重启电脑)中添加 +```sh +# oracle +export ORACLE_HOME=/usr/lib/oracle/12.2/client64 +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib +export TNS_ADMIN=$ORACLE_HOME +export PATH=$ORACLE_HOME/bin:$PATH +``` +在`/usr/lib/oracle/12.2/client64/`下新建文件`tnsnames.ora`添加 +```sql +xe= + (DESCRIPTION = + (ADDRESS_LIST = + (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 49161)) + ) + (CONNECT_DATA = + (SERVICE_NAME = xe) + ) + ) +``` +然后在终端中输入(需要新键用户等操作) +```sh +sqlplus eoda/foo@xe +``` +就可以了 diff --git a/oracle/dual表的用途.md b/oracle/dual表的用途.md new file mode 100644 index 0000000..26491aa --- /dev/null +++ b/oracle/dual表的用途.md @@ -0,0 +1,32 @@ +# dual表的使用 + +### 简介 +dual 是一张虚拟表用来构成select语句的语法规则,oracle保证dual里面只有一条记录。 + +## dual用途 + +* 查看当前用户 +```sql +select user from dual; +``` +* 用来调用系统函数 +```sql +select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual; -- 获取当前时间 +select SYS_CONTEXT('USERENV','TERMINAL') FROM DUAL; -- 获取当前登陆的用户 +select SYS_CONTEXT('USERENV','language') from dual; -- 获取当前的loacle +select dbms_random.random from dual; -- 获取随机数 +``` +* 得到当前序列的值或者下一个值 +```sql +select your_sequence.nextval from dual;--获得序列your_sequence的下一个值 +select your_sequence.currval from dual;--获得序列your_sequence的当前值 +``` +* 得到1到(n - 1)的数 +```sql +select level r from dual connect by level < 10; -- 输出1-9的数 +``` +* 计算器 +```sql +select 7*9 from dual; +``` + diff --git a/oracle/oracle常用命令和函数.md b/oracle/oracle常用命令和函数.md new file mode 100644 index 0000000..dbfe66f --- /dev/null +++ b/oracle/oracle常用命令和函数.md @@ -0,0 +1,71 @@ +## oracle 常用命令 +1. 开启监听 `lsnrctl start`,关闭监听`lsnrctl stop`; +2. 查看oracle版本: +```sql +select * from v$version; +``` +3. +```sql +SPOOL report +@run_report -- 指定输出文件可使用SPOOL report.txt +SPOOL OFF +``` +将输出的内容写道命名为`report.lst`的文件当中 + +4. 查看ORACLE相关参数 +``` +select * from v$NLS_PARAMETERS; +``` +5. 在sqlplus中执行Linux命令:在Linux命令最前面添加! ,比如`!pics -a` + +## oracle 常用函数 + +1. decode() + +以下sql +```sql +SELECT supplier_name, +decode(supplier_id, 10000, 'IBM', + 10001, 'Microsoft', + 10002, 'Hewlett Packard', + 'Gateway') result +FROM suppliers; +``` +相当于 +```sql +IF supplier_id = 10000 THEN + result := 'IBM'; +ELSIF supplier_id = 10001 THEN + result := 'Microsoft'; +ELSIF supplier_id = 10002 THEN + result := 'Hewlett Packard'; +ELSE + result := 'Gateway'; +END IF; +``` +比如以下语句 +```sql +select decode(a.count,1,3) from (select count(*) as count from dual) a; +``` + +2. mod 函数 + +mod(除数,被除数) +```sql +select mod(2,4) from dual; +``` + +3. nvl 函数 +```sql +nvl(expre1,expre2) +``` +当expre1 为空时返回expre2的值 + +4. multiset 函数 +告诉oracle这个查询想返回多行数据 + +5. case函数 +对oracle的对象进行强制转换,比如 +```sql +select case( empno as varchar2(20) ) e from eoda.emp; +``` diff --git a/oracle/oracle常见问题.md b/oracle/oracle常见问题.md new file mode 100644 index 0000000..3d7333c --- /dev/null +++ b/oracle/oracle常见问题.md @@ -0,0 +1,164 @@ +## 简介 +记录在使用`oracle`过程在遇到的一些问题,我所用的操作系统是`kali rolling` +## 问题如下 +* 在安装过程中遇到的监听器打开失败的问题 + 在`$ORACLE_HOME/network/admin/listerer.ora`中添加 + ``` + STENER = + (DESCRIPTION_LIST = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST = zeek)(PORT = 1521)) + (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) + ) + ) + ADR_BASE_LISTENER = /home/u01/app/oracle + ``` + 在`$ORACLE_HOME/network/admin/tnsnames.ora`中添加 + ``` + ORAL = + (DESCRIPTION = + (ADDRESS = (PROTOCOL = TCP)(HOST =zeek)(PORT = 1521)) + (CONNECT_DATA = + (SERVER = DEDICATED) + (SERVICE_NAME = ORAL) + ) + ) + ``` + 在`/etc/hosts`中添加 (或者在`listener.ora`中host直接写成ip) + ``` + 127.0.0.1 zeek + ``` +* 在创建表的过程中报错 + ``` + ORA-65096: invalid common user or role name + ``` + 产生原因是没有指定数据库,主要出现在可插拔式数据库中 + 解决方案 + ```sql + select con_id,dbid,name,open_mode from v$pdbs; + ``` + 得到 + ``` + CON_ID DBID NAME OPEN_MODE + 2 3159417430 PDB$SEED READ ONLY + 3 874804722 ORALP MOUNTED + ``` + 接着在输入 + ```sql + alter session set container=ORALP; + ``` +* 数据库实例没注册到listener + 报错信息如下,主要出现在用`sqlplus`或者`plsql`登录时报错 + ``` + ORA-12514: TNS:listener does not currently know of service requested in connect descriptor + ``` + 在listener.ora里面添加了一行 + ``` + SID_LIST_LISTENER = + (SID_LIST = + (SID_DESC = + (GLOBAL_DBNAME = ORAL) + (SID_NAME = ORAL) + ) + ) + ``` +* scott.emp 表不存在 + 造成这个问题的原因是scott用户没有解锁,所以解决这个问题的办法就是解锁scott用户: + 执行脚本`/rdbms/admin/utlsampl.sql `(执行这个脚本的脚本是因为在12c中可能没有这个用户) + 接着执行下面语句 + ```sql + alter user scott account unlock; + alter user scott identified by tiger; + commit; + ``` +* 在执行`lsnrctl start`的时候出现如下报错 + ``` + TNS-12535: TNS:operation timed out + TNS-12560: TNS:protocol adapter error + TNS-00505: Operation timed out + ``` + 很可能是你自己不小心将`/etc/hosts` 的`127.0.0.1 zeek `删掉了,补上即可 +* `dbms_output.put_line('content' )`中文乱码 + 在`~/.zshrc`或者`~/.bashrc`或者`/etc/profile` 中添加`export NLS_LANG="AMERICAN_AMERICA.ZHS16GBK"` + +* 操作临时表时报错信息如下 + ``` + ORA-14452: attempt to create, alter or drop an index on temporary table already in use + ``` + 解决办法:执行下面sql语句,得到一个sql语句,执行语句即可 + ```sql + select 'alter system kill session '''||sid||','||serial#||'''' + from v$session + where sid in ( + select sid + from v$lock + where id1 in ( + select object_id + from dba_objects + where object_name in ( + select table_name + from dba_tables + where owner='EODA') + ) + ); + ``` +* sqlplus 中文字符显示乱码或者显示? + 登陆ORACLE + ```sh + sqlplus eoda/foo + ``` + 查询当前的数据库的字符集 + ```sql + SELECT * FROM nls_database_parameters t + WHERE t.parameter = 'NLS_CHARACTERSET'; + ``` + 我的ORACLE查询的结果`AL32UTF8` + 在`.bash_profile`中配置(如果想要在除oracle用户下面也正常使用则需要在终端的配置文件里面添加下面内容) + ``` + export NLS_LANG="AMERICAN_AMERICA.AL32UTF8" + ``` +* oracle 报错资源忙,报错信息如下 + ``` + ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired + ``` + 解决方案 + ```sql + select session_id from v$locked_object; + SELECT sid, serial#, username, osuser FROM v$session where sid = 142; -- sid 的值是上条语句查询出来的 + ALTER SYSTEM KILL SESSION '142,38'; -- 值是 sid,serial# + ``` +* 修改会话支持pdml时,报错详细信息如下 + ``` + ORA-12841: Cannot alter the session parallel DML state within a transaction + ``` + 造成错误的主要原因是会话中存在未提交的事务,只需要在提交事务就行 + ```sql + commit; + alter session enable parallel dml; + ``` +* 在已经支持了pdml的会话中查看执行计划时,报错详细信息如下 + ``` + ORA-12838: cannot read/modify an object after modifying it in parallel + ``` + 造成错误的原因是存在未提交的事务 + ```sql + commit; + explain plan for update big_table set status = 'done'; + select * from table(dbms_xplan.display(null,null, 'BASIC +PARALLEL')); + ``` +* 在对varchar2类型的字符串进行trim操作之后比较是否相等,需要注意trim结果是否为null + ```sql + -- 比较字符串是否相同,执行结果为same + begin + IF trim(' ') <> trim('1') THEN + dbms_output.put_line(' not same'); + ELSE + dbms_output.put_line('same'); + END IF; + END; + / + ``` + 可以选择使用 + ```sql + select decode(trim(' '),trim('1'),'same','not same') from dual; + ``` diff --git a/oracle/oracle常见问题.sql b/oracle/oracle常见问题.sql new file mode 100644 index 0000000..a3ed0b7 --- /dev/null +++ b/oracle/oracle常见问题.sql @@ -0,0 +1,11 @@ +-- 比较字符串是否相同,执行结果为same +begin +IF trim(' ') <> trim('1') THEN + dbms_output.put_line(' not same'); +ELSE + dbms_output.put_line('same'); +END IF; +END; +/ +-- 可以选择使用下面语句 +select decode(trim(' '),trim('1'),'same','not same') from dual; diff --git a/oracle/oracle数据类型.md b/oracle/oracle数据类型.md new file mode 100644 index 0000000..70f4193 --- /dev/null +++ b/oracle/oracle数据类型.md @@ -0,0 +1,49 @@ +## oracle数据类型 +1. `varcha2` 字母数字型数据类型,最大长度是4000字节或者字符,是变长字符串。 +### 数字类型 +1. `NUMBER`类型: +`NUMBER(P,S)`是最常见的数字类型,可以存放数据范围为10^130~10^126(不包含此值),需要1~22字节(BYTE)不等的存储空间。 +2. `INTEGER`类型 +`INTEGER`是`NUMBER`的子类型,它等同于NUMBER(38,0),用来存储整数。若插入、更新的数值有小数,则会被四舍五入。 +3. 浮点型 +`BINARY_FLOAT` 是 32 位、 单精度浮点数字数据类型。可以支持至少6位精度,每个 `BINARY_FLOAT` 的值需要 5 个字节,包括长度字节。 +`BINARY_DOUBLE` 是为 64 位,双精度浮点数字数据类型。每个 `BINARY_DOUBLE` 的值需要 9 个字节,包括长度字节。 +3. FLOAT 类型 +FLOAT类型也是NUMBER的子类型。 + +### 日期类型 +1. DATE类型 +Oracle 存储以下信息: 世纪、 年、 月、 日期、 小时、 分钟和秒。一般占用7个字节的存储空间。 +2. TIMASTAMP类型 +这是一个7字节或12字节的定宽日期/时间数据类型。它与DATE数据类型不同,因为TIMESTAMP可以包含小数秒,带小数秒的TIMESTAMP在小数点右边最多可以保留9位 +3. TIMESTAMP WITH TIME ZONE类型 +这是TIMESTAMP类型的变种,它包含了时区偏移量的值 + +### LOB类型 +内置的LOB数据类型包括BLOB、CLOB、NCLOB、BFILE(外部存储)的大型化和非结构化数据,如文本、图像、视屏、空间数据存储。BLOB、CLOB、NCLOB类型 +#### CLOB类型 +它存储单字节和多字节字符数据。支持固定宽度和可变宽度的字符集。CLOB对象可以存储最多4G文本数据 + +#### NCLOB类型 + 它存储UNICODE类型的数据,支持固定宽度和可变宽度的字符集,NCLOB对象可以存储最多4G大小的文本数据。 + +#### BLOB类型 +它存储非结构化的二进制数据大对象,它可以被认为是没有字符集语义的比特流,一般是图像、声音、视频等文件。 + +#### BFILE类型 + 二进制文件,存储在数据库外的系统文件,只读的,数据库会将该文件当二进制文件处理 + +## RAR & LONG RAW 类型 + +### LONG 类型 +它存储变长字符串,最多达2G的字符数据(2GB是指2千兆字节, 而不是2千兆字符),与VARCHAR2 或CHAR 类型一样,存储在LONG 类型中的文本要进行字符集转换。ORACLE建议开发中使用CLOB替代LONG类型。支持LONG 列只是为了保证向后兼容性。CLOB类型比LONG类型的限制要少得多。 + +### LONG RAW 类型 +能存储2GB 的原始二进制数据(不用进行字符集转换的数据) + +### RAW 类型 +用于存储二进制或字符类型数据,变长二进制数据类型,这说明采用这种数据类型存储的数据不会发生字符集转换。这种类型最多可以存储2,000字节的信息 + +## ROWID & UROWID 类型 +在数据库中的每一行都有一个地址。然而,一些表行的地址不是物理或永久的,或者不是ORACLE数据库生成的。 + diff --git a/oracle/oracle编程艺术/.dbeaver-data-sources.xml b/oracle/oracle编程艺术/.dbeaver-data-sources.xml new file mode 100644 index 0000000..6c9d23b --- /dev/null +++ b/oracle/oracle编程艺术/.dbeaver-data-sources.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oracle/oracle编程艺术/.project b/oracle/oracle编程艺术/.project new file mode 100644 index 0000000..5538e59 --- /dev/null +++ b/oracle/oracle编程艺术/.project @@ -0,0 +1,12 @@ + + + oracle编程艺术 + + + + + + + org.jkiss.dbeaver.DBeaverNature + + diff --git a/oracle/oracle编程艺术/README.md b/oracle/oracle编程艺术/README.md new file mode 100644 index 0000000..655465c --- /dev/null +++ b/oracle/oracle编程艺术/README.md @@ -0,0 +1,138 @@ +## 注意事项 + +1. 脚本中有关创建数据库表的语句是为了方便自己测试和脚本的重复执行性才先删除再重新创建,在实际的开发当中不能这样干。 +2. 在配置环境创建用户`eoda`时的那个脚本是不可以重复执行的,脚本还需要完善。 + +# 目录 +## 配置环境 +用于创建一些后面会用到的用户或者表等信息 + +## 第一章 开发成功的`oracle`应用 + +## 第二章 体系结构简介 + +## 第三章 文件 + +## 第四章 内存结构 + +## 第五章 `oracle`进程 + +## 第六章 锁 + +## 第七章 并发与多版本控制 + +## 第八章 事务 +### 原子性 +#### 语句级原子性 +即使存在触发器,一条语句要么成功,要么失败。 + +#### 过程级原子性 +调用存储过程的时候,存储过程中存在语句级原子性,会保存存储过程的部分工作 + +#### 事务级原子性 +事务的总目标是把数据库从一种一致状态转到另一种一致状态,事务是一个原子性单元 + +### 一致性 + +### 隔离性 + +### 持久性 + + +## 第九章 `redo`与`undo` + + +## 第十章 数据库表 +* 表类型 + * 堆组织表:存储的数据一般都是无序的。 + * 索引组织表:存储在索引结构中的表,iot的数据是按照主键顺序来排序的,索引表组织不存在主键索引的空间开销(索引就是数据,数据就是索引),但是管理和维护索引需要浪费资源。iot好处: + * 提高缓冲区缓存效率,尾音给定查询在缓存中的块更少 + * 减少缓冲区缓存访问,这会改善可扩展性。 + * 获取数据的总工作量,因为获取数据更快。 + * 每次查询完成物理IO更少 + * 索引聚促表:利用聚簇,一个块可能包含多个表 的数据。概念上就是如果两个或多个表经常做链接操作,那么可以把需要的数据预先存储在一起。聚簇还可以用于单个表,可以按某个列将数据分组存储。 + 不能使用聚促的情况: + * 聚簇中的表会大量修改 + * 如果需要对聚簇中的表执行全表扫描 + * 如果你认为需要频繁地TRUNCATE和加载表:聚簇中的表不能截除。 + * 散列聚促表 + * 有序散列聚促表 + * 嵌套表 +* 术语 + * 段:占用磁盘上存储空间的一个对象,包括:聚簇、表、表分区、索引、索引分区等。 + * 段空间管理: + * 手动段空间管理: + * `FREELIST`:oracle会使用freelist维护高水位线之下的块,当freelist为空时才会使用高水位之上的块,多并发用户在一个对象上执行大量插入或者跟新操作时,就可以使用配置多个freelist来提升性能。 + * 自动段空间管理: + * 高水位线:曾经包含过的最右边的块,oracle在全面扫描段时,会扫描高水位线以下的所有块。即使是高水位线与低水位线之间不包含任何数据的块也会被扫描。 + * 手动段空间管理:当高水位线推动时会格式化所有高水位线之下的块 + * 自动段空间管理:当高水位线推动时不会格式化所有高水位线之下的块,而是当使用的时候才格式化。 + * 低水位线:oracle认为低水位线之下的数据都是安全的,可以直接读取 + * `PCTFREE`和`PCTUSED`: + * `LOGGING`和`NOLOGGING` + * `INITRANS`和`MAXTRANS` + +## 第十一章 索引 +### B*Tree索引 +#### 索引键压缩 +多列索引(索引的定义含有多列)中去除冗余数据 +#### 反向键索引 +能够将索引键反转,目的主要是减少右手索引中索引也快竞争。某些用一个序列或者时间戳填充,这些列上建立的索引就属于右手索引. +#### 降序索引 +列中的数据是以降序(由达到小)的方式存储的,而不是升序(由小到大)。 +#### 使用B*Tree情况 +* 需要访问表中非常少的一部分数据,就用B*Tree索引 +* 需要处理表中大量的数据,但这些数据都可以通过索引直接拿到 + +### 位图索引 +* 适用场景:适用于相异系数低的数据,也就是与整个数据集的总数相比,这个数据只有很少的几个不同的值。 +#### 位图联结索引 +一般索引都是建立一张表上,位图联结索引可以建立在两张表上。 + +### 基于函数的索引 +对于某些列经过计算之后的结果进行索引,比如对一个大小不敏感的字段进行搜索,可以使用函数索引,对字段值的大写的值进行索引,方便查询时走索引 + +### 关于索引上的一些问题总结 +#### 视图上是否能建立索引 +访问视图 时,oracle会把视图转换成视图所定义的查询。因此只需要在视图对应的基表上面建立索引即可 +#### Null能和索引协作吗 +B*Tree不会存储键值完全为空值的条目,而位图索引和聚促索引会存储。所以B*Tree索引在查询为空的值时候不会走索引 +#### 外键是否应该加索引 +外键是导致死锁的原因之一 +#### 传言:索引中从来不重用空间 +* 一旦插入了可以重用空间的数据,索引上的空间立刻会被重用 +* 只有索引块完全被清空时,数据库才会把它从索引中取出来以备使用。 + +#### 传言:最有差别的元素应该放在最前面 + +#### 索引没有用到情况 +##### 存在B*Tree索引,但是没有使用索引的最前列 +比如,表t的索引是(x,y),当x的取值可能比较多,使用下面语句用不到索引,但是如果x的值比较少CBO中可以使用跳跃式扫描 +```sql +select * from t where y = 's'; +``` +##### 使用类似于下面语句 +```sql +select count(*) from t; +``` +因为B*Tree索引不会保存为null的数据,所以会导致索引行数和表中实际行数不一致,优化器会选择使用全表扫描 +##### 在加了索引的列上使用函数 +```sql +select * from t where upper(x) = 'A'; +``` +如果经常使用这种函数,可以考虑加函数索引 +##### 在字符类型的索引上,存放了一些数值类型 +```sql +select * from t where c = 5;-- 相当于下面语句 +select * from t where to_number(c) = 5; +``` +##### 表上的统计信息不是最新的 + + +### 第十二章 数据类型 + +### 第十三章 分区 + +### 第十四章 并行执行 + +### 第十五章 数据库加载与卸载 diff --git a/oracle/oracle编程艺术/chapt1/READMD.md b/oracle/oracle编程艺术/chapt1/READMD.md new file mode 100644 index 0000000..e69de29 diff --git a/oracle/oracle编程艺术/chapt1/accounts.sql b/oracle/oracle编程艺术/chapt1/accounts.sql new file mode 100644 index 0000000..698767b --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/accounts.sql @@ -0,0 +1,18 @@ +prompt +prompt 创建accounts表 +create table accounts +( + account_number number primary key, + account_balance number +); +/ + +prompt +prompt 插入数据到accounts表中 +begin + insert into accounts (account_number,account_balance) values (123,500.00); + insert into accounts (account_number,account_balance) values (234,250.00); + insert into accounts (account_number,account_balance) values (345,400.00); + insert into accounts (account_number,account_balance) values (456,100.00); +end; +/ diff --git a/oracle/oracle编程艺术/chapt1/inj.sql b/oracle/oracle编程艺术/chapt1/inj.sql new file mode 100644 index 0000000..1bbea1f --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/inj.sql @@ -0,0 +1,22 @@ +-- 执行的时候报错 +create or replace procedure inj(p_date in date) +as + l_username all_users.username%type; + c sys_refcursor; + l_query varchar2(400); +begin + l_query := ' + select username from all_users where create = ''' ||p_date ||''''; + + dbms_output.put_line( l_query ); + open c for l_query; + + for i in 1 .. 5 + loop + fetch c into l_username ; + exit when c%notfound; + dbms_output.put_line( l_username || '......' ); + end loop; + close c; +end; +/ diff --git a/oracle/oracle编程艺术/chapt1/multi_versioning.sql b/oracle/oracle编程艺术/chapt1/multi_versioning.sql new file mode 100644 index 0000000..faa933f --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/multi_versioning.sql @@ -0,0 +1,17 @@ +create table t +as +select username,created from all_users +/ +set autoprint off; +variable x refcursor; +begin + open :x for select * from t; +end; +/ +declare pragma autonomous_transaction; +begin + delete from t; + commit; +end; +/ +print x diff --git a/oracle/oracle编程艺术/chapt1/not_inj.sql b/oracle/oracle编程艺术/chapt1/not_inj.sql new file mode 100644 index 0000000..f26b1f1 --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/not_inj.sql @@ -0,0 +1,19 @@ +create or replace procedure not_inj(p_date in date) +as + l_username all_users.username%type; + c sys_refcursor; + l_query varchar2(400); +begin + l_query := 'select username from all_users where created = :x'; + dbms_output.put_line( l_query ); + + open c for l_query USING P_DATE; + for i in 1 .. 5 + loop + fetch c into l_username ; + exit when c%notfound; + dbms_output.put_line( l_username || '......' ); + end loop; + close c; +end; +/ diff --git a/oracle/oracle编程艺术/chapt1/proc1.sql b/oracle/oracle编程艺术/chapt1/proc1.sql new file mode 100644 index 0000000..3adc41f --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/proc1.sql @@ -0,0 +1,10 @@ +create or replace procedure eoda.proce1 +as +begin + for i in 1 .. 10000 + loop + execute immediate + 'insert into t (x) values (:x)' using i; + end loop; +end; +/ diff --git a/oracle/oracle编程艺术/chapt1/proc2.sql b/oracle/oracle编程艺术/chapt1/proc2.sql new file mode 100644 index 0000000..c74719e --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/proc2.sql @@ -0,0 +1,10 @@ +create or replace procedure eoda.proce2 +as +begin + for i in 1 .. 10000 + loop + execute immediate + 'insert into t values ('||i||')'; + end loop; +end; +/ diff --git a/oracle/oracle编程艺术/chapt1/scn.sql b/oracle/oracle编程艺术/chapt1/scn.sql new file mode 100644 index 0000000..2fae50d --- /dev/null +++ b/oracle/oracle编程艺术/chapt1/scn.sql @@ -0,0 +1,5 @@ + +-- 闪回 +variable scn number; +exec :scn := dbms_flashback.get_system_change_number; +print scn diff --git a/oracle/oracle编程艺术/chapt10/README.md b/oracle/oracle编程艺术/chapt10/README.md new file mode 100644 index 0000000..e69de29 diff --git a/oracle/oracle编程艺术/chapt10/assm.sql b/oracle/oracle编程艺术/chapt10/assm.sql new file mode 100644 index 0000000..7c0e18a --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/assm.sql @@ -0,0 +1,3 @@ + +-- +create diff --git a/oracle/oracle编程艺术/chapt10/cluster_hash.sql b/oracle/oracle编程艺术/chapt10/cluster_hash.sql new file mode 100644 index 0000000..848262a --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/cluster_hash.sql @@ -0,0 +1,30 @@ + +prompt +prompt 创建hash_cluster +create cluster hash_cluster +(hash_key number) +hashkeys 75000 +size 150 +tablespace mssm +/ + +prompt +prompt 创建表t_hashed +create table t_hashed +cluster hash_cluster(object_id) +as +select * from all_objects +/ + +prompt +prompt 在表t_hashed 添加主健约束 +alter table t_hashed add constraint +t_hashd_pk primary key(object_id) +/ + +prompt +prompt 收集表信息 +begin + dbms_stats.gather_table_stats( user,'T_HASHED' ); +end; +/ diff --git a/oracle/oracle编程艺术/chapt10/cluster_index_insert.sql b/oracle/oracle编程艺术/chapt10/cluster_index_insert.sql new file mode 100644 index 0000000..a02b03a --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/cluster_index_insert.sql @@ -0,0 +1,57 @@ + +prompt +prompt 先删除原来表中的数据 +begin + -- 以下三个的顺序不能变 + delete from eoda.emp_cluster_index; + delete from eoda.dept; + commit; +end; +/ +-- 向表dept 插入数据 +prompt +prompt 向表dept 插入数据 +begin + insert into eoda.dept + (deptno,dname,loc ) + select deptno+r,dname,loc + from scott.dept,(select level r from dual connect by level < 10); +end; +/ +-- 向表emp_cluster_index插入数据 +prompt +prompt 向表emp_cluster_index插入数据 +begin + insert into eoda.emp_cluster_index + (empno,ename,job,mgr,hiredate,sal,comm,deptno) + select rownum ,ename, job,mgr,hiredate,sal,comm,deptno + r + from scott.emp,(select level r from dual connect by level < 10); +end; +/ + +-- 放到begin end ;块中报错 +prompt +prompt 查询每块有多少dept 行 +select min(count(*)),max(count(*)),avg(count(*)) +from eoda.emp_cluster_index group by dbms_rowid.rowid_block_number(rowid); +/ + + +prompt +prompt 所有数据都得到妥善存储,完全没有emp_cluster_index表中的记录与相对应dept记录在不同块上存储的情况 +select * from +( + select + dept_blk,emp_blk,case when dept_blk <> emp_blk then '*' end flag,deptno + from + (select + dbms_rowid.rowid_block_number(dept.rowid) dept_blk, + dbms_rowid.rowid_block_number(emp_cluster_index.rowid) emp_blk, + dept.deptno + from emp_cluster_index,dept + where emp_cluster_index.deptno = dept.deptno + ) +) +where flag = '*' +order by deptno +/ diff --git a/oracle/oracle编程艺术/chapt10/cluster_index_insert2.sql b/oracle/oracle编程艺术/chapt10/cluster_index_insert2.sql new file mode 100644 index 0000000..46d212a --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/cluster_index_insert2.sql @@ -0,0 +1,62 @@ + +prompt +prompt 删除之前表eoda.emp_cluster_index eoda.dept 中的数据 +begin + delete from eoda.emp_cluster_index; + delete from eoda.dept; + commit; +end; +/ + +prompt +prompt 向表eoda.dept中插入数据 +begin + insert into eoda.dept + (deptno,dname,loc) + select deptno + r,dname,loc + from scott.dept,(select level r from dual connect by level < 10); + commit; +end; +/ + +prompt +prompt 向表eoda.emp_cluster_index 表中插入数据 +begin + insert into eoda.emp_cluster_index + (empno,ename,job,mgr,hiredate,sal,comm,deptno) + select + rownum,ename,job,mgr,hiredate,sal,comm,deptno + r + from + scott.emp, + (select level r from dual connect by level < 10), + (select level r2 from dual connect by level < 8); + commit; +end; +/ + +prompt +prompt 查询结果 +select + min(count(*)),max(count(*)),avg(count(*)) +from eoda.dept +group by dbms_rowid.rowid_block_number(rowid); +/ + +prompt +prompt 所有数据都得到妥善存储,完全没有emp_cluster_index表中的记录与相对应dept记录在不同块上存储的情况 +select * from +( + select + dept_blk,emp_blk,case when dept_blk <> emp_blk then '*' end flag,deptno + from + (select + dbms_rowid.rowid_block_number(dept.rowid) dept_blk, + dbms_rowid.rowid_block_number(emp_cluster_index.rowid) emp_blk, + dept.deptno + from emp_cluster_index,dept + where emp_cluster_index.deptno = dept.deptno + ) +) +where flag = '*' +order by deptno +/ diff --git a/oracle/oracle编程艺术/chapt10/cluster_single_hash.sql b/oracle/oracle编程艺术/chapt10/cluster_single_hash.sql new file mode 100644 index 0000000..284f602 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/cluster_single_hash.sql @@ -0,0 +1,20 @@ + +create cluster single_hash_cluster +(hash_key number(10)) +hashkeys 75000 +size 150 +single table +hash is HASH_KEY +/ + +create table t_hashed +cluster single_hash_cluster (object_id) +as +select OWNER,OBJECT_NAME,SUBOBJECT_NAME, +cast ( OBJECT_ID as number) object_id, +DATA_OBJECT_ID,OBJECT_TYPE,CREATED, +LAST_DDL_TIME,TIMESTAMP,STATUS,TEMPORARY, +GENERATED,SECONDARY +from all_objects +/ + diff --git a/oracle/oracle编程艺术/chapt10/clustered_index.sql b/oracle/oracle编程艺术/chapt10/clustered_index.sql new file mode 100644 index 0000000..fedcd87 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/clustered_index.sql @@ -0,0 +1,43 @@ + +-- 创建聚簇健列 +prompt +prompt 创建聚簇健列 +create cluster emp_dept_cluster +(deptno number(2)) +size 1024 +/ + +-- 创建聚簇健索引 +prompt +prompt 创建聚簇健索引 +create index emp_dept_cluster_idx on cluster emp_dept_cluster +/ + +-- 在聚簇中创建表 +prompt +prompt 在聚簇中创建dept表 +create table dept +( + deptno number(2) primary key, + dname varchar2(14), + loc varchar2(13) +) +cluster emp_dept_cluster(deptno) +/ + +-- 在聚簇中创建emp表 +prompt +prompt 在聚簇中创建emp表 +create table eoda.emp_cluster_index +( + empno number primary key, + ename varchar2(10), + job varchar2(9), + mgr number, + hiredate date, + sal number, + comm number, + deptno number(2) references dept(deptno) +) +cluster emp_dept_cluster(deptno) +/ diff --git a/oracle/oracle编程艺术/chapt10/dynamic_sampling.sql b/oracle/oracle编程艺术/chapt10/dynamic_sampling.sql new file mode 100644 index 0000000..a68b800 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/dynamic_sampling.sql @@ -0,0 +1,97 @@ +-- 此脚本适用于 +prompt +prompt 创建临时表gtt +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper('gtt') and temporary = 'Y'; + if num = 0 then + execute immediate ' + create global temporary table eoda.gtt + as + select * from scott.emp where 1=0 + '; + end if; +end; +/ +prompt +prompt 插入数据到eoda.gtt +begin + execute immediate 'truncate table eoda.gtt'; + insert into eoda.gtt select * from scott.emp; +end; +/ + +set autotrace traceonly explain; +select /*+ first_rows */ * from eoda.gtt; +select /*+ first_rows dynamic_sampling(gtt 2) */ * from eoda.gtt; +set autotrace off; + +prompt +prompt 创建临时表scott.emp_dynamic +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 'emp_dynamic' ) and owner = upper('eoda'); + if num = 0 then + execute immediate ' + create table eoda.emp_dynamic + as + select * from scott.emp + '; + end if; +end; +/ + + +prompt +prompt 创建临时表eoda.gtt1、和eoda.gtt2 +declare + num1 number; + num2 number; +begin + select count(1) into num1 from user_tables where table_name = upper( 'gtt1' ) and temporary = 'Y'; + select count(1) into num2 from user_tables where table_name = upper( 'gtt2' ) and temporary = 'Y'; + if num1 = 1 then + execute immediate 'drop table eoda.gtt1'; + end if; + if num2 = 1 then + execute immediate 'drop table eoda.gtt2'; + end if; + execute immediate ' + create global temporary table eoda.gtt1 ( x number ) + on commit preserve rows + '; + execute immediate ' + create global temporary table eoda.gtt2 ( x number ) + on commit delete rows + '; +end; +/ + +prompt +prompt 插入数据到eoda.gtt1 eoda.gtt2 +begin + execute immediate 'truncate table eoda.gtt1'; + execute immediate 'truncate table eoda.gtt2'; + insert into eoda.gtt1 select user_id from all_users; + insert into eoda.gtt2 select user_id from all_users; + commit; + dbms_stats.gather_schema_stats ( user ); +end; +/ + +select table_name,last_analyzed,num_rows from user_tables where table_name in ('GTT1','GTT2','EMP_DYNAMIC'); + +-- 这儿查询不到临时表的信息,这个脚本是在oracle 12c上面跑的,也可能是由于版本原因造成的 +prompt +prompt 插入数据到eoda.gtt2 +begin + execute immediate 'truncate table eoda.gtt2'; + insert into eoda.gtt2 select user_id from all_users; + commit; + dbms_stats.gather_schema_stats ( user, gather_temp=>TRUE ); +end; +/ + +select table_name,last_analyzed,num_rows from user_tables where table_name in ('GTT1','GTT2','EMP_DYNAMIC'); diff --git a/oracle/oracle编程艺术/chapt10/hash_heap.sql b/oracle/oracle编程艺术/chapt10/hash_heap.sql new file mode 100644 index 0000000..5620d14 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/hash_heap.sql @@ -0,0 +1,48 @@ + +prompt +prompt 创建传统的堆表eoda.t_heap +declare + num number; + num_hashed number; +begin + select count(1) into num from all_tables where TABLE_NAME = 'T_HEAP' AND OWNER = 'EODA'; + select count(1) into num_hashed from all_tables where TABLE_NAME = 'T_HEAPED' AND OWNER = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.t_heap'; + end if; + if num_hashed = 0 then + execute immediate ''; + end if; + execute immediate ' + create table eoda.t_heap + as + select * from eoda.t_hashed + '; +end; +/ + + +prompt +prompt 添加主健eoda.t_heap +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'T_HEAP' and owner = 'EODA'; + if num = 1 then + execute immediate 'alter table eoda.t_heap add constraint t_heap_pk primary key(object_id)' + end if; +end; +/ + + +prompt +prompt 收集统计信息 +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'T_HEAP' and owner = 'EODA'; + if num = 1 then + dbms_stats.gather_table_stats( user,'T_HEAP' ); + end if; +end; +/ diff --git a/oracle/oracle编程艺术/chapt10/iot.sql b/oracle/oracle编程艺术/chapt10/iot.sql new file mode 100644 index 0000000..6eff3fc --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/iot.sql @@ -0,0 +1,28 @@ + +-- 创建iot表 +prompt +prompt 创建iot表 +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'IOT' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.iot'; + end if; + execute immediate ' + create table iot + ( + owner, + object_type, + object_name, + constraint iot_pk primary key (owner,object_type,object_name) + ) organization index NOCOMPRESS + as + select distinct owner,object_type,object_name from all_objects + '; +end; +/ + +analyze index iot_pk validate structure; +select lf_blks,br_blks,used_space,opt_cmpr_count,opt_cmpr_pctsave from index_stats; + diff --git a/oracle/oracle编程艺术/chapt10/iot_heap_comp.sql b/oracle/oracle编程艺术/chapt10/iot_heap_comp.sql new file mode 100644 index 0000000..96b8a08 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/iot_heap_comp.sql @@ -0,0 +1,129 @@ +/** + * 本脚本用于创建表和插入相关数据,不能重复执行 + * + **/ + +-- 创建emp表 +prompt +prompt 创建emp表 +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'EMP' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.emp'; + end if; + execute immediate ' + create table eoda.emp + as + select + object_id empno, + object_name ename, + created hiredate + from + all_objects + '; +end; +/ + +prompt +prompt emp 表添加索引 +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'EMP' and owner = 'EODA'; + if num = 1 then + execute immediate 'alter table emp add constraint emp_pk primary key (empno)'; + end if; +end; +/ + +prompt +prompt 统计信息 +begin + dbms_stats.gather_table_stats (user,'EMP',cascade=>true); +end; +/ + +-- 创建表heap_addresses +prompt +prompt 创建表heap_addresses +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'HEAP_ADDRESSES' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.heap_addresses'; + end if; + execute immediate ' + create table heap_addresses + ( + empno references emp(empno) on delete cascade, + addr_type varchar2(10), + street varchar2(20), + city varchar2(20), + state varchar2(2), + zip number, + primary key (empno,addr_type) + ) + '; +end; +/ + +-- 创建表iot_addresses +prompt +prompt 创建表iot_addresses +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'IOT_ADDRESSES' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.iot_addresses'; + end if; + execute immediate ' + create table iot_addresses + ( + empno references emp(empno) on delete cascade, + addr_type varchar2(10), + street varchar2(20), + city varchar2(20), + state varchar2(2), + zip number, + primary key (empno,addr_type) + ) ORGANIZATION INDEX + '; +end; +/ + +-- 向表中插入数据 +prompt +prompt 向表中插入数据 +declare + num_iot number; + num_heap number; +begin + select count(1) into num_iot from all_tables where table_name = 'IOT_ADDRESSES' and owner = 'EODA'; + select count(1) into num_heap from all_tables where table_name = 'HEAP_ADDRESSES' and owner = 'EODA'; + if num_heap = 1 and num_iot = 1 then + insert into heap_addresses select empno,'WORK','123 main street','Washington','DC',20123 from scott.emp; + insert into iot_addresses select empno,'WORK','123 main street','Washington','DC',20123 from scott.emp; + commit; + end if; +end; +/ + +-- 收集统计信息 +prompt +prompt 收集统计信息 +declare + num_iot number; + num_heap number; +begin + select count(1) into num_iot from all_tables where table_name = 'IOT_ADDRESSES' and owner = 'EODA'; + select count(1) into num_heap from all_tables where table_name = 'HEAP_ADDRESSES' and owner = 'EODA'; + if num_heap = 1 and num_iot = 1 then + dbms_stats.gather_table_stats( user,'HEAP_ADDRESSES' ); + dbms_stats.gather_table_stats( user,'IOT_ADDRESSES' ); + end if; +end; +/ diff --git a/oracle/oracle编程艺术/chapt10/mssm.sql b/oracle/oracle编程艺术/chapt10/mssm.sql new file mode 100644 index 0000000..7d925ca --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/mssm.sql @@ -0,0 +1,3 @@ + +-- 创建mssm表空间 +create tablespace mssm datafile size 1m autoextend on next 1m segment space management manual; diff --git a/oracle/oracle编程艺术/chapt10/mssm_freelist.sql b/oracle/oracle编程艺术/chapt10/mssm_freelist.sql new file mode 100644 index 0000000..20c40a8 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/mssm_freelist.sql @@ -0,0 +1,20 @@ + +prompt +prompt 创建表t +create table t +( + x int, + y char(50) +) storage (freelists 5) tablespace mssm; +/ + +prompt +prompt 向表中插入1000000条数据 +begin + for i in 1 .. 1000000 + loop + insert into t values (i,'x'); + end loop; + commit; +end; +/ diff --git a/oracle/oracle编程艺术/chapt10/mssm_nofreelist.sql b/oracle/oracle编程艺术/chapt10/mssm_nofreelist.sql new file mode 100644 index 0000000..1a1f394 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/mssm_nofreelist.sql @@ -0,0 +1,16 @@ +-- 在表空间中创建表t; +create table t +( + x int, + y char(50) +) tablespace mssm; + +-- 插入大量数据到表t中 +begin + for i in 1 .. 1000000 + loop + insert into t values ( i ,'x' ); + end loop; + commit; +end; +/ diff --git a/oracle/oracle编程艺术/chapt10/nest_table.sql b/oracle/oracle编程艺术/chapt10/nest_table.sql new file mode 100644 index 0000000..053ceb9 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/nest_table.sql @@ -0,0 +1,180 @@ + +/* + * + * + * + */ + +-- begin 用关系模式实现嵌套表的模型 +prompt +prompt 创建dept表 +declare + num number; + num_emp number; +begin + select count(1) into num from all_tables where table_name = 'DEPT_NEST' and owner = 'EODA'; + select count(1) into num_emp from all_tables where table_name = 'EMP_NEST' and owner = 'EODA'; + if num_emp = 1 then + execute immediate 'drop table eoda.emp_nest'; + end if; + if num = 1 then + execute immediate 'drop table eoda.dept_nest'; + end if; + execute immediate ' + create table eoda.dept_nest + ( + deptno number(2) primary key, + dname varchar2(14), + loc varchar2(13) + ) + '; +end; +/ + +prompt +prompt 创建表emp_nest +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'EMP_NEST' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.emp_nest'; + end if; + execute immediate ' + create table eoda.emp_nest + ( + empno number(4) primary key, + ename varchar2(10), + job varchar2(9), + mgr number(4) references emp_nest, + hiredate date, + sal number(7,2), + comm number(7,2), + deptno number(2) references dept_nest + ) + '; +end; +/ +-- end 用关系模式实现嵌套表的模型 + +prompt +prompt 创建type eoda.emp_type +declare + num number; +begin + select count(1) into num from all_types where type_name = 'EMP_TYPE' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop type eoda.emp_type force'; + end if; + execute immediate ' + create or replace type eoda.emp_type + as object + ( + empno number(4), + ename varchar2(10), + job varchar2(9), + mgr number(4), + hiredate date, + sal number(7,2), + comm number(7,2) + ) + '; +end; +/ + +prompt +prompt 创建type eoda.emp_tab_type +create or replace type emp_tab_type +as table of emp_type +/ + +prompt +prompt 创建表eoda.dept_and_emp +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'DEPT_AND_EMP' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.dept_and_emp'; + end if; + -- 在创建eoda.dept_and_emp表的时候也会创建表eoda.emps_nt + execute immediate ' + create table eoda.dept_and_emp + ( + deptno number(2) primary key, + dname varchar2(14), + loc varchar2(13), + emps emp_tab_type + ) + nested table emps store as emps_nt + '; +end; +/ + +prompt +prompt 添加唯一索引 +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'DEPT_AND_EMP' and owner = 'EODA'; + if num = 1 then + execute immediate 'alter table emps_nt add constraint emps_empno_unique unique(empno)'; + end if; +end; +/ + +prompt +prompt 插入数据 +begin + execute immediate 'truncate table eoda.dept_and_emp'; + insert into eoda.dept_and_emp + select dept.*, + cast( multiset( select emp.empno,emp.ename,emp.job,emp.mgr,emp.hiredate,emp.sal,emp.comm + from scott.emp emp + where emp.deptno = dept.deptno ) as emp_tab_type ) + from scott.dept dept; +end; +/ + + +select deptno,dname,loc,d.emps as employees + from eoda.dept_and_emp d +where d.deptno = 10; + +select d.deptno,d.dname,emp.* +from eoda.dept_and_emp d, table(d.emps) emp; + +prompt +prompt 跟新表数据 +begin + update table( select emps from eoda.dept_and_emp where deptno = 10 ) set comm = 100; +end; +/ + +select d.deptno,d.dname,emp.* + from eoda.dept_and_emp d, table(d.emps) emp; + +-- 由于数据较多,所以少查几条 +select /*+NESTED_TABLE_GET_REFS+*/ nested_table_id,sys_nc_rowinfo$ from eoda.emps_nt where rownum < 5; + +select name + from sys.col$ + where obj# = ( + select object_id + from dba_objects + where object_name = 'DEPT_AND_EMP' and + owner = 'EODA' ); + + +select SYS_NC0000400005$ + from eoda.dept_and_emp; + +prompt +prompt DBMS_METADATA.GET_DDL转储信息 +begin + dbms_metadata.set_transform_param( DBMS_METADATA.SESSION_TRANSFORM,'STORAGE',false ); +end; +/ + +-- 第一次运行会比较慢,慢的要死 +select dbms_metadata.get_ddl( 'TABLE','DEPT_AND_EMP' ) from dual; diff --git a/oracle/oracle编程艺术/chapt10/object_table.sql b/oracle/oracle编程艺术/chapt10/object_table.sql new file mode 100644 index 0000000..b3f6239 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/object_table.sql @@ -0,0 +1,84 @@ +prompt +prompt 创建类型eoda.address_type +--declare +-- num number; +begin +-- select count(1) into num all_types where type_name = upper( 'address_type' ) and owner = upper( 'eoda' ); +-- if num = 1 then +-- execute immediate 'drop type eoda.address_type'; +-- end if; + execute immediate ' + create or replace type eoda.address_type + as object + ( + city varchar2(30), + street varchar2(30), + state varchar2(2), + zip number + ) + '; +end; +/ + +prompt +prompt 创建类型eoda.person_type +begin + execute immediate ' + create or replace type eoda.person_type + as object + ( + name varchar2(30), + dob date, + home_address address_type, + work_address address_type + ) + '; +end; +/ + +prompt +prompt 创建表eoda.people +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 'people' ) and owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.people'; + end if; + execute immediate 'create table eoda.people of eoda.person_type'; +end; +/ + +desc eoda.people; + +prompt +prompt +begin + execute immediate 'truncate table eoda.people'; + insert into eoda.people values ( 'Tom','15-mar-1965', + address_type ( 'Denver','123 Main Street','Co','12345' ), + address_type( 'Redwood','1 Oracle Way','Ca','23456' ) ); +end; +/ + +begin + dbms_output.put_line( '查询1' ); +end; +/ +select name,dob,p.home_address Home,p.work_address work from eoda.people p; + +begin + dbms_output.put_line( '查询2' ); +end; +/ +select name,p.home_address.city from eoda.people p; + + +select name,segcollength + from sys.col$ + where obj#= ( select object_id + from user_objects + where object_name = upper( 'people' ) + ); + +select sys_nc_rowinfo$ from eoda.people; diff --git a/oracle/oracle编程艺术/chapt10/sampling.sql b/oracle/oracle编程艺术/chapt10/sampling.sql new file mode 100644 index 0000000..f6ac0e6 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/sampling.sql @@ -0,0 +1,16 @@ +CREATE GLOBAL +TEMPORARY TABLE gt (x number) ON +COMMIT PRESERVE ROWS TRUNCATE TABLE gt +INSERT INTO gt +SELECT user_id +FROM all_users; + +dbms_stats.gather_table_stats (USER,'GT'); + + +SELECT TABLE_NAME, + num_rows, + last_analyzed, + SCOPE +FROM user_tab_statistics +WHERE TABLE_NAME LIKE 'GT'; diff --git a/oracle/oracle编程艺术/chapt10/sampling_delete.sql b/oracle/oracle编程艺术/chapt10/sampling_delete.sql new file mode 100644 index 0000000..defa987 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/sampling_delete.sql @@ -0,0 +1,35 @@ + +prompt +prompt 创建eoda.gt_delete +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 'gt_delete' ) and temporary = 'Y'; + if num = 1 then + execute immediate 'drop table eoda.gt_delete'; + end if; + execute immediate ' + create global temporary table eoda.gt_delete ( x number ) + on commit delete rows + '; +end; +/ + +prompt +prompt 插入数据到eoda.gt_delete +declare + num number; +begin + execute immediate 'truncate table eoda.gt_delete'; + insert into eoda.gt_delete select user_id from all_users; + -- 在事务提交之前查询,等到事务提交之后eoda.gt_delete表中数据就会被清除 + select count(*) into num from eoda.gt_delete; + dbms_output.put_line ( '表中数据' || to_char( num ) ); + commit; + dbms_stats.gather_table_stats ( user,'GT_DELETE' ); +end; +/ + +select table_name,num_rows,last_analyzed,scope + from user_tab_statistics + where table_name like 'GT_DELETE'; diff --git a/oracle/oracle编程艺术/chapt10/sampling_share.sql b/oracle/oracle编程艺术/chapt10/sampling_share.sql new file mode 100644 index 0000000..27a64f1 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/sampling_share.sql @@ -0,0 +1,49 @@ +prompt +prompt 创建表eoda.gt +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 'gt' ) and temporary = 'Y'; + if num = 1 then + execute immediate 'drop table eoda.gt'; + end if; + execute immediate ' + create global temporary table eoda.gt ( x number ) + on commit preserve rows + '; +end; +/ + +prompt +prompt 插入数据到eoda.gt +begin + execute immediate 'truncate table eoda.gt'; + insert into eoda.gt select user_id from all_users; + commit; + -- 将GLOBAL_TEMP_TABLE_STATS设置成SHARED + dbms_stats.set_table_prefs( user,'GT','GLOBAL_TEMP_TABLE_STATS','SHARED' ); + dbms_stats.gather_table_stats ( user,'GT' ); +end; +/ + +begin + dbms_output.put_line ( '查询视图USER_TAB_STATISTICS' ); +end; +/ +select table_name,num_rows ,last_analyzed,scope + from user_tab_statistics + where table_name like 'GT'; + +begin + dbms_output.put_line ( '清除统计信息' ); +end; +/ +exec dbms_stats.delete_table_stats ( user,'GT' ); + +begin + dbms_output.put_line ( '查询视图USER_TAB_STATISTICS' ); +end; +/ +select table_name,num_rows ,last_analyzed,scope + from user_tab_statistics + where table_name like 'GT'; diff --git a/oracle/oracle编程艺术/chapt10/segment.sql b/oracle/oracle编程艺术/chapt10/segment.sql new file mode 100644 index 0000000..aaa84aa --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/segment.sql @@ -0,0 +1,25 @@ + +-- 在执行脚本之前需要保证数据库中不存在表名为t的表,如果有的话删掉 +select segment_name,segment_type from user_segments; + +create table t +( + x int primary key, + y clob, + z blob +) +SEGMENT CREATION IMMEDIATE +/ +-- 延迟段创建,只有在oracle 11g之后的企业版中才有的,在之前的版本中不支持 + + +select segment_name,segment_type from user_segments; + +create table t +( + x int primary key, + y clob, + z blob +) +SEGMENT CREATION IMMEDIATE +/ diff --git a/oracle/oracle编程艺术/chapt10/sorted_hash_cluster.sql b/oracle/oracle编程艺术/chapt10/sorted_hash_cluster.sql new file mode 100644 index 0000000..f678830 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/sorted_hash_cluster.sql @@ -0,0 +1,77 @@ + + +prompt +prompt 创建cluster shc +declare + num number; +begin + select count(1) into num from all_clusters where cluster_name = 'SHC' and owner = 'EODA'; + if num = 1 then + select count(1) into num from all_tables where table_name = 'CUST_ORDERS' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.cust_orders'; + end if; + -- 如果还有表需要删除,在这里添加 + execute immediate 'drop cluster eoda.shc'; + end if; + execute immediate ' + create cluster shc + ( + cust_id number, + order_dt timestamp SORT + ) + hashkeys 10000 + hash is cust_id + size 8129 + '; +end; +/ + +prompt +prompt 创建eoda.cust_orders +declare + num number; +begin + select count(1) into num from all_tables where table_name = 'CUST_ORDERS' and owner = 'EODA'; + if num = 1 then + execute immediate 'drop table eoda.cust_orders'; + end if; + execute immediate ' + create table eoda.cust_orders + ( + cust_id number, + order_dt timestamp SORT, + order_number number, + username varchar2(30), + ship_addr number, + bill_addr number, + invoice_num number + ) + cluster shc ( cust_id, order_dt ) + '; +end; +/ + + +prompt +prompt 查看执行计划 +set autotrace traceonly explain; +variable x number +begin + select + cust_id,order_dt,order_number + from + eoda.cust_orders + where + cust_id = :x + order by order_dt; + + select + job,hiredate,empno + from + scott.emp + where job = 'CLERK' + order by hiredate; +end; +/ +set autotrace off; diff --git a/oracle/oracle编程艺术/chapt10/state_pkg.sql b/oracle/oracle编程艺术/chapt10/state_pkg.sql new file mode 100644 index 0000000..ab82498 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/state_pkg.sql @@ -0,0 +1,36 @@ + +prompt +prompt 创建 state_pkg +create or replace package state_pkg +as + type array is table of t_hashed.object_id%type; + g_data array; +end; +/ + +prompt +prompt 将查询得到的数据填入到state_pkg.g_data +begin + select object_id bulk collect into state_pkg.g_data + from t_hashed + order by dbms_random.random; +end; +/ + +prompt +prompt heap代替hashed +declare + l_rec t_heap%rowtype; +begin + for i in 1 .. state_pkg.g_data.count + loop + select * into l_rec from t_heap + where object_id = state_pkg.g_data(i); + end loop; +end; +/ + +prompt +prompt 执行报告 +exec runstats_pkg.rs_stop (10000); +/ diff --git a/oracle/oracle编程艺术/chapt10/temp_table.sql b/oracle/oracle编程艺术/chapt10/temp_table.sql new file mode 100644 index 0000000..5cb5539 --- /dev/null +++ b/oracle/oracle编程艺术/chapt10/temp_table.sql @@ -0,0 +1,73 @@ + +prompt +prompt 创建临时表eoda.temp_table_session +declare + num number; +begin + select count(1) into num from user_tables where table_name =upper( 'temp_table_session') and TEMPORARY = 'Y'; + if num = 1 then + execute immediate 'drop table eoda.temp_table_session'; + end if; + execute immediate ' + create global temporary table eoda.temp_table_session + on commit preserve rows + as + select * from scott.emp where 1=0 + '; +end; +/ + +prompt +prompt 创建临时表eoda.temp_table_transaction +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 'temp_table_transaction' ) and TEMPORARY = 'Y'; + if num = 1 then + execute immediate 'drop table eoda.temp_table_transaction'; + end if; + execute immediate ' + create global temporary table temp_table_transaction + on commit delete rows + as + select * from scott.emp where 1=0 + '; +end; +/ + +prompt +prompt 插入数据到eoda.temp_table_session、eoda.temp_table_transaction +declare + session_cnt number; + transaction_cnt number; +begin + execute immediate 'truncate table eoda.temp_table_session'; + execute immediate 'truncate table eoda.temp_table_transaction'; + insert into eoda.temp_table_session select * from scott.emp; + insert into eoda.temp_table_transaction select * from scott.emp; + select session_cnt,transaction_cnt into session_cnt,transaction_cnt + from ( select count(*) session_cnt from eoda.temp_table_session ), + ( select count(*) transaction_cnt from eoda.temp_table_transaction ); + dbms_output.put_line( 'session_cnt = ' || to_char( session_cnt ) || ',transaction_cnt = ' || to_char( transaction_cnt )); + commit; + select session_cnt,transaction_cnt into session_cnt,transaction_cnt + from ( select count(*) session_cnt from eoda.temp_table_session ), + ( select count(*) transaction_cnt from eoda.temp_table_transaction ); + dbms_output.put_line( 'session_cnt = ' || to_char( session_cnt ) || ',transaction_cnt = ' || to_char( transaction_cnt )); +end; +/ + +connect eoda/foo + +prompt +prompt 重新连接、查看临时表中的数据 +declare + session_cnt number; + transaction_cnt number; +begin + select session_cnt,transaction_cnt into session_cnt,transaction_cnt + from ( select count(*) session_cnt from eoda.temp_table_session ), + ( select count(*) transaction_cnt from eoda.temp_table_transaction ); + dbms_output.put_line( 'session_cnt = ' || to_char( session_cnt ) || ',transaction_cnt = ' || to_char( transaction_cnt )); +end; +/ diff --git a/oracle/oracle编程艺术/chapt11/b_tree_compressed.sql b/oracle/oracle编程艺术/chapt11/b_tree_compressed.sql new file mode 100644 index 0000000..ea16888 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/b_tree_compressed.sql @@ -0,0 +1,81 @@ +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper('t') ; + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * from all_objects + where rownum <= 50000 + '; +end; +/ + +prompt +prompt 创建索引eoda.t_idx +declare + num number; +begin + select count(1) into num from user_indexes where table_name = upper('t') and index_name = upper('t_idx'); + if num = 1 then + execute immediate 'drop index eoda.t_idx '; + end if; + execute immediate ' + create index eoda.t_idx on + eoda.t(owner,object_type,object_name) + '; +end; +/ + +analyze index eoda.t_idx validate structure; + +prompt +prompt 创建表eoda.idx_stats +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper('idx_stats'); + if num = 1 then + execute immediate 'drop table eoda.idx_stats'; + end if; + execute immediate ' + create table eoda.idx_stats + as + select ''nocompressed'' what,a.* + from index_stats a + '; +end; +/ + +prompt +prompt 重建索引eoda.idx_stats +declare + num number; +begin + select count(1) into num from user_indexes where table_name = upper('t') and index_name = upper('t_idx'); + if num = 1 then + execute immediate 'drop index eoda.t_idx '; + end if; + execute immediate ' + create index eoda.t_idx on + eoda.t(owner,object_type,object_name ) + compress &1 + '; + execute immediate 'analyze index eoda.t_idx validate structure '; + insert into eoda.idx_stats + select 'compress &1',a.* + from index_stats a; +end; +/ + +select what,height,lf_blks,br_blks,btree_space,opt_cmpr_count,opt_cmpr_pctsave + from eoda.idx_stats +/ + +select 1974060 * (1-0.28) from dual; +/ diff --git a/oracle/oracle编程艺术/chapt11/b_tree_index.sql b/oracle/oracle编程艺术/chapt11/b_tree_index.sql new file mode 100644 index 0000000..6f20540 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/b_tree_index.sql @@ -0,0 +1,9 @@ + +select index_name,blevel, num_rows + from user_indexes + where table_name = upper( 'big_table' ); + +set autotrace on ; + +select id from eoda.big_table where id = 42; + diff --git a/oracle/oracle编程艺术/chapt11/bitmap_index.sql b/oracle/oracle编程艺术/chapt11/bitmap_index.sql new file mode 100644 index 0000000..da972dd --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/bitmap_index.sql @@ -0,0 +1,98 @@ +/** + * 位图索引 + **/ +prompt +prompt 创建eoda.emp +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('emp'); + if row_count = 1 then + execute immediate 'drop table eoda.emp '; + end if; + execute immediate ' + create table eoda.emp + as + select * from scott.emp + '; +end; +/ + +prompt +prompt 创建位图索引eoda.job_idx +declare + row_count number(5); +begin + select count(1) into row_count from user_indexes where index_name = upper('job_jdx') and table_name = upper('emp'); + if row_count = 1 then + execute immediate 'drop index eoda.job_idx'; + end if; + execute immediate ' + create bitmap index eoda.job_idx on eoda.emp(job) + '; +end; +/ + +prompt +prompt 创建eoda.t +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + ( + gender not null, + location not null, + age_group not null, + data + ) + as + select + decode( round(dbms_random.value(1,2)) ,1, ''M'',2 , ''F'' ) gender, + ceil( dbms_random.value(1,50) ) location , + decode( round(dbms_random.value(1,5)),1,''18 and under'',2,''19-25'',3,''26-30'',4,''31-40'',5,''41 and over'' ), + rpad( ''*'',20,''*'' ) + from dual connect by level <= 100000 + '; +end; +/ + +prompt +prompt 创建位图索引eoda.gender_idx、eoda.location_idx、eoda.age_group_idx +declare + row_count_gender number(5); + row_count_location number(5); + row_count_age_group number(5); +begin + select count(1) into row_count_gender from user_indexes where index_name = upper('gender_idx'); + select count(1) into row_count_location from user_indexes where index_name = upper('location_idx'); + select count(1) into row_count_age_group from user_indexes where index_name = upper('age_group_idx'); + if row_count_gender = 1 then + execute immediate 'drop index eoda.gender_idx'; + end if; + if row_count_location = 1 then + execute immediate 'drop index eoda.location_idx'; + end if; + if row_count_age_group = 1 then + execute immediate 'drop index eoda.age_group_idx'; + end if; + execute immediate 'create bitmap index eoda.gender_idx on eoda.t(gender)'; + execute immediate 'create bitmap index eoda.location_idx on eoda.t(location)'; + execute immediate 'create bitmap index eoda.age_group_idx on eoda.t(age_group)'; +end; +/ +prompt +prompt 搜集信息edoa.t +exec dbms_stats.gather_table_stats ( user,'T' ); + +prompt +prompt 查询edoa.t +select count(*) + from eoda.t + where gender = 'M' + and location in (1, 10, 30) + and age_group = '41 and over'; diff --git a/oracle/oracle编程艺术/chapt11/bitmap_join_index.sql b/oracle/oracle编程艺术/chapt11/bitmap_join_index.sql new file mode 100644 index 0000000..5a28234 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/bitmap_join_index.sql @@ -0,0 +1,61 @@ +/* + * 位图联接索引 + * + */ +prompt +prompt 创建eoda.emp 和edoa.dept +declare + row_count_emp number(5); + row_count_dept number(5); +begin + select count(1) into row_count_emp from user_tables where table_name = upper('emp'); + select count(1) into row_count_dept from user_tables where table_name = upper('dept'); + if row_count_emp = 1 then + execute immediate 'drop table eoda.emp'; + end if; + if row_count_dept = 1 then + execute immediate 'drop table eoda.dept'; + end if; + execute immediate ' + create table eoda.dept + as + select * from scott.dept + '; + execute immediate ' + create table eoda.emp + as + select * from scott.emp + '; +end; +/ + +prompt +prompt 创建位图索引eoda.emp_bm_idx +declare + row_count number(5); +begin + select count(1) into row_count from user_indexes where index_name = upper('emp_bm_idx'); + if row_count = 1 then + execute immediate 'drop index eoda.emp_bm_idx'; + end if; + execute immediate ' + create bitmap index eoda.emp_bm_idx + on eoda.emp (d.dname) + from eoda.emp e,eoda.dept d + where e.deptno = d.deptno + '; +end; +/ + +prompt +prompt 让cbo认为表很大eoda.emp、eoda.dept +begin + dbms_stats.set_table_stats( user ,'EMP',numrows => 1000000,numblks => 300000); + dbms_stats_set_table_stats( user,'DEPT' ,numrows => 1000000,numblks => 300000); + dbms_stats.delete_index_stats( user,'EMP_BM_IDX' ); +end; +/ + +select count(*) from eoda.emp a,eoda.dept b +where a.deptno = b.deptno +and b.dname = 'SALES'; diff --git a/oracle/oracle编程艺术/chapt11/colocated.sql b/oracle/oracle编程艺术/chapt11/colocated.sql new file mode 100644 index 0000000..86c98d2 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/colocated.sql @@ -0,0 +1,84 @@ +/* + * 比较相邻数据保存在相同数据块和不同数据块查询速度 + */ +prompt +prompt 创建表eoda.colocated +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('colocated'); + if row_count = 1 then + execute immediate 'drop table eoda.colocated '; + end if; + execute immediate ' + create table eoda.colocated + ( + x int, + y varchar2(80) + ) + '; +end; +/ + +prompt +prompt 插入数据eoda.colocated +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('colocated'); + if row_count = 1 then + for i in 1 .. 100000 + loop + insert into eoda.colocated ( x,y ) + values ( i,rpad(dbms_random.random,75,'*') ); + end loop; + commit; + execute immediate ' + alter table eoda.colocated add constraint colocated_pk primary key(x) + '; + dbms_stats.gather_table_stats( user, 'COLOCATED' ); + end if; +end; +/ + +prompt +prompt 创建表eoda.disorganized +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('disorganized'); + if row_count = 1 then + execute immediate 'drop table eoda.disorganized'; + end if; + execute immediate ' + create table eoda.disorganized + as + select x,y + from eoda.colocated + order by y + '; + execute immediate ' + alter table eoda.disorganized add constraint disorganized_pk primary key(x) + '; + dbms_stats.gather_table_stats( user,'DISORGANIZED' ); +end; +/ + +select * +from eoda.colocated +where x between 20000 and 40000; +/ + +select /*+ index( eoda.disorganized disorganized_pk ) */ * +from eoda.disorganized +where x between 20000 and 40000; +/ + +select a.index_name, + b.num_rows, + b.blocks, + a.clustering_factor +from user_indexes a, user_tables b +where a.index_name in ( 'COLOCATED_PK','DISORGANIZED_PK' ) +and a.table_name = b.table_name; +/ diff --git a/oracle/oracle编程艺术/chapt11/compressed_key_index.sql b/oracle/oracle编程艺术/chapt11/compressed_key_index.sql new file mode 100644 index 0000000..6a9d3e2 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/compressed_key_index.sql @@ -0,0 +1,58 @@ + +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 't' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * from all_objects + where rownum <= 50000 + '; +end; +/ + +prompt +prompt 创建索引eoda.t_idx +declare + num number; +begin + select count(1) into num from user_indexes where table_name = upper( 't' ) and index_name = upper( 't_idx' ); + if num = 1 then + execute immediate 'drop index eoda.t_idx'; + end if; + execute immediate ' + create index eoda.t_idx on eoda.t( owner,object_type,object_name ) + '; +end; +/ + +prompt +prompt 分析eoda.t_idx +begin + execute immediate 'analyze index eoda.t_idx validate structure'; +end; +/ + +prompt +prompt 创建表eoda.idx_stats +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 'idx_stats' ); + if num = 1 then + execute immediate 'drop table eoda.idx_stats'; + end if; + execute immediate ' + create table eoda.idx_stats + as + select ''noncompressed'' what, a.* + from index_stats a + '; +end; +/ diff --git a/oracle/oracle编程艺术/chapt11/descending.sql b/oracle/oracle编程艺术/chapt11/descending.sql new file mode 100644 index 0000000..7f6c5a5 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/descending.sql @@ -0,0 +1,65 @@ +/* + * 降序索引相关 + * + */ +prompt +prompt 创建表eoda.t +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * + from all_objects + '; +end; +/ + +prompt +prompt 搜集相关信息表eoda.t +begin + dbms_stats.gather_table_stats (user ,'T', method_opt=>'for all indexd columns'); +end; +/ + +set autotrace traceonly explain +select owner, object_type + from eoda.t +where owner between 'T' and 'z' + and object_type is not null +order by owner desc, object_type desc; +/ + +select owner, object_type + from eoda.t +where owner between 'T' and 'z' + and object_type is not null +order by owner desc, object_type asc; +/ + +prompt +prompt 创建索引eoda.desc_t_idx +declare + row_count number(5); +begin + select count(1) into row_count from user_indexes where index_name = upper('desc_t_idx'); + if row_count = 1 then + execute immediate 'drop index eoda.desc_t_idx'; + end if; + execute immediate ' + create index eoda.desc_t_idx on eoda.t(owner desc, object_type asc ) + '; +end; +/ + +select owner, object_type + from eoda.t +where owner between 'T' and 'z' + and object_type is not null +order by owner desc, object_type asc; +/ diff --git a/oracle/oracle编程艺术/chapt11/function_base_index.sql b/oracle/oracle编程艺术/chapt11/function_base_index.sql new file mode 100644 index 0000000..e7580d6 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/function_base_index.sql @@ -0,0 +1,81 @@ +/* + * 基于函数的索引 + */ + +prompt +prompt 'create table eoda.emp and idnex eoda.emp_upper_idx' +declare + row_count number(5); + row_count_emp_idx number(5); +begin + select count(*) into row_count from user_tables where table_name = upper('emp'); + if row_count = 1 then + execute immediate 'drop table eoda.emp'; + end if; + execute immediate ' + create table eoda.emp + as + select * + from scott.emp + where 1=0 + '; + insert into eoda.emp + (empno,ename,job,mgr,hiredate,sal,comm,deptno) + select rownum empno, + initcap(substr(object_name,1,10)) ename, + substr(object_type,1,9) job, + rownum mgr, + created hiredate, + rownum sal, + rownum comm, + (mod(rownum,4) + 1) * 10 deptno + from all_objects + where rownum < 10000; + select count(1) into row_count_emp_idx from user_indexes where index_name = upper('emp_upper_idx'); + if row_count_emp_idx = 1 then + execute immediate 'drop idnex eoda.emp_upper_idx'; + end if; + execute immediate ' + create index eoda.emp_upper_idx on eoda.emp(upper(ename)) + '; + dbms_stats.gather_table_stats( user,'EMP',cascade=>true ); +end; +/ + +select * from eoda.emp where upper(ename) = 'KING'; + +prompt +prompt 'create function my_soundex' +create or replace function my_soundex( p_string in varchar ) +return varchar2 +deterministic +as +l_return_string varchar2(6) default substr( p_string,1 ,1 ); +l_char varchar2(1); +l_last_digit number default 0; + +type vcArray is table of varchar2(10) index by binary_integer; +l_code_table vcArray; +begin + stats.cnt := stats.cnt + 1; + l_code_table(1) := 'BPFV'; + l_code_table(2) := 'CSKGJQXZ'; + l_code_table(3) := 'DT'; + l_code_table(4) := 'L'; + l_code_table(5) := 'MN'; + l_code_table(6) := 'R'; + for i in 1 .. length(p_string) + loop + exit when (length(l_return_string) = 6 ); + l_char := upper(substr( p_string,1 ,1 )); + for j in 1 .. l_code_table.count + loop + if (instr(l_code_table(j), l_char ) > 0 and j <> l_last_digit ) + then + l_return_string := l_return_string || to_char(j,'fm9'); + l_last_digit := j; + end if; + end loop; + end loop; +end; +/ diff --git a/oracle/oracle编程艺术/chapt11/index_not_use/case_five.sql b/oracle/oracle编程艺术/chapt11/index_not_use/case_five.sql new file mode 100644 index 0000000..b2ac11c --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/index_not_use/case_five.sql @@ -0,0 +1,41 @@ + +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t (x int) + '; +end; +/ + +prompt +prompt 'insert data into eoda.t' +begin + insert into eoda.t select rownum from dual connect by level < 1000000; +end; +/ + +prompt +prompt 'create index ti' +declare row_count number(5); +begin + select count(1) into row_count from user_indexes where table_name = upper('t') and index_name = upper('ti'); + if row_count = 1 then + execute immediate 'drop index eoda.ti'; + end if; + execute immediate 'create index eoda.ti on eoda.t(x)'; +end; +/ + +exec dbms_stats.gather_table_stats(user, 'T'); + +-- 当数据较少时,cbo会认为走索引好一点 +select count(*) from eoda.t where x < 50; + +-- 当超过一定 +select count(*) from eoda.t where x < 1000000; diff --git a/oracle/oracle编程艺术/chapt11/index_not_use/case_four.sql b/oracle/oracle编程艺术/chapt11/index_not_use/case_four.sql new file mode 100644 index 0000000..9547fb3 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/index_not_use/case_four.sql @@ -0,0 +1,36 @@ + +/* + * 当出现隐式转换时,查询不会走索引,会走全表扫描 + */ +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t (x char(1) constraint t_pk primary key, y date) + '; +end; +/ + +prompt +prompt 'insert data into eoda.t' +begin + insert into eoda.t values ('5',sysdate); + commit; +end; +/ + +-- 存在隐式转换 to_number(x) = 5 +explain plan for select * from eoda.t where x = 5 +select * from table(dbms_xplan.display); +-- 强制使用唯一索引,还是存在隐式转换 to_number(x) = 5; +explain plan for select /*+ INDEX(t t_pk) */ * from eoda.t where x = 5; +select * from table(dbms_xplan.display); +-- 不存在隐式转换,直接使用唯一索引 +explain plan for select * from eoda.t where x = '5'; +select * from table(dbms_xplan.dislay); + diff --git a/oracle/oracle编程艺术/chapt11/invisible_index.sql b/oracle/oracle编程艺术/chapt11/invisible_index.sql new file mode 100644 index 0000000..025613a --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/invisible_index.sql @@ -0,0 +1,34 @@ +/* + * + */ +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t(x int) + '; +end; +/ + +prompt +prompt 'insert data into eoda.t' + insert into eoda.t select round(dbms_random.value(1,10000)) from dual connect by level <= 10000; +/ + +prompt +prompt 'create index edoa.ti' +begin + dbms_stats.gather_table_stats( user, 'T' ); + execute immediate 'create index eoda.ti on eoda.t(x) invisible'; +end; +/ + +select * from eoda.t where x = 5; +alter session set optimizer_use_invisible_indexes=true; +select * from eoda.t where x = 5; +alter session set optimizer_use_invisible_indexes=false; diff --git a/oracle/oracle编程艺术/chapt11/reverse.sql b/oracle/oracle编程艺术/chapt11/reverse.sql new file mode 100644 index 0000000..43c22ec --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/reverse.sql @@ -0,0 +1,127 @@ +/* + * 反向键索引 + * + */ + +select 90101, dump(90101,16) from dual + union all +select 90102, dump(90102,16) from dual + union all +select 90103, dump(90103,16) from dual +/ + +prompt +prompt 创建表空间assm +declare + row_count number(5); +begin + select count(1) into row_count from dba_tablespaces where tablespace_name = upper('assm'); + if row_count = 0 then + execute immediate ' + create tablespace assm + datafile ''/u01/app/oracle/oradata/xe/assm.dbf'' size 1m autoextend on next 1m + segment space management auto + '; + end if; +end; +/ + +prompt +prompt 创建表eoda.t +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t tablespace assm + as + select 0 id,owner, object_name,subject_name, + object_id,data_object_id,object_type,created, + last_ddl_time,timestamp,status,temporary, + generated,secondary + from all_obejects a + where 1=0 + '; + alter table eoda.t add constraint t_pk on eoda.t(id) primary key (id) + using index (create index t_pk on eoda.t(t) &indexType tablespace assm ); +end; +/ + +prompt +prompt 创建存储过程eoda.do_sql +create or replace procedure do_sql +as +begin + for x in ( + select rownum r,OWNER,OBJECT_NAME,SUBJECT_NAME, + OBJECT_ID,DATA_OBJECT_TYPE,CREATED, + LAST_DDL_TIME,TIMESTAMP,STATUS,TEMPORARY, + GENERATED,SECONDARY + ) + loop + insert into eoda.t + ( + id,owner,object_name,subject_name, + object_id,data_object_id,object_type,created, + last_ddl_time,timestamp,status,temporary, + generated, secondary + ) + values + ( + s.nextval,x.owner,x.object_name,x.subject_name, + x.object_id,x.data_object_id,x.object_type,x.created, + x.last_ddl_time,x.timestamp,x.status,x.temporary, + x.generated, x.secondary + ); + if ( mod(x.r,100) = 0 ) then + commit; + end if; + end loop; + commit; +end; +/ + +prompt +prompt 模拟加载转换加载.. +begin + declare c cursor for select * from all_objects; + open c; + whenever notfound do break; + for (;;) + { + fetch c into :owner:owner_i, + :object_name:object_name_i, :subject_name:subject_name_i, + :object_id:object_id_i, :data_object_id:data_object_id_i, + :object_type:object_type_i, :created:created_i, + :last_ddl_time:last_ddl_time_i, :timestamp:timestamp_i, + :status:status_i, :temporary:temporary_i, + :generated:generated_i, :secondary:secondary_i; + + insert into eoda.t + ( + id,owner,object_name,subject_name, + object_id,data_object_id,object_type,created, + last_ddl_time,timestamp,status,temporary, + generated, secondary + ) + values + ( + s.nextval_i,x.owner_i,x.object_name_i,x.subject_name_i, + x.object_id_i,x.data_object_id_i,x.object_type_i,x.created_i, + x.last_ddl_time_i,x.timestamp_i,x.status_i,x.temporary_i, + x.generated_i, x.secondary_i + ); + + if ( (++cnt%100) == 0 ) + { + commit; + } + } + whenever notfound continue; + commit; + close c; +end; +/ diff --git a/oracle/oracle编程艺术/chapt11/virtural_index.sql b/oracle/oracle编程艺术/chapt11/virtural_index.sql new file mode 100644 index 0000000..142ea5e --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/virtural_index.sql @@ -0,0 +1,34 @@ + +/* + * 使用虚拟列 + */ +prompt +prompt 'create table t' +declare + row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t (x varchar2(3276)) + '; +end; +/ + +prompt +prompt 'insert data to eoda.t' +begin + insert into eoda.t + select to_char(level) || rpad('abc',1000,'xyz') + from dual connect by level < 1001 + union + select to_char(level) + from dual connect by level < 1001; + execute immediate 'alter table eoda.t add (xv as (substr(x,1,10)))'; + execute immediate ' + create index te on eoda.t(xv) + '; +end; +/ diff --git a/oracle/oracle编程艺术/chapt11/wrong_think/index_not_reuse_place.sql b/oracle/oracle编程艺术/chapt11/wrong_think/index_not_reuse_place.sql new file mode 100644 index 0000000..2834279 --- /dev/null +++ b/oracle/oracle编程艺术/chapt11/wrong_think/index_not_reuse_place.sql @@ -0,0 +1,40 @@ + +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate 'create table eoda.t (x int, constraint t_pk primary key(x))'; +end; +/ + +prompt +prompt 'insert data into eoda.t' +begin + insert into eoda.t values (1); + insert into eoda.t values (2); + insert into eoda.t values (999999999); +end; +/ + +analyze index eoda.t_pk validate structure; +select lf_blks,BR_BLKS,BTREE_SPACE from index_stats; + +prompt +prompt 'reinsert data to eoda.t' +begin + for i in 2 .. 10000 + loop + delete from eoda.t where x = i; + commit; + insert into eoda.t values (i + 1); + commit; + end loop; +end; +/ + +analyze index eoda.t_pk validate structure; +select lf_blks,BR_BLKS,BTREE_SPACE from index_stats; diff --git a/oracle/oracle编程艺术/chapt12/README.md b/oracle/oracle编程艺术/chapt12/README.md new file mode 100644 index 0000000..725df4e --- /dev/null +++ b/oracle/oracle编程艺术/chapt12/README.md @@ -0,0 +1,2 @@ + +`oracle`数据类型 diff --git a/oracle/oracle编程艺术/chapt13/index_partition.sql b/oracle/oracle编程艺术/chapt13/index_partition.sql new file mode 100644 index 0000000..4e07720 --- /dev/null +++ b/oracle/oracle编程艺术/chapt13/index_partition.sql @@ -0,0 +1,3 @@ +/** + 索引分区 +*/ diff --git a/oracle/oracle编程艺术/chapt13/table_partition.sql b/oracle/oracle编程艺术/chapt13/table_partition.sql new file mode 100644 index 0000000..717da4b --- /dev/null +++ b/oracle/oracle编程艺术/chapt13/table_partition.sql @@ -0,0 +1,149 @@ +-- 创建tablespace p1和p2, + +CREATE TABLESPACE p1 DATAFILE '/opt/oracle/oradata/orcl/p1.dbf' SIZE 1m autoextend ON NEXT 1m; + + +CREATE TABLESPACE p2 DATAFILE '/opt/oracle/oradata/orcl/p2.dbf' SIZE 1m autoextend ON NEXT 1m; + +-- oracle11g 执行下面两句,存在差异的主要原因是在docker中安装时,oracle路径等造成的 +-- create tablespace p1 datafile '/u01/app/oracle/oradata/XE/p1.dbf' size 1m autoextend on next 1m; +-- create tablespace p2 datafile '/u01/app/oracle/oradata/XE/p2.dbf' size 1m autoextend on next 1m; +-- 创建表emp,并根据字段emp将数据分散到两个表空间中 +-- 分区是oracle收费部分,标准版没有,所以下面语句在标准版中会报错 + +CREATE TABLE emp (empno int, ename varchar2(20)) PARTITION BY hash(empno) (PARTITION part_1 TABLESPACE p1, + PARTITION part_2 TABLESPACE p2); + +-- select * from scott.emp; + +INSERT INTO emp +SELECT empno, + ename +FROM scott.emp; + + +SELECT * +FROM emp partition(part_1); + + +SELECT * +FROM emp partition(part_2); + +-- 创建tablespace big1、big2 注意:由于下面sql语句的size比较大,创建起来比较费时间 + +CREATE TABLESPACE big1 DATAFILE '/opt/oracle/oradata/orcl/big1.dbf' SIZE 1200m; + + +CREATE TABLESPACE big2 DATAFILE '/opt/oracle/oradata/orcl/big2.dbf' SIZE 1200m; + + +CREATE OR REPLACE PROCEDURE hash_proc (p_nhash IN number, p_cursor OUT sys_refcursor) authid CURRENT_USER AS l_next long; + +ROW_COUNT number; + +l_template long := 'select $PRS$ oc,''p$PROS$'' pname,count(*) cnt' || ' from t partition ($PNAME$) union all '; + +table_or_view_not_exits +EXCEPTION; + +pragma exception_init(table_or_view_not_exits,-942); + +BEGIN BEGIN +SELECT count(*) INTO ROW_COUNT +FROM user_tables +WHERE TABLE_NAME = upper('t'); + +IF ROW_COUNT = 1 THEN EXECUTE IMMEDIATE 'drop table t'; + +END IF; + + +EXCEPTION WHEN table_or_view_not_exits THEN NULL; + +END; + +EXECUTE IMMEDIATE ' +create table t (id) +partition by hash(id) +partitions ' || p_nhash || ' +as +select rownum +from all_objects +'; + + +FOR x IN + (SELECT partition_name pname, + partition_position pos + FROM user_tab_partitions + WHERE TABLE_NAME = 'T' + ORDER BY partition_position) LOOP l_next := l_next || +REPLACE (replace(l_template,'$POS$',x.pos), + '$PNAME$', + x.pname); + +END LOOP; + +OPEN p_cursor +FOR 'select pname,cnt, + substr( rpad(''*'',30*round( cnt/max(cnt)over(),2 ),''*''),1,30 ) hg + from ('|| substr(l_next,1,length(l_next) - 11) ||') + order by oc'; + +END; + +-- 引用分区 +-- 出错:THEN 误写成then + +CREATE TABLE orders (order# number PRIMARY KEY, + order_date date, DATA varchar2(30)) ENABLE ROW movement PARTITION BY range (order_date) (PARTITION part_2014 + VALUES LESS THAN(to_date('01-01-2015','dd-mm-yyyy')), + PARTITION part_2015 + VALUES LESS THAN(to_date('01-01-2016','dd-mm-yyyy'))); + + +INSERT INTO orders +VALUES (1, + to_date('01-jun-2014','dd-mm-yyyy'), + 'xxx'); + + +INSERT INTO orders +VALUES (2, + to_date('01-jun-2015','dd-mm-yyyy'), + 'xxx'); + +-- 虚拟列分区 + +CREATE TABLE res(reservation_code varchar2(30)); + + +INSERT INTO res(reservation_code) +SELECT chr(64+round(dbms_random.value(1,4))) || LEVEL +FROM dual CONNECT BY LEVEL <= 100000; + + +SELECT * +FROM res; + + +DROP TABLE res; + + +CREATE TABLE res (reservation_code varchar2(30), + region AS (decode(substr(reservation_code,1,1), 'A','NE','C','NE','B','SW','D','NW'))) PARTITION BY list(region) (PARTITION p1 + VALUES('NE'), PARTITION p2 + VALUES('SW'), PARTITION p3 + VALUES('NW')); + +-- 行移动 + +CREATE TABLE range_example ( range_key_column date, DATA varchar2(20)) PARTITION BY range (range_key_column) ( PARTITION part_1 + VALUES LESS THAN (to_date('01/01/2014','dd/mm/yyyy')), PARTITION part_2 + VALUES LESS THAN (to_date('01/01/2015','dd/mm/yyyy'))); + + +insert into range_example (range_key_column,data) values (to_date('15-dec-2013 00:00:00','dd-mon-yyyy hh24:mi:ss'),'application data...'); +insert into range_example (range_key_column,data) values (to_date('01-jan-2013 00:00:00','dd-mon-yyyy hh24:mi:ss')-1/24/60/60,'application data...'); +select * from range_example partition(part_1); +update range_example set range_key_column = trunc(range_key_column) where range_key_column = to_date('31-dec-2013 23:59:59','dd-mon-yyyy hh24:mi:ss'); diff --git a/oracle/oracle编程艺术/chapt14/parallel.sql b/oracle/oracle编程艺术/chapt14/parallel.sql new file mode 100644 index 0000000..ab62e73 --- /dev/null +++ b/oracle/oracle编程艺术/chapt14/parallel.sql @@ -0,0 +1,84 @@ + +-- hint下之后就是非并行的 +explain plan for select /*+ no_parallel */ count(status) from big_table; +select * from table(dbms_xplan.display(null,null, 'TYPICAL -ROWS -BYTES -COST')); + +-- 修改big_table为并行的 +alter table big_table parallel; + +explain plan for select /*+ PARALLEL(4) */ count(status) from big_table; +select * from table(dbms_xplan.display(null,null, 'TYPICAL -ROWS -BYTES -COST')); + +-- 在执行下句sql语句时,需要确认会话中不存在未提交的事务 +alter session enable parallel dml; +select pdml_enabled from v$session where sid = sys_context('userenv','sid'); +update big_table set status = 'done'; + +-- 在执行下句sql语句时,需要确认会话中不存在未提交的事务 +explain plan for update big_table set status = 'done'; +select * from table(dbms_xplan.display(null,null, 'BASIC +PARALLEL')); + +-- 创建表user_info +create table user_info as select * from all_users; +alter table user_info parallel; +exec dbms_stats.gather_table_stats( user,'USER_INFO' ); + +-- select count(*) from all_users; +-- select * from all_users; + +select * from table(dbms_xplan.display); + +create table t1 +as +select object_id id,object_name text +from +all_objects; + +exec dbms_stats.set_table_stats( user,'T1',numrows=>10000000,numblks=>100000 ); + +create table t2 +as +select t1.*,0 session_id +from t1 +where 1=0; + + +create or replace type t2_type +as object ( + id number, + text varchar2(30), + session_id number +) +/ + +create or replace type t2_tab_type +as table of t2_type +/ + +-- 并发处理 +create or replace function +parallel_pipelined(l_cursor in sys_refcursor) +return t2_tab_type +pipelined +parallel_enable (partition l_cursor by any) +is +l_session_id number; +l_rec t1%rowtype; +begin + select sid into l_session_id + from v$mystat + where rownum = 1; + loop + fetch l_cursor into l_rec; + exit when l_cursor%notfound; + -- complex process here + pipe row(t2_type(l_rec.id,l_rec.text,l_session_id)); + end loop; + close l_cursor; + return; +end; +/ + +alter session enable parallel dml; +insert /*+ append */ into t2(id,text,session_id ) +select * from table(parallel_pipelined (cursor (select /*+ parallel(t1) */ * from t1))); diff --git a/oracle/oracle编程艺术/chapt15/dept.ctl b/oracle/oracle编程艺术/chapt15/dept.ctl new file mode 100644 index 0000000..e83caec --- /dev/null +++ b/oracle/oracle编程艺术/chapt15/dept.ctl @@ -0,0 +1,10 @@ +load data +infile * +into table dept +fields terminated by ',' +(deptno,dname,loc) +begindata +10,Sales,Virginia +20,Accounting,Virginia +30,Consulting,Virginia +40,Finance,Virginia diff --git a/oracle/oracle编程艺术/chapt15/dept.dat b/oracle/oracle编程艺术/chapt15/dept.dat new file mode 100644 index 0000000..b809b81 --- /dev/null +++ b/oracle/oracle编程艺术/chapt15/dept.dat @@ -0,0 +1,4 @@ +10,Sales,Virginia +20,Accounting,Virginia +30,Consulting,Virginia +40,Finance,Virginia diff --git a/oracle/oracle编程艺术/chapt2/README.md b/oracle/oracle编程艺术/chapt2/README.md new file mode 100644 index 0000000..4b6d4fa --- /dev/null +++ b/oracle/oracle编程艺术/chapt2/README.md @@ -0,0 +1,2 @@ +## 简介 + diff --git a/oracle/oracle编程艺术/chapt3/get_param.sql b/oracle/oracle编程艺术/chapt3/get_param.sql new file mode 100644 index 0000000..5c22080 --- /dev/null +++ b/oracle/oracle编程艺术/chapt3/get_param.sql @@ -0,0 +1,28 @@ + +prompt +prompt 'get_param' +create or replace function get_param(p_name in varchar2) +return varchar2 +as + l_param_type number; + l_intval binary_integer; + l_strval varchar2(256); + invalid_paramter exception; + pragma exception_init(invalid_paramter,-20000); +begin + begin + l_param_type := dbms_utility.get_parameter_value(parnam => p_name, intval => l_intval, strval => l_strval ); + exception + when invalid_paramter then + return '*access denied*'; + end; + if ( l_param_type = 0 ) then + l_strval := to_char(l_intval); + end if; + return l_strval; +end; +/ + +exec dbms_output.put_line( get_param( 'db_block_size' ) ); + + diff --git a/oracle/oracle编程艺术/chapt6/latch_test.sql b/oracle/oracle编程艺术/chapt6/latch_test.sql new file mode 100644 index 0000000..d9629c6 --- /dev/null +++ b/oracle/oracle编程艺术/chapt6/latch_test.sql @@ -0,0 +1,15 @@ + + +prompt +prompt 'latch ' +begin + for i in 1 .. 10 + loop + for x in (select * from user_tables where table_name = 'T'||i) + loop + execute immediate 'drop table ' || x.table_name; + end loop; + execute immediate 'create table t' || i || ' (x int) '; + end loop; +end; +/ diff --git a/oracle/oracle编程艺术/chapt6/test_lock.sql b/oracle/oracle编程艺术/chapt6/test_lock.sql new file mode 100644 index 0000000..c670722 --- /dev/null +++ b/oracle/oracle编程艺术/chapt6/test_lock.sql @@ -0,0 +1,74 @@ + +/** + + 此脚本执行时可能造成死锁 + +**/ + +prompt +prompt 'create table t' +declare row_count number; +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table t'; + end if; + execute immediate ' + create table t + ( + x int primary key, + y varchar2(4000) + ) + '; +end; +/ + +prompt +prompt 'insert date' +begin + insert into t (x,y) select rownum,rpad('*',148,'*') from dual connect by level <= 46; +end; +/ + +select length(y), dbms_rowid.rowid_block_number(rowid) blk,count(*),min(x),max(x) + from t + group by length(y),dbms_rowid.rowid_block_number(rowid); + + +prompt +prompt 'procedure do_update' +create or replace procedure do_update( p_n in number ) +as + pragma autonomouse_transaction; + l_rec t%rowtype; + resource_busy exception; + pragma exception_init( resource_busy, -54 ); +begin + select * + into l_rec + from t + where x = p_n + for update NOWAIT; + commit; +exception + when resource_busy then + dbms_output.put_line( 'locked out trying to select row ' || p_n ); + commit; + when no_data_found then + dbms_output.put_line( 'we finished - no problems' ); + commit; +end; +/ + +exec do_update(1); + +truncate table t; + +insert into t (x,y) select rownum,rpad('*',147,'*') from dual connect by level <= 46; +/ + +select length(y), dbms_rowid.rowid_block_number(rowid) blk,count(*),min(x),max(x) + from t + group by length(y),dbms_rowid.rowid_block_number(rowid); + +exec do_update(1); diff --git a/oracle/oracle编程艺术/chapt7/read_and_write.sql b/oracle/oracle编程艺术/chapt7/read_and_write.sql new file mode 100644 index 0000000..2bba020 --- /dev/null +++ b/oracle/oracle编程艺术/chapt7/read_and_write.sql @@ -0,0 +1,23 @@ +exec dbms_monitor.session_trace_enable; +-- 如果t表的表结构和下面不相符,则删除重新建表 +-- drop table t; +-- create table t(x int); +select * from t; +update t t1 set x = x + 1; +update t t2 set x = x + 1; +select * from t; + +-- 触发器 +-- 表结构 +-- create table t (x int, y int); +-- insert into t values(1,1); +create or replace trigger t_buffer +before update on t for each row +begin + dbms_output.put_line('old.x = ' || :old.x || ',.old.y = ' || :old.y); + dbms_output.put_line('new.x = ' || :new.x || ',.new.y = ' || :new.y); +end; + +update t set x = x + 1; + +update t set x = x + 1 where x > 0; \ No newline at end of file diff --git a/oracle/oracle编程艺术/chapt8/autonomous_insert.sql b/oracle/oracle编程艺术/chapt8/autonomous_insert.sql new file mode 100644 index 0000000..826c3f7 --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/autonomous_insert.sql @@ -0,0 +1,59 @@ + +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 't' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t ( msg varchar2(25) ) + '; +end; +/ + +prompt +prompt 创建存储过程eoda.Autonomous_insert +create or replace procedure eoda.Autonomous_insert +as + pragma autonomous_transaction; +begin + insert into eoda.t values ( 'Autonomous Insert' ); + commit; +end; +/ + +prompt +prompt 创建存储过程eoda.NonAutonomous_insert +create or replace procedure eoda.NonAutonomous_insert +as +begin + insert into eoda.t values ( 'NonAutonomous Insert' ); + commit; +end; +/ + +prompt +prompt 非自治事务eoda.NonAutonomous_insert +begin + insert into eoda.t values ( 'Anonymous Block' ); + NonAutonomous_insert; + rollback; +end; +/ + +select * from eoda.t; + +prompt +prompt 自治事务edoa.Autonomous_insert +begin + execute immediate 'truncate table eoda.t'; + insert into eoda.t values ( 'Anonymous Block' ); + Autonomous_insert; + rollback; +end; +/ + +select * from eoda.t; diff --git a/oracle/oracle编程艺术/chapt8/cascade_update.sql b/oracle/oracle编程艺术/chapt8/cascade_update.sql new file mode 100644 index 0000000..f809f65 --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/cascade_update.sql @@ -0,0 +1,98 @@ +prompt +prompt 创建表eoda.parent +declare + parent_num number; + child_num number; +begin + select count(1) into parent_num from all_tables where table_name = upper ( 'parent' ) and owner = upper ( 'eoda' ); + select count(1) into child_num from all_tables where table_name = upper ( 'child' ) and owner = upper ( 'eoda' ); + if child_num = 1 then + execute immediate 'drop table eoda.child'; + end if; + if parent_num = 1 then + execute immediate 'drop table eoda.parent'; + end if; + execute immediate ' + create table eoda.parent + ( + pk int primary key + ) + '; +end; +/ + + +prompt +prompt 创建表eoda.child +declare + parent_num number; + child_num number; +begin + select count(1) into parent_num from all_tables where table_name = upper ( 'parent' ) and owner = upper ( 'eoda' ); + select count(1) into child_num from all_tables where table_name = upper ( 'child' ) and owner = upper ( 'eoda' ); + if parent_num = 1 then + if child_num = 1 then + execute immediate 'drop table eoda.child'; + end if; + execute immediate ' + create table eoda.child + ( + fk constraint child_fk_parent + references parent(pk) + deferrable + initially immediate + ) + '; + end if; +end; +/ + +prompt +prompt 插入数据到eoda.parent 和 eoda.child +begin + insert into eoda.parent values ( 1 ); + insert into eoda.child values ( 1 ); +end; +/ + +prompt +prompt 跟新表eoda.parent +begin + update eoda.parent set pk = 2; +exception + when others then + dbms_output.put_line ( 'Error!!!' || sqlerrm ); + rollback; +end; +/ + +begin + dbms_output.put_line ( '设置deferrable选项' ); +end; +/ + +set constraint eoda.child_fk_parent deferred; + +prompt +prompt 跟新表eoda.parent +begin + update eoda.parent set pk = 2; +exception + when others then + dbms_output.put_line ( 'Error!!!' || sqlerrm ); + rollback; +end; +/ + +prompt +prompt 插入eoda.child +begin + update eoda.child set pk = 2; +exception + when others then + dbms_output.put_line ( 'Error!!!' || sqlerrm ); + rollback; +end; +/ + +set constraint eoda.child_fk_parent immediate; diff --git a/oracle/oracle编程艺术/chapt8/error_log.sql b/oracle/oracle编程艺术/chapt8/error_log.sql new file mode 100644 index 0000000..33d922b --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/error_log.sql @@ -0,0 +1,87 @@ +prompt +prompt 创建表eoda.error_log +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 'error_log' ); + if num = 1 then + execute immediate 'drop table eoda.error_log'; + end if; + execute immediate ' + create table eoda.error_log + ( + ts timestamp, + err1 clob, + err2 clob + ) + '; +end; +/ + +prompt +prompt 创建存储过程eoda.log_error +create or replace procedure eoda.log_error +( + p_err1 in varchar2 , + p_err2 in varchar2 +) +as + pragma autonomous_transaction; +begin + insert into eoda.error_log ( ts,err1,err2 )values ( systimestamp,p_err1,p_err2 ); + commit; +end; +/ + +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper ( 't' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t ( x int check( x>0 ) ) + '; +end; +/ + +prompt +prompt 创建存储过程eoda.p1 +create or replace procedure eoda.p1 ( p_n in number ) +as +begin + -- some code here + insert into eoda.t values ( p_n ); +end; +/ + +prompt +prompt 创建存储过程eoda.p2 +create or replace procedure eoda.p2 ( p_n in number ) +as +begin + -- code + -- code + eoda.p1( p_n ); +end; +/ + +prompt +prompt 执行eoda.p1和eoda.p2 +begin + eoda.p2 (1); + eoda.p2 (2); + eoda.p2 (-1); + rollback; +exception + when others then + eoda.log_error( sqlerrm,dbms_utility.format_error_backtrace ); + RAISE; + -- 使用RAISE会报错,故意为之 +end; +/ + +select * from eoda.error_log; diff --git a/oracle/oracle编程艺术/chapt8/index.sql b/oracle/oracle编程艺术/chapt8/index.sql new file mode 100644 index 0000000..08e3ff2 --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/index.sql @@ -0,0 +1,80 @@ +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 't' ) and owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + ( + x int constraint x_not_null not null deferrable, + y int constraint y_not_null not null, + z varchar2(30) + ) + '; +end; +/ + +prompt +prompt 插入数据到eoda.t +begin + insert into eoda.t( x,y,z ) select rownum,rownum,rpad( 'x',30,'x' ) from all_users; + commit; +end; +/ +prompt +prompt 收集数据 +begin + dbms_stats.gather_table_stats ( user,'T' ); +end; +/ + +prompt +prompt 创建索引eoda.t_index在edoa.t(y) +declare + num number; +begin + select count(1) into num from user_indexes where index_name = upper( 't_index' ) and table_name = upper( 't' ) and table_owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop index eoda.t_index'; + end if; + execute immediate ' + create index eoda.t_index on eoda.t(y) + '; +end; +/ + +explain plan for select count(*) from eoda.t; +select * from table(dbms_xplan.display( null,null,'BASIC' )); + +prompt +prompt 创建索引eoda.t_index在edoa.t(x) +declare + num number; +begin + select count(1) into num from user_indexes where index_name = upper( 't_index' ) and table_name = upper( 't' ) and table_owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop index eoda.t_index'; + end if; + execute immediate ' + create index eoda.t_index on eoda.t(x) + '; +end; +/ + +explain plan for select count(*) from eoda.t; +select * from table(dbms_xplan.display( null,null,'BASIC' )); + +prompt +prompt 修改eoda.t中x列的约束是不可延迟约束x_not_null +begin + alter table eoda.t drop constraint x_not_null; + alter table eoda.t modify x constraint x_not_null not null; +end; +/ + +explain plan for select count(*) from eoda.t; +select * from table(dbms_xplan.display( null,null,'BASIC' )); diff --git a/oracle/oracle编程艺术/chapt8/loop_commit.sql b/oracle/oracle编程艺术/chapt8/loop_commit.sql new file mode 100644 index 0000000..040e4bf --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/loop_commit.sql @@ -0,0 +1,68 @@ + +prompt +prompt 创建数据库表eoda.t +declare + num number; +begin + select count(1) into num from user_tables where table_name = upper( 't' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t as select * from all_objects + '; + dbms_stats.gather_table_stats( user, 'T' ); +end; +/ + +/** + * 方法1要比方法二快,具体执行要看电脑性能和oracle配置. + **/ +prompt +prompt update表eoda.t +variable n number +begin + dbms_output.put_line ( 'method one' ); + :n := dbms_utility.get_cpu_time; + update eoda.t set object_name = lower(object_name); + commit; + dbms_output.put_line ( (dbms_utility.get_cpu_time - :n) || ' cpu hsesc...'); + dbms_output.put_line ( 'method two' ); + :n := dbms_utility.get_cpu_time; + for x in ( select rowid rid,object_name,rownum r from eoda.t ) + loop + update eoda.t set object_name = lower(object_name) where rowid = x.rid; + if ( mod( x.r,100 ) = 0 ) then + commit; + end if; + end loop; + commit; + dbms_output.put_line ( (dbms_utility.get_cpu_time - :n) || ' cpu hsesc...'); + /** // 下面部分代码报错,具体原因未知 + dbms_output.put_line ( 'method three' ); + :n := dbms_utility.get_cpu_time; + declare + type ridArray is table of rowid; + type vcArray is table of eoda.t.object_name%type; + + l_rids ridArray; + l_names vcArray; + cursor c is select rowid,object_name,rownum from eoda.t; + begin + open c; + loop + fetch c bulk collect into l_rids,l_names limit 100; + forall i in l_rids.count + update eoda.t + set object_name = lower( l_names(i) ) + where rowid = l_rids(i); + commit; + exit when c%notfound; + end loop; + close c; + end; + dbms_output.put_line ( (dbms_utility.get_cpu_time - :n) || ' cpu hsesc...'); + **/ +end; +/ + diff --git a/oracle/oracle编程艺术/chapt8/proc_atom.sql b/oracle/oracle编程艺术/chapt8/proc_atom.sql new file mode 100644 index 0000000..fb90a2a --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/proc_atom.sql @@ -0,0 +1,53 @@ +prompt +prompt 创建存储过程eoda.p +create or replace procedure eoda.p +as +begin + insert into eoda.t values (1); + insert into eoda.t values (-1); +end; +/ + +prompt +prompt 插入数据到eoda.t +begin + delete from eoda.t; + update eoda.t2 set cnt = 0; + commit; +end; +/ + +select * from eoda.t; +select * from eoda.t2; + +prompt +prompt 执行存储过程eoda.p +begin + begin + p; + exception + when others then + dbms_output.put_line( 'Error!!!' || sqlerrm ); + end; +end; +/ + +select * from eoda.t; +select * from eoda.t2; + +prompt +prompt 执行存储过程eoda.p,使用savepoint +begin + begin + savepoint sp; + p; + exception + when others then + rollback to sp; + dbms_output.put_line( 'Error!!!' || sqlerrm ); + end; +end; +/ + +select * from eoda.t; +select * from eoda.t2; diff --git a/oracle/oracle编程艺术/chapt8/slow_by_slow.sql b/oracle/oracle编程艺术/chapt8/slow_by_slow.sql new file mode 100644 index 0000000..6d88d04 --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/slow_by_slow.sql @@ -0,0 +1,60 @@ +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper ( 't' ) and owner = upper ( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * + from all_objects + where 1=0 + '; +end; +/ + +prompt +prompt 创建存储过程eoda.p1 +create or replace procedure eoda.p1 +as +begin + for x in ( select * from all_objects ) + loop + insert into eoda.t values x; + commit; + end loop; +end; +/ + +prompt +prompt 创建存储过程eoda.p2 +create or replace procedure eoda.p2 +as +begin + for x in ( select * from all_objects ) + loop + insert into t values x; + commit write nowait; + end loop; +end; +/ + +prompt +prompt 执行eoda.p1 +begin + execute immediate 'truncate table eoda.t'; + eoda.p1; +end; +/ + +prompt +prompt 执行eoda.p2 +begin + execute immediate 'truncate table eoda.t'; + eoda.p2; +end; +/ diff --git a/oracle/oracle编程艺术/chapt8/sql_atom.sql b/oracle/oracle编程艺术/chapt8/sql_atom.sql new file mode 100644 index 0000000..1dfc061 --- /dev/null +++ b/oracle/oracle编程艺术/chapt8/sql_atom.sql @@ -0,0 +1,85 @@ +prompt +prompt 创建表eoda.t2 +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 't2' ) and owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.t2'; + end if; + execute immediate ' + create table eoda.t2 + ( + cnt int + ) + '; +end; +/ + +prompt +prompt 插入数据到eoda.t2 +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 't2' ) and owner = upper( 'eoda' ); + if num = 1 then + insert into eoda.t2 values (0); + commit; + end if; +end; +/ + +prompt +prompt 创建表eoda.t +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper( 't' ) and owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + ( + x int check( x > 0 ) + ) + '; +end; +/ + +prompt +prompt 创建触发器eoda.t_trigger +declare + num number; +begin + select count(1) into num from user_triggers where trigger_name = upper( 't_trigger' ) and table_owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop tigger eoda.t_trigger'; + end if; + execute immediate ' + create trigger eoda.t_trigger + before insert or delete on eoda.t for each row + begin + if ( inserting ) then + update eoda.t2 set cnt = cnt + 1; + else + update eoda.t2 set cnt = cnt - 1; + end if; + dbms_output.put_line( ''I fired and updated'' || sql%rowcount || '' rows'' ); + end; + '; +end; +/ + +prompt +prompt 插入数据到eoda.t +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper ( 't' ) and owner = upper ( 'eoda' ); + if num = 1 then + insert into eoda.t values (1); + commit; + end if; +end; +/ diff --git a/oracle/oracle编程艺术/chapt9/blockcleanout.sql b/oracle/oracle编程艺术/chapt9/blockcleanout.sql new file mode 100644 index 0000000..6f6429d --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/blockcleanout.sql @@ -0,0 +1,60 @@ + +/** + + + **/ +prompt +prompt 'create table eoda.t ' +declare row_count number; +begin + select 1 into row_count from dual where exists (select 1 from user_tables where table_name = upper('t') ); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + ( + id number primary key, + x char(2000), + y char(2000), + z char(2000) + ) + '; +end; +/ + +prompt +prompt ' insert data into eoda.t' +begin + dbms_stats.set_table_stats( user,'T',numrows=>10000,numblks=>10000 ); + insert into eoda.t select rownum,'x','y','z' from all_objects where rownum <= 10000; +end; +/ + +variable redo number; +prompt +prompt 'select data 10000 times' +declare l_rec t%rowtype; +begin + :redo := get_stat_val('redo size'); + for i in 1 .. 10000 + loop + select * into l_rec from eoda.t where id=i; + end loop; + dbms_output.put_line ( (get_stat_val('redo size')-:redo) || ' byties of redo generated...' ); +end; +/ + +variable redo number; +prompt +prompt 'select data 10000 times, second' +declare l_rec t%rowtype; +begin + :redo := get_stat_val('redo size'); + for i in 1 .. 10000 + loop + select * into l_rec from eoda.t where id=i; + end loop; + dbms_output.put_line ( (get_stat_val('redo size')-:redo) || ' byties of redo generated...' ); +end; +/ diff --git a/oracle/oracle编程艺术/chapt9/get_stat_val.sql b/oracle/oracle编程艺术/chapt9/get_stat_val.sql new file mode 100644 index 0000000..282c731 --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/get_stat_val.sql @@ -0,0 +1,82 @@ + +prompt +prompt 'create function eoda.get_stat_val' +create or replace function eoda.get_stat_val (p_name in varchar2 ) return number +as + l_val number; +begin + select b.value + into l_val + from v$statname a,v$mystat b + where a.statistic# = b.statistic# + and a.name = p_name; + return l_val; +end; +/ + +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * + from big_table + where 1 = 0 + '; +end; +/ + +prompt +prompt 'test commit' +declare + l_redo number; + l_cpu number; + l_ela number; +begin + dbms_output.put_line ( '-' || ' Rows' || ' Redo' || ' CPU' || ' Elapsed' ); + for i in 1 .. 6 + loop + l_redo := get_stat_val ( 'redo size' ); + insert into eoda.t select * from big_table where rownum <= power(10,i); + l_cpu := dbms_utility.get_cpu_time; + l_ela := dbms_utility.get_time; + commit work write wait; + dbms_output.put_line( '-' || + to_char( power(10,i),'9,999,999' ) || + to_char( (get_stat_val('redo size') - l_redo ), '999,999,999' ) || + to_char( (dbms_utility.get_cpu_time - l_cpu),'999,999' ) || + to_char( (dbms_utility.get_time - l_ela),'999,999' )); + end loop; +end; +/ + +prompt +prompt 'test rollback' +declare + l_redo number; + l_cpu number; + l_ela number; +begin + dbms_output.put_line ( '-' || ' Rows' || ' Redo' || ' CPU' || ' Elapsed' ); + for i in 1 .. 6 + loop + l_redo := get_stat_val ( 'redo size' ); + insert into eoda.t select * from big_table where rownum <= power(10,i); + l_cpu := dbms_utility.get_cpu_time; + l_ela := dbms_utility.get_time; + -- commit work write wait; + rollback; + dbms_output.put_line( '-' || + to_char( power(10,i),'9,999,999' ) || + to_char( (get_stat_val('redo size') - l_redo ), '999,999,999' ) || + to_char( (dbms_utility.get_cpu_time - l_cpu),'999,999' ) || + to_char( (dbms_utility.get_time - l_ela),'999,999' )); + end loop; +end; +/ diff --git a/oracle/oracle编程艺术/chapt9/temp_table_redo_and_undo.sql b/oracle/oracle编程艺术/chapt9/temp_table_redo_and_undo.sql new file mode 100644 index 0000000..07d53cb --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/temp_table_redo_and_undo.sql @@ -0,0 +1,127 @@ + +prompt +prompt 'create table perm and temp' +declare + row_count number; + row_count_temp number; +begin + select count(1) into row_count from dual where exists (select 1 from user_tables where table_name = upper('perm')); + select count(1) into row_count_temp from dual where exists (select 1 from user_tables where table_name = upper('temp')); + if row_count = 1 then + execute immediate 'drop table perm'; + end if; + if row_count_temp = 1 then + execute immediate 'drop table temp'; + end if; + execute immediate ' + create table perm + ( + x char(2000), + y char(2000), + z char(2000) + ) + '; + execute immediate ' + create global temporary table temp + ( + x char(2000), + y char(2000), + z char(2000) + ) + on commit preserve rows + '; +end; +/ + +prompt +prompt 'create procedure do_sql' +create or replace procedure eoda.do_sql(p_sql in varchar2) +as + l_start_redo number; + l_redo number; +begin + l_start_redo := get_stat_val('redo size'); + execute immediate p_sql; + commit; + l_redo := get_stat_val('redo size') - l_start_redo; + dbms_output.put_line( to_char(l_redo,'99,999,999') || ' byties of redo generated for "' || + substr( replace( p_sql,chr(10),' ' ),1,25 ) || '"...'); +end; +/ + +prompt +prompt 'deal with perm and temp' +begin + do_sql( 'insert into perm + select 1,1,1 + from all_objects + where rownum <= 500' ); + + do_sql( 'insert into temp + select 1,1,1 + from all_objects + where rownum <= 500' ); + dbms_output.new_line; + + do_sql( 'update perm set x = 2' ); + do_sql( 'update temp set x = 2' ); + + do_sql( 'delete from perm' ); + do_sql( 'delete from temp' ); +end; +/ + +prompt +prompt 'create idnex on perm and temp' +declare + perm_row_count number; + temp_row_count number; +begin +-- select 'alter system kill session '''||sid||','||serial#||'''' +-- from v$session +-- where sid in ( +-- select sid +-- from v$lock +-- where id1 in ( +-- select object_id +-- from dba_objects +-- where object_name in ( +-- select table_name +-- from dba_tables +-- where owner='EODA') +-- ) +-- ); +-- commit; + select count(1) into perm_row_count from dual where exists (select 1 from user_indexes where table_name = upper('perm') and index_name = upper('perm_idx') ); + select count(1) into temp_row_count from dual where exists (select 1 from user_indexes where table_name = upper('temp') and index_name = upper('temp_idx') ); + if perm_row_count = 0 then + execute immediate 'create index perm_idx on perm(x)'; + end if; + -- 执行下面语句可能会报错 ORA-14452: attempt to create, alter or drop an index on temporary table already in use ,此时就需要将下面代码注释掉,并单独执行 + --if temp_row_count = 0 then + -- execute immediate 'create index temp_idx on temp(x)'; + --end if; +end; +/ + +prompt +prompt 'deal with perm and temp' +begin + do_sql( 'insert into perm + select 1,1,1 + from all_objects + where rownum <= 500' ); + + do_sql( 'insert into temp + select 1,1,1 + from all_objects + where rownum <= 500' ); + dbms_output.new_line; + + do_sql( 'update perm set x = 2' ); + do_sql( 'update temp set x = 2' ); + + do_sql( 'delete from perm' ); + do_sql( 'delete from temp' ); +end; +/ diff --git a/oracle/oracle编程艺术/chapt9/test_redo.sql b/oracle/oracle编程艺术/chapt9/test_redo.sql new file mode 100644 index 0000000..92f90e9 --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/test_redo.sql @@ -0,0 +1,63 @@ + +prompt +prompt 'create table eoda.t' +declare row_count number; +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * from eoda.big_table where 1=0 + '; +end; +/ + +set autotrace traceonly statistics; +insert into eoda.t select * from eoda.big_table; +commit; +truncate table eoda.t; +insert /*+ APPEND */ into eoda.t select * from eoda.big_table; +commit; +set autotrace off; + +-- variable 放在prompt里面会报错 +variable redo number; +prompt +prompt 'logging' +declare row_count number; +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + :redo := get_stat_val('redo size'); + execute immediate ' + create table eoda.t + as + select * from all_objects + '; + dbms_output.put_line( (get_stat_val('redo size') - :redo) || ' bytes of redo generated' ); +end; +/ + +prompt +prompt 'nologging' +declare row_count number; +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + :redo := get_stat_val('redo size'); + execute immediate ' + create table eoda.t + NOLOGGING + as + select * from all_objects + '; + dbms_output.put_line( (get_stat_val('redo size') - :redo) || ' bytes of redo generated' ); +end; +/ diff --git a/oracle/oracle编程艺术/chapt9/undo_and_redo.sql b/oracle/oracle编程艺术/chapt9/undo_and_redo.sql new file mode 100644 index 0000000..7a8757d --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/undo_and_redo.sql @@ -0,0 +1,36 @@ + +prompt +prompt 'create table eoda.t' +declare row_count number(5); +begin + select count(1) into row_count from user_tables where table_name = upper('t'); + if row_count = 1 then + execute immediate 'drop table eoda.t'; + end if; + execute immediate ' + create table eoda.t + as + select * + from all_objects + where 1 = 0 + '; +end; +/ + +select * from eoda.t; +set autotrace traceonly statistics +select * from eoda.t; + +prompt +prompt 'insert data into eoda.t and rollback' +begin + insert into eoda.t select * from all_objects; + rollback; +end; +/ + +select * from eoda.t; +set autotrace traceonly statistics +select * from eoda.t; + + diff --git a/oracle/oracle编程艺术/chapt9/undo_small.sql b/oracle/oracle编程艺术/chapt9/undo_small.sql new file mode 100644 index 0000000..0d7db2f --- /dev/null +++ b/oracle/oracle编程艺术/chapt9/undo_small.sql @@ -0,0 +1,41 @@ + +-- 原来undo段的名称:UNDOTBS1 + +prompt +prompt 'create tablespace undo_small ' +declare row_count number; +begin + select count(1) into row_count from dual where exists( select 1 from dba_tablespaces where tablespace_name = upper('undo_small')); + if row_count = 0 then + execute immediate ' + create undo tablespace undo_small + datafile ''/tmp/undo.dbf'' size 2m + autoextend off + '; + end if; +end; +/ + +alter system set undo_tablespace = 'undo_small'; + +prompt +prompt 'create table t' +declare row_count number; +begin + select count(1) into row_count from dual where exists (select 1 from user_tables where table_name = upper('t')); + if row_count = 1 then + execute immediate 'drop table t'; + end if; + execute immediate ' + create table t + as + select * + from all_objects + order by dbms_random.random + '; + commit; + dbms_stats.gather_table_stats( user,'T',cascade=>true ); +end; +/ + +alter system set undo_tablespace = 'UNDOTBS1'; diff --git a/oracle/oracle编程艺术/pre/READMD.md b/oracle/oracle编程艺术/pre/READMD.md new file mode 100644 index 0000000..e69de29 diff --git a/oracle/oracle编程艺术/pre/big_table.sql b/oracle/oracle编程艺术/pre/big_table.sql new file mode 100644 index 0000000..796b955 --- /dev/null +++ b/oracle/oracle编程艺术/pre/big_table.sql @@ -0,0 +1,101 @@ +-- 创建eoda.big_table表 +prompt +prompt 创建表eoda.big_table +declare + num number; +begin + select count(1) into num from all_tables where table_name = upper ( 'big_table' ) and owner = upper( 'eoda' ); + if num = 1 then + execute immediate 'drop table eoda.big_table'; + end if; + + execute immediate ' + create table eoda.big_table + as + select + rownum ID, + OWNER, + OBJECT_NAME, + SUBOBJECT_NAME, + OBJECT_ID, + DATA_OBJECT_ID, + OBJECT_TYPE, + CREATED, + LAST_DDL_TIME, + TIMESTAMP, + STATUS, + TEMPORARY, + GENERATED, + SECONDARY, + NAMESPACE, + EDITION_NAME + from + all_objects + where + 1 = 0 + '; +end; +/ +alter table big_table nologging; +declare + l_cnt number; + l_rows number := &numrows; +begin + insert /*+ append */ + into big_table + select + rownum ID, + OWNER, + OBJECT_NAME, + SUBOBJECT_NAME, + OBJECT_ID, + DATA_OBJECT_ID, + OBJECT_TYPE, + CREATED, + LAST_DDL_TIME, + TIMESTAMP, + STATUS, + TEMPORARY, + GENERATED, + SECONDARY, + NAMESPACE, + EDITION_NAME + from + all_objects + where rownum <= &numrows; + -- + l_cnt := sql%rowcount; + commit; + while (l_cnt < l_rows ) + loop + insert /*+ append */ + into big_table + select + rownum ID, + OWNER, + OBJECT_NAME, + SUBOBJECT_NAME, + OBJECT_ID, + DATA_OBJECT_ID, + OBJECT_TYPE, + CREATED, + LAST_DDL_TIME, + TIMESTAMP, + STATUS, + TEMPORARY, + GENERATED, + SECONDARY, + NAMESPACE, + EDITION_NAME + from + big_table a + where rownum <= l_rows - l_cnt; + l_cnt := l_cnt + sql%rowcount; + commit; + end loop; +end; +/ + +alter table big_table add constraint big_table_pk primary key(ID); + +exec dbms_stats.gather_table_stats(user,'BIG_TABLE'); diff --git a/oracle/oracle编程艺术/pre/eoda_create.sql b/oracle/oracle编程艺术/pre/eoda_create.sql new file mode 100644 index 0000000..2135f6d --- /dev/null +++ b/oracle/oracle编程艺术/pre/eoda_create.sql @@ -0,0 +1,17 @@ +-- 此脚本只有在oracle 用户模式下执行 +-- 并且此脚本不能重复执行,以后可以考虑支持一下 +connect / as sysdba +-- 定义变量 +define username=eoda +define usernamepwd=foo +-- 创建用户 +create user &&username identified by &&usernamepwd ; +-- 赋予相关权限 +grant dba to eoda; +grant execute on dbms_stats to &&username; +grant select on V_$STATNAME to &&username; +grant select on V_$MYSTAT to &&username; +grant select on V_$LATCH to &&username; +grant select on V_$TIMER to &&username; +-- 连接用户 +conn &&username/&&usernamepwd diff --git a/oracle/oracle编程艺术/pre/login.sql b/oracle/oracle编程艺术/pre/login.sql new file mode 100644 index 0000000..ba4060c --- /dev/null +++ b/oracle/oracle编程艺术/pre/login.sql @@ -0,0 +1,22 @@ +-- 使用方法:将本脚本里面的内容粘贴到$ORACLE_HOME/sqlplus/admin/glogin.sql 文件里面酒醒了 + +-- 设置sqlplus 默认的编辑器,本人经常使用vim,所以就设置了vim,不过vim没有经过配置,不怎么好使 +define _editor=vi +-- 默认打开DBMS_OUTPUT +set serveroutput on size 1000000 +-- 这条命令会去除文本两端的空格 +set trimspool on +-- 设置选择LONG和CLOB列时显示的默认字节数 +set long 5000 +-- 设置sqlplus显示的文本宽度为100字符 +set linesize 190 +-- 设置自动显示执行计划 +set autotrace on +-- 显示执行时间 +set timing on +-- 设置sqlplus多久打印一次标题 +set pagesize 9999 +-- 设置AUTOTRACE输出的执行计划默认宽度,a80通常足以放下整个执行计划 +column plan_plus_exp format a80 +-- 用户名@实例名> 例如: EODA@ORAL> +set sqlprompt '&_user.@&_connect_identifier.> ' diff --git a/oracle/oracle编程艺术/pre/mystat.sql b/oracle/oracle编程艺术/pre/mystat.sql new file mode 100644 index 0000000..a74c16e --- /dev/null +++ b/oracle/oracle编程艺术/pre/mystat.sql @@ -0,0 +1,10 @@ +-- 在完成某些操作之前和之后的变化情况 + +set echo off +set verify off +column value new_val V +define S="&1" +set autotrace off +select a.name,b.value from v$statname a,v$mystat b where a.statistic# = b.statistic# and lower(a.name) = lower('&S') +/ +set echo off diff --git a/oracle/oracle编程艺术/pre/mystat2.sql b/oracle/oracle编程艺术/pre/mystat2.sql new file mode 100644 index 0000000..c646ddc --- /dev/null +++ b/oracle/oracle编程艺术/pre/mystat2.sql @@ -0,0 +1,15 @@ +-- 用于报告差值 + +set echo off +set verify off +select + a.name, + b.value V, + to_char(b.value-&V,'999,999,999,999') diff +from + v$statname a,v$mystat b +where + a.statistic# = b.statistic# and + lower(a.name) = lower('&S'); +/ +set echo on diff --git a/oracle/oracle编程艺术/pre/runstats.sql b/oracle/oracle编程艺术/pre/runstats.sql new file mode 100644 index 0000000..6c5ead9 --- /dev/null +++ b/oracle/oracle编程艺术/pre/runstats.sql @@ -0,0 +1,23 @@ +-- +prompt +prompt 创建收集信息的视图stats +create or replace VIEW stats +as +select 'STAT...' || a.name name ,b.value +from v$statname a,v$mystat b +where a.statistic# = b.statistic# +union all +select 'LATCH.' || name,gets +from v$latch +union all +select 'STAT...Elapsed Time',hsecs from v$timer; +/ +-- 创建小表来收集信息 +prompt +prompt 创建小表run_stats收集信息 +create global temporary table run_stats( + runid varchar2(15), + name varchar2(80), + value int + )on commit preserve rows; +/ diff --git a/oracle/oracle编程艺术/pre/runstats_pkg.sql b/oracle/oracle编程艺术/pre/runstats_pkg.sql new file mode 100644 index 0000000..a6fe04b --- /dev/null +++ b/oracle/oracle编程艺术/pre/runstats_pkg.sql @@ -0,0 +1,12 @@ + +-- 创建runstats包 +prompt +prompt 创建runstats包 +create or replace package runstats_pkg +as + procedure rs_start; + procedure rs_middle; + procedure rs_stop(p_difference_threshold in number default 0); +end; +/ + diff --git a/oracle/oracle编程艺术/pre/runstats_pkg_body.sql b/oracle/oracle编程艺术/pre/runstats_pkg_body.sql new file mode 100644 index 0000000..5fb466f --- /dev/null +++ b/oracle/oracle编程艺术/pre/runstats_pkg_body.sql @@ -0,0 +1,93 @@ +prompt +prompt 创建runstats_pkg body +create or replace package body runstats_pkg +as +g_start number; +g_run1 number; +g_run2 number; + +procedure rs_start +is +begin + delete from run_stats; + + insert into run_stats + select 'before',stats.* from stats; + g_start := dbms_utility.get_cpu_time; +end; + +procedure rs_middle +is +begin + g_run1 := (dbms_utility.get_cpu_time-g_start); + + insert into run_stats + select 'after 1',stats.* from stats; + + g_start := dbms_utility.get_cpu_time; +end; + +procedure rs_stop(p_difference_threshold in number default 0) +is +begin + g_run2 := (dbms_utility.get_cpu_time-g_start); + + dbms_output.put_line('Run1 ran in ' || g_run1 || 'cpu hsecs'); + dbms_output.put_line('Run2 ran in ' || g_run2 || 'cpu hsecs'); + + if (g_run2 <> 0) + then + dbms_output.put_line('run 1 ran in ' || round(g_run1/g_run2*100,2) || '% of the time '); + end if; + + dbms_output.put_line(chr(9)); + insert into run_stats select 'after 2',stats.* from stats; + + dbms_output.put_line(rpad('Name',30) || lpad('Run1',16) || lpad('Run2',16) || lpad('Diff',16)); + + for x in ( + select rpad(a.name,30) || + to_char(b.value-a.value,'999,999,999,999') || + to_char(c.value-b.value,'999,999,999,999') || + to_char((c.value-b.value)-(b.value-a.value),'999,999,999,999') data + from run_stats a,run_stats b,run_stats c + where a.name = b.name and + b.name = c.name and + a.runid = 'before' and + b.runid = 'after 1'and + c.runid = 'afer 2'and + abs((c.value-b.value) - (b.value-a.value)) > p_difference_threshold + order by abs((c.value-b.value) - (b.value-a.value)) + ) + loop + dbms_output.put_line(x.data); + end loop; + + dbms_output.put_line(chr(9)); + dbms_output.put_line('Run1 latches total versus runs -- difference and pct'); + dbms_output.put_line(lpad('Run1',14) || lpad('Run2',19) || lpad('Diff',18) || lpad('Pct',11)); + + for x in ( + select to_char(run1,'9,999,999,999,999') || + to_char(run2,'9,999,999,999,999') || + to_char(diff,'9,999,999,999,999') || + to_char( round( run1/decode( run2,0,to_number(0),run2) *100,2 ),'99,999,99' ) || + '%' data + from (select sum(b.value-a.value) run1, + sum(c.value-b.value) run2, + sum( (c.value-b.value)-(b.value-a.value) ) diff + from run_stats a,run_stats b,run_stats c + where a.name = b.name and + b.name = c.name and + a.runid = 'before' and + b.runid = 'after 1'and + c.runid = 'afer 2'and + a.name like 'LATCH%' + ) + ) + loop + dbms_output.put_line(x.data); + end loop; +end; +end; +/ diff --git a/oracle/oracle编程艺术/pre/scott_dept.sql b/oracle/oracle编程艺术/pre/scott_dept.sql new file mode 100644 index 0000000..7047823 --- /dev/null +++ b/oracle/oracle编程艺术/pre/scott_dept.sql @@ -0,0 +1,44 @@ +-------------------------------------------------------- +-- File created - Thursday-February-01-2018 +-------------------------------------------------------- +-------------------------------------------------------- +-- DDL for Table DEPT +-------------------------------------------------------- + + CREATE TABLE "SCOTT"."DEPT" + ( "DEPTNO" NUMBER(2,0), + "DNAME" VARCHAR2(14 BYTE), + "LOC" VARCHAR2(13 BYTE) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 + NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ; +REM INSERTING into SCOTT.DEPT +SET DEFINE OFF; +Insert into SCOTT.DEPT (DEPTNO,DNAME,LOC) values (10,'ACCOUNTING','NEW YORK'); +Insert into SCOTT.DEPT (DEPTNO,DNAME,LOC) values (20,'RESEARCH','DALLAS'); +Insert into SCOTT.DEPT (DEPTNO,DNAME,LOC) values (30,'SALES','CHICAGO'); +Insert into SCOTT.DEPT (DEPTNO,DNAME,LOC) values (40,'OPERATIONS','BOSTON'); +-------------------------------------------------------- +-- DDL for Index PK_DEPT +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SCOTT"."PK_DEPT" ON "SCOTT"."DEPT" ("DEPTNO") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ; +-------------------------------------------------------- +-- Constraints for Table DEPT +-------------------------------------------------------- + + ALTER TABLE "SCOTT"."DEPT" ADD CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ENABLE; diff --git a/oracle/oracle编程艺术/pre/scott_emp.sql b/oracle/oracle编程艺术/pre/scott_emp.sql new file mode 100644 index 0000000..1361ad6 --- /dev/null +++ b/oracle/oracle编程艺术/pre/scott_emp.sql @@ -0,0 +1,59 @@ +-------------------------------------------------------- +-- File created - Tuesday-January-30-2018 +-------------------------------------------------------- +-------------------------------------------------------- +-- DDL for Table EMP +-------------------------------------------------------- + + CREATE TABLE "SCOTT"."EMP" + ( "EMPNO" NUMBER(4,0), + "ENAME" VARCHAR2(10 BYTE), + "JOB" VARCHAR2(9 BYTE), + "MGR" NUMBER(4,0), + "HIREDATE" DATE, + "SAL" NUMBER(7,2), + "COMM" NUMBER(7,2), + "DEPTNO" NUMBER(2,0) + ) SEGMENT CREATION IMMEDIATE + PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 + NOCOMPRESS LOGGING + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ; +REM INSERTING into SCOTT.EMP +SET DEFINE OFF; +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7369,'SMITH','CLERK',7902,to_date('17-DEC-80','DD-MON-RR'),800,null,20); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7499,'ALLEN','SALESMAN',7698,to_date('20-FEB-81','DD-MON-RR'),1600,300,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7521,'WARD','SALESMAN',7698,to_date('22-FEB-81','DD-MON-RR'),1250,500,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7566,'JONES','MANAGER',7839,to_date('02-APR-81','DD-MON-RR'),2975,null,20); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7654,'MARTIN','SALESMAN',7698,to_date('28-SEP-81','DD-MON-RR'),1250,1400,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7698,'BLAKE','MANAGER',7839,to_date('01-MAY-81','DD-MON-RR'),2850,null,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7782,'CLARK','MANAGER',7839,to_date('09-JUN-81','DD-MON-RR'),2450,null,10); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7788,'SCOTT','ANALYST',7566,to_date('19-APR-87','DD-MON-RR'),3000,null,20); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7839,'KING','PRESIDENT',null,to_date('17-NOV-81','DD-MON-RR'),5000,null,10); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7844,'TURNER','SALESMAN',7698,to_date('08-SEP-81','DD-MON-RR'),1500,0,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7876,'ADAMS','CLERK',7788,to_date('23-MAY-87','DD-MON-RR'),1100,null,20); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7900,'JAMES','CLERK',7698,to_date('03-DEC-81','DD-MON-RR'),950,null,30); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7902,'FORD','ANALYST',7566,to_date('03-DEC-81','DD-MON-RR'),3000,null,20); +Insert into SCOTT.EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) values (7934,'MILLER','CLERK',7782,to_date('23-JAN-82','DD-MON-RR'),1300,null,10); +-------------------------------------------------------- +-- DDL for Index PK_EMP +-------------------------------------------------------- + + CREATE UNIQUE INDEX "SCOTT"."PK_EMP" ON "SCOTT"."EMP" ("EMPNO") + PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ; +-------------------------------------------------------- +-- Constraints for Table EMP +-------------------------------------------------------- + + ALTER TABLE "SCOTT"."EMP" ADD CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO") + USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS + STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 + PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 + BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) + TABLESPACE "USERS" ENABLE; diff --git a/oracle/oracle编程艺术/pre/scott用户.md b/oracle/oracle编程艺术/pre/scott用户.md new file mode 100644 index 0000000..a5c1f09 --- /dev/null +++ b/oracle/oracle编程艺术/pre/scott用户.md @@ -0,0 +1,24 @@ +## scott 相关问题 +1. scott不存在,执行`$ORACLE_HOME/rdbms/admin/utlsampl.sql` +```sql +@$ORACLE_HOME/rdbms/admin/utlsampl.sql +``` +2. `connect scott/tiger`时报错 +```sql +SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled +SP2-0611: Error enabling STATISTICS report +``` +解决方案: +```sql +@$ORACLE_HOME/sqlplus/admin/plustrce.sql +grant plustrace to scott; +``` +3. 报错信息 +```sql +ORA-01039: insufficient privileges on underlying objects of the view +SP2-0612: Error generating AUTOTRACE EXPLAIN report +``` +解决方案: +```sql +grant select any dictionary to scott; +``` diff --git a/oracle/oracle编程艺术/pre/show_space.sql b/oracle/oracle编程艺术/pre/show_space.sql new file mode 100644 index 0000000..2c2a808 --- /dev/null +++ b/oracle/oracle编程艺术/pre/show_space.sql @@ -0,0 +1,140 @@ +-- 用于打印数据库段的空间利用率信息 +-- +-- P_SEGNAME:段名(例如,表或者索引名称) +-- P_OWNER 默认为当前用户,不过也可以使用这个存储过程来查看另外某个用户 +-- P_TYPE 默认为TABLE,这个参数表示查看哪种类型的对象 +-- P_PARTITION 显示分区对象的空间时所用的分区名,SHOW_SPACE一次只显示一个分区的空间利用率 + + +-- + +-- 此脚本执行完之后可能会遇到ORA-00942: table or view does not exist 的错误,这个错误就是因为部分表没有权限的缘故 + +create or replace procedure show_space +( + p_segname in varchar2, + p_owner in varchar2 default user, + p_type in varchar2 default 'TABLE', + p_partition in varchar2 default NULL +) +as + l_free_blks number; + l_total_blocks number; + l_total_bytes number; + l_unused_blocks number; + l_unused_bytes number; + l_LastUsedExtFileId number; + l_LastUsedExtBlockId number; + l_LAST_USED_BLOCK number; + l_segment_space_mgmt varchar2(255); + l_unformatted_blocks number; + l_unformatted_bytes number; + l_fs1_blocks number; + l_fs1_bytes number; + l_fs2_blocks number; + l_fs2_bytes number; + l_fs3_blocks number; + l_fs3_bytes number; + l_fs4_blocks number; + l_fs4_bytes number; + l_full_blocks number; + l_full_bytes number; + + -- 内部存储过程,用于格式化数字 + -- + procedure p(p_label in varchar2,p_num in number) + is + begin + dbms_output.put_line( rpad(p_label,40,'.') || to_char(p_num,'999,999,999,999') ); + end; + +begin + begin + execute immediate + -- 此部分执行出现表不存在的错误时可以是因为没有权限造成的,赋予select权限即可 + 'select + ts.segment_space_management + from + dba_segments seg,dba_tablespaces ts + where + seg.segment_name = :p_segname and + (:p_partition is null or seg.partition_name = :p_partition) and + seg.owner = :p_owner and + seg.tablespace_name = ts.tablespace_name ' + into l_segment_space_mgmt + using p_segname,p_partition,p_partition,p_owner; + exception + when too_many_rows then + dbms_output.put_line( 'This must be a partitiond table,use p_partition =>' ); + return; + -- 解决没有数据时报错的问题 + WHEN NO_DATA_FOUND THEN + dbms_output.put_line( 'no data found =>' ); + return; + end; + + -- api + + if l_segment_space_mgmt = 'AUTO' then + dbms_space.space_usage + ( + p_owner, + p_segname, + p_type, + l_unformatted_blocks, + l_unformatted_bytes, + l_fs1_blocks, + l_fs1_bytes, + l_fs2_blocks, + l_fs2_bytes, + l_fs3_blocks, + l_fs3_bytes, + l_fs4_blocks, + l_fs4_bytes, + l_full_blocks, + l_full_bytes, + p_partition + ); + + p( 'Unformatted Blocks',l_unformatted_blocks ); + p( 'FS1 Blocks (0-25)',l_fs1_blocks ); + p( 'FS1 Blocks (25-50)',l_fs2_blocks ); + p( 'FS1 Blocks (50-75)',l_fs3_blocks ); + p( 'FS1 Blocks (75-100)',l_fs4_blocks ); + else + dbms_space.free_blocks + ( + segment_owner => p_owner, + segment_name => p_segname, + segment_type => p_type, + freelist_group_id => 0, + free_blks => l_free_blks + ); + p( 'Free Blocks',l_free_blks ); + end if; + + dbms_space.unused_space + ( + segment_owner => p_owner, + segment_name => p_segname, + segment_type => p_type, + partition_name => p_partition, + total_blocks => l_total_blocks, + total_bytes => l_total_bytes, + unused_blocks => l_unused_blocks, + unused_bytes => l_unused_bytes, + LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId, + LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId, + LAST_USED_BLOCK => l_LAST_USED_BLOCK + ); + + p( 'Total Blocks',l_total_blocks ); + p( 'Total Bytes',l_total_bytes ); + p( 'Total Mbytes',trunc(l_total_bytes/1024/1024) ); + p( 'Unused Blocks',l_unused_blocks ); + p( 'Unused Bytes',l_unused_bytes ); + p( 'Last Used Ext FileId',l_LastUsedExtFileId ); + p( 'Last Used Ext Blocks',l_LastUsedExtBlockId ); + p( 'Last Used Block',l_LAST_USED_BLOCK ); +end; +/ diff --git a/oracle/oracle编程艺术/pre/statspack使用教程.md b/oracle/oracle编程艺术/pre/statspack使用教程.md new file mode 100644 index 0000000..a7d2e6f --- /dev/null +++ b/oracle/oracle编程艺术/pre/statspack使用教程.md @@ -0,0 +1,8 @@ +## statspack 安装 + +1. 执行安装脚本,在`@ORACLE_HOME/rdbms/admin/`下,运行`@spcreate.sql` +2. 创建`PERFSTAT Schema` 密码 +3. `zeek` 默认表空间`SYSAUX`;`PERFSTAT` 临时表空间:`temp`; + +#### 注意: +1. 重复执行时,需要删除用户`PERFSTAT`,不然执行脚本时会报错 diff --git a/oracle/oracle编程艺术/sys_sql.md b/oracle/oracle编程艺术/sys_sql.md new file mode 100644 index 0000000..33cf089 --- /dev/null +++ b/oracle/oracle编程艺术/sys_sql.md @@ -0,0 +1,23 @@ +## 常用的查询 +1. 查询oracle中的sid +```sql +select instance_name from V$instance; +``` + +2. 查询锁定表信息 +```sql +SELECT s.sid, + s.serial#, + s.username, + s.schemaname, + s.osuser, + s.process, + s.machine, + s.terminal, + s.logon_time, + l.type + FROM v$session s, v$lock l + WHERE s.sid = l.sid + AND s.username IS NOT NULL + ORDER BY sid; +``` diff --git a/oracle/plsql/README.md b/oracle/plsql/README.md new file mode 100644 index 0000000..e69de29 diff --git a/oracle/plsql/chapt1/customers.sql b/oracle/plsql/chapt1/customers.sql new file mode 100644 index 0000000..b58dff2 --- /dev/null +++ b/oracle/plsql/chapt1/customers.sql @@ -0,0 +1,16 @@ +-- 创建customers表 + +prompt +prompt 创建customers表 +create table customers +( + pin_number number(6) +); + +/* +-- 添加主健,因为customers表只有一个子段,所以下面代码汇报错:ORA-02260: table can have only one primary key +prompt +prompt 添加主健 +alter table customers add constraint customers_pk primary key (pin_number); +/ +*/ diff --git a/oracle/plsql/chapt1/exec_gen_customer.sql b/oracle/plsql/chapt1/exec_gen_customer.sql new file mode 100644 index 0000000..3c88478 --- /dev/null +++ b/oracle/plsql/chapt1/exec_gen_customer.sql @@ -0,0 +1,8 @@ + +set timing on + +begin + gen_customer; + commit; +end; +/ diff --git a/oracle/plsql/chapt1/gen_customer.sql b/oracle/plsql/chapt1/gen_customer.sql new file mode 100644 index 0000000..9cf308f --- /dev/null +++ b/oracle/plsql/chapt1/gen_customer.sql @@ -0,0 +1,26 @@ +/** + * 产生随机数,并且将产生随机数插入到gen_customer, + * + */ + + +set echo on + +create or replace procedure gen_customer +is + v_new_cid customers.pin_number%type; +begin + loop + begin + v_new_cid := round(dbms_random.value(100000,999999)); + insert into customers values (v_new_cid); + --commit; + exit; +-- 将原来中的下面部分注释掉了,当出现报错时就会出现bug +-- exception +-- when dup_val_on_irdex then +-- null; + end; + end loop; +end; +/ diff --git a/oracle/sys/README.md b/oracle/sys/README.md new file mode 100644 index 0000000..e69de29 diff --git a/oracle/sys/dbms常用系统包详解.md b/oracle/sys/dbms常用系统包详解.md new file mode 100644 index 0000000..e50ec4a --- /dev/null +++ b/oracle/sys/dbms常用系统包详解.md @@ -0,0 +1,11 @@ +## `dbms_medadata.get_ddl` +生成数据库对象的ddl +## `dbms_stat` +用于搜集查看修改数据库对象的优化统计信息 + + +## `dbms_output` +用于输出信息 +`dbms_output.put_line( message )` + + diff --git a/oracle/sys/oracle常见系统表的用法.md b/oracle/sys/oracle常见系统表的用法.md new file mode 100644 index 0000000..e69de29 diff --git a/pics/inode1.gif b/pics/inode1.gif new file mode 100755 index 0000000..38e164d Binary files /dev/null and b/pics/inode1.gif differ diff --git a/pics/jingcheng.jpg b/pics/jingcheng.jpg new file mode 100644 index 0000000..8ae6982 Binary files /dev/null and b/pics/jingcheng.jpg differ diff --git a/pics/kernel_space.jpg b/pics/kernel_space.jpg new file mode 100644 index 0000000..73f4ca4 Binary files /dev/null and b/pics/kernel_space.jpg differ diff --git a/pics/linux1.PNG b/pics/linux1.PNG new file mode 100644 index 0000000..eef151e Binary files /dev/null and b/pics/linux1.PNG differ diff --git a/pics/linux2.png b/pics/linux2.png new file mode 100644 index 0000000..e356f94 Binary files /dev/null and b/pics/linux2.png differ diff --git a/pics/linux_duan.png b/pics/linux_duan.png new file mode 100644 index 0000000..6666d5b Binary files /dev/null and b/pics/linux_duan.png differ diff --git a/pics/linux_page.png b/pics/linux_page.png new file mode 100644 index 0000000..3c4a3c4 Binary files /dev/null and b/pics/linux_page.png differ diff --git a/pics/linux_page32.png b/pics/linux_page32.png new file mode 100644 index 0000000..a3feaab Binary files /dev/null and b/pics/linux_page32.png differ diff --git a/pics/user_space.jpg b/pics/user_space.jpg new file mode 100644 index 0000000..eb22c4b Binary files /dev/null and b/pics/user_space.jpg differ diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..dcc89fc --- /dev/null +++ b/python/README.md @@ -0,0 +1,20 @@ + +# python 相关教程 + +## 简介 +不解释 + +## 基础环境搭建 +```sh +apt install "python*" +``` + +## django项目 +```shell +django-admin startproject message +python3 manage.py makemigrations +python3 manage.py migrate +python manage.py sqlmigrate app_name 0001 +python manage.py dbshell +python3 manage.py runserver 0.0.0.0:8000 +``` diff --git a/python/listTest.py b/python/listTest.py new file mode 100755 index 0000000..33e512c --- /dev/null +++ b/python/listTest.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# coding: utf-8 + +a = [1, 2, 3] +b = [4, 5, 6] +print(a) +print(b) +# 将b作为a的第四个元素 +a.append(b) +print("a.append(b):", a) +a = [1, 2, 3] +a.extend(b) +print("a.extend(b):", a) +print(a[:2]) +print(a[2:]) diff --git a/sitmap-generator.py b/sitmap-generator.py new file mode 100755 index 0000000..0fa9695 --- /dev/null +++ b/sitmap-generator.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import os +from xml.dom.minidom import Document +import time + + +html_path = '_book' +http_path = 'http://www.zeekling.cn/book/study' +site_map_name = 'study.xml' + + +def dirlist(path, all_file): + file_list = os.listdir(path) + for file_name in file_list: + file_path = os.path.join(path, file_name) + if os.path.isdir(file_path): + if str(file_path).endswith('gitbook'): + continue + all_file.append(file_path + '/') + dirlist(file_path, all_file) + else: + all_file.append(file_path) + + return all_file + + +def write_xml(url_paths): + doc = Document() + doc.encoding = 'UTF-8' + url_set = doc.createElement('urlset') + doc.appendChild(url_set) + url_set.setAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9') + date_str = time.strftime('%Y-%m-%d', time.localtime()) + for url_path in url_paths: + url = doc.createElement('url') + url_set.appendChild(url) + loc = doc.createElement('loc') + loc_value = doc.createTextNode(url_path) + loc.appendChild(loc_value) + changefreq = doc.createElement('changefreq') + freq_value = doc.createTextNode('weekly') + changefreq.appendChild(freq_value) + priority = doc.createElement('priority') + prio_value = doc.createTextNode('0.8') + priority.appendChild(prio_value) + lastmod = doc.createElement('lastmod') + mode_value = doc.createTextNode(date_str) + lastmod.appendChild(mode_value) + url.appendChild(loc) + url.appendChild(changefreq) + url.appendChild(priority) + url.appendChild(lastmod) + path = os.getcwd() + '/' + site_map_name + f = open(path, 'w') + f.write(doc.toprettyxml(indent=' ')) + f.close() + + +if __name__ == '__main__': + pwd = os.getcwd() + '/' + html_path + all_file = [] + all_file = dirlist(pwd, all_file) + all_html_file = [] + for file_name in all_file: + file_name = str(file_name) + if file_name.endswith('.html') or file_name.endswith('/'): + html_name = file_name.replace(pwd, http_path) + all_html_file.append(html_name) + + write_xml(all_html_file) +