Life

Tuesday, December 31, 2019

2019年终盘点

2019在不知不觉中走到了尽头,回首这一整年,在我身上、在我身旁、在那远方发生了那么多那么多的事情。
在这一年里,我第一次走出校园,进入社会拿着家里的”补贴“,拿着有限的实习工资度过了近三个月的实习经历;在这一年里,我第一次写出五十多页的毕业论文,最后一次站在台上向老师们汇报最后一次作业;在这一年里,我签下人生第一份劳动合同;在这一年里,我尝试过清闲的划水摸鱼,也体验过上六休一的’福报‘;在这一年里,我从西理工肄业,报考社会大学并被录取;我与大学同班同学的散伙饭,喝的很放肆,而与室友在大学的最后一顿饭,喝的很克制;我遇到了吝啬的房东,我遇到了令人恶心作呕以及其他所有你知道的而我不能写在这里的恶毒语言来描述的隔壁;当然,我也遇到了还不错的导师,还不错的同事;我见识了江南风情,小家碧玉,阴雨连绵;我亲身游历了西湖,走过了苏堤白堤······这一年承此生前廿二载,启余生后XX年。

Tuesday, December 24, 2019

社会心理学

  • 与寻找证据证伪自己的信念相比,我们更愿意证实它们。我们把这种现象叫做验证性偏见
  • 将随机事件知觉为有联系的倾向往往容易产生一种控制错觉(illusion of control)--认为各种随机事件受自己影响。
  • 趋均数回归。当我们处在一个最低水平时,任何尝试行为看起来似乎都是有效的,因为我们将会趋向于自己更通常的状态。

Thursday, December 12, 2019

李洪元事件

        李洪元事件发酵了这么久,经历了这么长时间,事件的脉络被网友扒的越来越清晰。
如今看来,整件事情的剧情简直堪比悬疑剧情片了。
李被诬陷与无故拘禁不在于那三十万的离职补偿。起因在于之前举报其所在的逆变器部门销售造假一事。

Thursday, November 14, 2019

《弯曲的脊梁》摘录

  • 极权主义的政党懂得,允许任何非政治的“孤岛”就等于提供了滋生异端或政治冷漠的土壤。
  • 我们国家社会主义者以十分的自信宣称,对我们来说,在攸关人民的国家与社会利益之所有政治和其他事务上,元首绝对正确。--赫曼·戈林(1941)
  • 米兰·昆德拉(milan kundra)写道:“极权主义不仅是人间地狱,还是天堂之梦。”没有这个梦,国家社会主义和马列主义就不能在人类灵魂中建立它们已然拥有的控制。对他们的追随者来说,这一梦想使他们能悬着忽略罪恶,看见善的幻想。
  • 一个人必须倾听人们在说什么,如果他想争取他们的话。

Monday, November 4, 2019

MariaDB与ORACLE数据库的字符串分割

最近关于ORACLE向MariaDB迁移涉及到区别比较多~~~
还是直接上栗子吧。
还是以前的student表:
假如从前台传入一个由sno组成的字符串,比如“1,11,15,16”。
要根据该字符串查出这几条数据。
在ORACLE中可以这样写:
WITH SYSNO AS (SELECT ? SNO FROM DUAL),
SYSNO_ARRAY AS (
    SELECT REGEXP_SUBSTR(SNO,'[^,]+',1,LEVEL) SNO FROM SYSNO CONNECT BY LEVEL<=LENGTH(SNO)-LENGTH(REPLACE(SNO,',',''))+1
)
SELECT * FROM STUDENT T WHERE T.SNO IN (SELECT SNO FROM SYSNO_ARRAY) 
大概就是是这样一个情景。
放到ORACLE中执行一下:
效果似乎不错。

但在MariaDB中要怎么操作呢?
事实上,在10.0.38版本是不支持with as 语法的,但是也还好,with as 实际上就是个子查询,放到查询里面就是了。

  • ORACLE     REGEXP_SUBSTR()

但REGEXP_SUBSTR()怎么解决呢?
先来看下ORACLE中的REGEXP_SUBSTR()函数。
根据文档说明,REGEXP_SUBSTR的语法是这样婶的:

REGEXP_SUBSTR(source_char, pattern [, position [, occurrence [, match_parameter ]]])
各参数的意义分别是:
现在,参照官方文档我们看一下上述ORACLE里的sql,我们传入一个值为‘1,11,15,16’的source_string,从第一个字符开始根据正则表达式'[^,]+'按逗号‘,’分割它,并取其第...LEVEL 个匹配项???
这个LEVEL 又是个什么东西啊?
LEVEL是ORACLE的关键字,主要用来代表树形结构中的层级编号,它与后面的CONNECT BY组合可以存在树形结构的数据,关于这部分的知识比较复杂,我也不是很明白,以后遇到可以单独再出一片学习文档。在这里,我们可以看一个简单的例子就能明白这样写的作用:

是不是清晰了很多?其实就是生成了一个序列。那看回上述例子,我们就明白了它取了SYSNO_ARRAY的下标,嗯,大概就是这个意思,然后交给REGEXP_SUBSTR()这样就可以取出每一个匹配的字符串了。

  • MariaDB    REGEXP_SUBSTR()


MariaDB也有个类似的REGEXP_SUBSTR()内建函数,但根据MariaDB的官方文档:
该函数不能做到像ORACLE里的REGEXP_SUBSTR()那样可以选择起始位置或选择哪一个匹配的结果,功能比较单一.

  • MariaDB    SUBSTRING_INDEX()
好在MariaDB提供了另外一个内建函数SUBSTRING_INDEX().
可以实现类似的根据字符分割字符串并取其中某一匹配项。
另外,在实现过程中还使用到了自带的mysql数据库中的
help_topic表,它的help_topic_id字段是自增的,当然你也可以使用其他具有自增字段的表。

直接看最终的SQL:

SELECT * FROM student WHERE SNO IN (
SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(SNO,',',help_topic_id+1),',',-1) AS SNO
FROM
    mysql.help_topic,(SELECT '1,11,15,16' SNO)SYSNO_ARRAY
WHERE
    help_topic_id < LENGTH(SNO)-LENGTH(REPLACE(SNO,',',''))+1);
分析一下这段sql:
  1. 利用help_topic_id < LENGTH(SNO)-LENGTH(REPLACE(SNO,',',''))+1)可以得到最终可以被拆分为多少个字符串,有三个逗号,那结果就是四个字符串。之后就可以利用help_topic_id来遍历第n个匹配的字符串了。
  2. SUBSTRING_INDEX(SUBSTRING_INDEX(SNO,',',help_topic_id+1),',',-1) AS SNO。利用内层的SUBSTRING_INDEX() 可以取出第help_topic_id+1(help_topic_id是从0开始)个逗号之前的字符串,也就是说,
  3. help_topic_id = 0,help_topic_id+1=1,SUBSTRING_INDEX(SNO,',',help_topic_id+1) = 1
    help_topic_id = 1,help_topic_id+1=2,SUBSTRING_INDEX(SNO,',',help_topic_id+1) = 1,11

  4. 之后再利用外层的SUBSTRING_INDEX()取根据逗号分割的-1个匹配项,就可以将所有的SNO取出,通过SNO 在student表中取数据了。
至于(SELECT '1,11,15,16' SNO)SYSNO_ARRAY 就是前面提到的WITH AS 在MariaDB中的写法,而且MariaDB还要求所有的子查询必须要有一个别名,真是奇怪的设计。
最后放到MariaDB中运行一下:
可以,没问题!
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/11/mariadb.html

Friday, November 1, 2019

Table 'name' is specified twice, both as a target for 'UPDATE' and as a separate source for data

明明一个在ORACLE里平平无奇的UPDATE语句放到较旧的MariaDB(10.0.38)里面变得如此的麻烦~
还用上次的表好了,原始数据如下:
现在我想把第一条的course后面加一个’类‘字,我们可能会这样写:

update student t set 
course = (concat((select  course from student t where t.sno=8),'类')) 
where t.sno=8;
当然它在ORALCE中是没有问题的,可是放到MariaDB中运行它,就会返回“Table 't' is specified twice, both as a target for 'UPDATE' and as a separate source for data”的错误提示。
大概就是说你不能自己又当“因”,又当“果”,(额,自己打自己?)
那既然不允许被更新的表直接出现在子查询中,那我们可以把它放到缓存表里,就像这样:

update student t set course = 
(concat((select * from(select  course from student t where t.sno=1)as temp),'类')) 
where t.sno=1;
执行这条语句就可以回避之前的尴尬错误。效果如下:
事实上,在MariaDB的官方文档中对这样的UPDATE情况有说明:
文档说的很明白了,对于这种源和目标是同一张表单情况,截至到10.3.1版本都是不支持的,即需要用我上述的方法“曲线救国”,自10.3.2版本后这样的写法就是可以的了~
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/11/table-name-is-specified-twice-both-as.html

Sunday, October 20, 2019

IKBC W200开箱

           我的第一把机械键盘还是大学买的平民神器-雷柏V500。
记得当时九十几块入手的,青轴轴体,陪我征战四年,现在依然完好,质量很是不错。
      现在工作之后就想着在入一把键盘放在办公室码代码用,v500就放出租屋里打游戏用了。
      我很希望能让桌面设备能够简洁一点,鼠标键盘都做到无线化。然而市面上价格合适的、无线的机械键盘就那么几款。而IKBC 的W200是我比较中意的(喂,IKBC,还不打钱!)。2,4G无线,价格不贵,87键,是我想要的那一款。
      但价格还是稍稍有些小贵:京东日常价格438元。但是!但是!但是!今天早上看到京东有活动,满299减40,再,再,再加上本月是我生日,京东送了生日礼包,满300减20,再,再,再加上公司也送了生日礼物,京东E卡100元。所以所有优惠统统加起来拿下这把键盘花了278RMB。。。还是挺满足的~~~~
       话不多说,看外观。

     包装盒是简洁的瓦楞纸盒,加上ikbc的logo,侧面是型号,防伪标签。
可以看到我入手的是黑色,茶轴,其实我更倾向与青轴,青轴的声音,手感真的没得说,那种按下去”咔嗒“的段落感真的是一种享受。但正因为此,青轴的声音大,在办公室可能会有些嘈杂,所以选择了声音小的茶轴。

打开包装,防尘罩,说明书,键盘本体,拔键器,再加一对电池,没了。

 键盘拿出来第一感觉就是还挺重的。
茶轴

键盘采用的是两节7号电池方案,据官方介绍说,每天使用4小时的情况下,键盘的续航时间可以达到6个月。这也是我购买这把键盘的原因之一,其实我也并不指望真的能用6个月那么久,能用个几个月就很满足了。
 键盘高度看起来挺高,但对我这样手大的人来说并没有什么烦恼。
总体来说对新键盘还是比较满意的,没有明显的瑕疵,简洁的外观,低调的配色,不错的手感体验,对于这个价格来说,还要什么自行车呢~

版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/10/ikbc-w200.html

Friday, March 29, 2019

python进程通信(共享数据)

       前言

        在一般情况下当我们的程序中的某些代码需要并发执行的时候,我们通常会使用多线程(threading),它确实能够解决很多情况下的问题。
       但事实上,python中的多线程并不是真正意义上的“并行”,只能算是一段时间内的“并发”。在操作系统的底层,一个多线程的程序共同属于一个进程,程序使用一个cpu在多个线程之间频繁的上下文切换,造成了宏观现象的“并发”,是我们感觉它似乎是‘同时’进行的。
      多进程的使用能够实现真正意义的“并行”,每个进程使用一个cpu(如果你的计算机是多核cpu的画话)同时工作。

      multiprocessing

      python提供了非常好用的多进程包multiprocessing,借助这个包可以轻松实现多进程的想法。提供了Process,Queue等组件。

Process

     Process([group [, target [, name [, args [, kwargs]]]]])用于创建进程。target表示调用对象,args表示调用对象的位置参数元组。kwargs表示调用对象的字典。name为别名。group实质上不使用。
下面例子演示是创建函数作为一个子进程并等待其结束:
from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
    print 'Run child process %s (%s)...' % (name, os.getpid())

if __name__=='__main__':
    print 'Parent process %s.' % os.getpid()
    p = Process(target=run_proc, args=('test',))
    print 'Process will start.'
    p.start()
    p.join()
    print 'Process end.'
执行结果如下:
Parent process 928.
Process will start.
Run child process test (929)...
Process end.
join()方法可以等待子进程结束后在继续往下运行,通常用于进程间的同步。

复杂的程序不可能只有一个函数,对于包含多个函数的程序我们可以创建类并将类作为一个进程:

import multiprocessing
import time

class ClockProcess(multiprocessing.Process):
    def __init__(self, interval):
        multiprocessing.Process.__init__(self)
        self.interval = interval

    def run(self):
        n = 5
        while n > 0:
            print("the time is {0}".format(time.ctime()))
            time.sleep(self.interval)
            n -= 1

if __name__ == '__main__':
    p = ClockProcess(3)
    p.start()
执行结果:
the time is Tue Apr 21 20:31:30 2015
the time is Tue Apr 21 20:31:33 2015
the time is Tue Apr 21 20:31:36 2015
the time is Tue Apr 21 20:31:39 2015
the time is Tue Apr 21 20:31:42 2015
start()启动某个进程后会自动调用run()方法。

Queue(进程共享数据)

在使用多线程时要使线程共享数据只需将该数据声明为全局数据即可,线程是共享内存的,应为他们同属于一个进程。
而在多进程中默认是不共享内存即无法共享数据的。python提供了Queue、Pipes等多种方式来共享数据。
Queue是多进程安全的队列,使用较多,在此以Queue为例。Queue提供了put方法用以插入数据到队列中,提供get方法可以从队列读取并且删除一个元素。
上代码:


import multiprocessing
from multiprocessing import Process
from multiprocessing import Queue
import time
class func(Process):
    def __init__(self,queue):
        self.queue = queue
        super(func, self).__init__()
    def run(self):
        for i in range(6):
            time.sleep(0.5)
            self.queue.put(i)
            print('put {0} into queue'.format(i))

class fun2(Process):
    def __init__(self,queue):
        self.queue = queue
        super(fun2, self).__init__()
    def run(self):
        while 1:
            if self.queue.qsize()>=2:
                for i in range(2):
                    print('get {0} from queue'.format(self.queue.get()))

if __name__=='__main__':
    queue = Queue()
    p = func(queue)
    g = fun2(queue)
    p.start()
    g.start()
    p.join()
    g.terminate()
输出:
put 0 into queue
put 1 into queue
get 0 from queue
get 1 from queue
put 2 into queue
put 3 into queue
get 2 from queue
get 3 from queue
put 4 into queue
put 5 into queue
get 4 from queue
get 5 from queue
func向queue中put数据,fun2进程监视queue中的数据,有两个以上的数据时取两个出来。这样就实现了在两个进程之间的数据传输。

版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/03/python_29.html

Wednesday, March 20, 2019

Python 列表学习

列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。
列表的数据项不需要具有相同的类型。
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。
list1 = ['Google', 'blogger', 1997, 'tian'];
list2 = [1, 2, 3, 4, 5 ];
list3 = ["a", "b", "c", "d"];
列表索引从0开始。列表可以进行截取、组合等。
print ("list1[0]: ", list1[0]) #Google
print ("list2[1:5]: ", list2[1:5])  #2, 3, 4, 5
注意列表截取取头不取尾。

对列表的数据项进行修改或更新。
如将list1中 1997 改为 2019
list1[2] = 2019
我在使用列表时常常犯一个错误:
list4 = []
for i in range(5):
    list4[i] = i
这个语句我总感觉没有问题,但实际上它运行时会报错:IndexError: list assignment index out of range
原因在于初始化的list4是个空的,所以当我按索引值往里放元素的时候会报错。
正确的方式应该是用append()方法:
list4 = []
for i in range(5):
    list4.append(i)

使用 del 语句来删除列表的的元素
list5 = [1,2,3,4]
del list5[2]   #删除 3

list中常用的方法:
list.append(obj) 
在列表末尾添加新的对象

list.count(obj)
统计某个元素在列表中出现的次数

list.pop([index=-1])
移除列表中的一个元素(默认最后一个元素),并且返回该元素的值, -1就是指倒数第一个
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/03/python.html

Wednesday, February 27, 2019

正则表达式-java日期检查

在Java编程中检查日期格式要比上文的邮箱检查简洁些。
以下示例演示如何使用String类的matches()方法检查日期格式是否正确。
package regex.test;

/**
 * description:日期检查2
 * @auther :田江涛
 * @date :2019-02-27 9:03
 */
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CheckDateFormat2 {
    public static void main(String args[]) {
        List dates = new ArrayList();
        dates.add("1990-12-21");
        dates.add("1990-12-31");
        dates.add("1990-12-32");
        dates.add("09-12-12");
        dates.add("2001-02-10");
        dates.add("1989-06-04");
        dates.add("45-09-12");
        dates.add("18/02/02");
        dates.add("2019/04/21");
        String regex = "^([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])$";
        Pattern pattern = Pattern.compile(regex);

        for (Object date : dates) {
            Matcher matcher = pattern.matcher((CharSequence) date);
            System.out.println(date + " : " + matcher.matches());
        }
    }
}
示例输出结果:

1990-12-21 : true
1990-12-31 : true
1990-12-32 : false
09-12-12 : false
2001-02-10 : true
1989-06-04 : true
45-09-12 : false
18/02/02 : false
2019/04/21 : false

代码示例使用正则表达式:"^([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])$",
根据对照正则表达式语法表,我们可以解释该正则表达式匹配的字符串形式:
^([0-9]{4}) : 开头匹配0-9且为4位数字,对应年份;
- : 以‘-’分割,所以示例中‘/’非法;
(1[0-2]|0[1-9]) : 匹配10,11,12 或者是 01-09,对应月份;
(3[01]|[12][0-9]|0[1-9])$ : 以30、31或10-19、20-29或01-09结尾,对应日期。

当然有一点小问题就是它无法考虑平年2月只有28天的情况,不过在这里并不追究了。

Matcher.maches()方法:

public static boolean matches(String regex,  CharSequence input)
编译给定正则表达式并尝试将给定输入与其匹配,返回的是一个boolean值。  
可以使用快捷方法的形式对代码进行简化:
Pattern.matches(regex, input);
Pattern.compile(regex).matcher(input).matches() ; 

for (Object date : dates) {
//          Matcher matcher = pattern.matcher((CharSequence) date);
            boolean b = Pattern.compile(regex).matcher((CharSequence) date).matches();
            System.out.println(date + " : " + b);
        }

版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/02/java_26.html

Tuesday, February 26, 2019

正则表达式--Java邮箱验证

在Java编程中,如何验证电子邮件地址格式?
以下示例使用String类的matches()方法来验证电子邮件地址。
String.matches() 这个方法主要是返回是否匹配指定的字符串,如果匹配则为true,否则为false

package regex.test;

/**
 * description:验证电子邮件地址
 * @auther :jiangtoa.tian
 * @date :2019-02-26 15:46
 */
public class ValidateEmailFormat {
    public static void main(String[] args) {
        //String EMAIL_REGEX = "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$"; //正则表达式1
        String EMAIL_REGEX ="\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";    //正则表达式2
                String email1 = "admin@admin.com";
        boolean b = email1.matches(EMAIL_REGEX);
        System.out.println("email:" + email1 +" : valid = "+b);

        String email2 = "admin&admin.com";
        boolean b2 = email2.matches(EMAIL_REGEX);
        System.out.println("email:" + email2 +" : valid = "+b2);
    }
}
上述代码示例将产生以下结果:
email:admin@admin.com : valid = true
email:admin&admin.com : valid = false
代码实际上并不长,关键点是其中所使用的正则表达式.
在代码中使用了两个正则表达式:

  1. "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$"
  2. "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"

都可以正确验证邮箱格式,所以说正则表达式并不是唯一的,关键是要能明白正则表达式的语法.
  1. 字符描述:
  2. ^ :匹配输入的开始位置。
  3. \:将下一个字符标记为特殊字符或字面值。
  4. * :匹配前一个字符零次或几次。
  5. + :匹配前一个字符一次或多次。
  6. [a-z] :表示某个范围内的字符。与指定区间内的任何字符匹配。
  7. \w :与任何单词字符匹配,包括下划线。
  8. $ :匹配输入的结尾。
对照语法表就能大致读懂正则表达式匹配的内容.
注:在 Java 中,\\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。这也就是为什么表示任一字符的正则表达式是 \\w.

版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/02/java.html

Friday, January 18, 2019

oracle字符集问题

在向oracle数据库中插入中文字符串是出现错误:
ERROR:ORA-01756: quoted string not properly terminated

是因为无法识别语句中的中文字符,插入的是乱码,无法成功。
再比如:
仍然是乱码显示
我们查询出数据库服务端的编码为AMERICAN_AMERICA.AL32UTF8
应该正常显示中文,那么就可能是客户端的问题
编辑linux用户的环境变量文件.bash_profile    
添加NLS_LANG oracle客服端字符环境变量,将该变量和数据库设置成一致。
激活使之生效

在此插入、查询
中文字符正常显示。
如果还是无法正常显示
请查看你的连接终端的字符集设置,将其设置为utf-8再重试。

版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/01/oracle_18.html

Thursday, January 17, 2019

oracle安装过程中遇到的问题及解决

在之前的文章Linux上安装oracle奋斗历程中我说到在安装oracle时会遇到一些问题,在这里我将我遇到的问题及解决方法与大家分享,希望能有所帮助。

1.安装oracle需要图形界面

在oracle安装过程中是以图形界面显示的,而我们选择在Linux服务器上安装oracle,上哪去找图形界面呢?
在这里我给大家分享我使用的工具:MobaXterm。可以下载绿色免安装版。MobaXterm内建了一个X server,可以直接执行远程端的X窗口程序。也是随着SSH连接自动发挥作用,无需任何配置。利用该工具使用oracle账户登录服务器再执行安装脚本就会有图形界面啦。

2.连接时报错:DISPLAY not set. Please set the DISPLAY and try again。

在使用MobaXterm去连接服务器时还有可能报错:DISPLAY not set. Please set the DISPLAY and try again。
具体原理我不是很清楚,感兴趣的可以深究,我只讲如何解决。
切换到root用户,执行以下命令:
# export DISPLAY=:0.0
# xhost +
如果有提示:
access control disabled, clients can connect from any host
则该问题解决,若提示

xhost: unable to open display “”

则请看下一问题

3.xhost: unable to open display “”

第一步:用root登陆linux,启动vnc服务;
第二步:根据vnc起来的端口,设置export DISPLAY=localhost:1;
第三步:执行xhost +
最好在mobaXterm上再开一个终端执行该命令,我当初在xshell上执行这些命令一直失败,换到MobaXterm上一下就ok了。
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/01/oracle.html

Monday, January 14, 2019

Linux上安装oracle奋斗历程

写在前面

    先说明oracle的版本:
Oracle Database 11g Release 2
安装的环境,使用阿里云为学生提供优惠的轻量应用服务器,每月低至9.5元。配置如下:

进入正题

1.创建oracle用户及用户组

以root用户连接linux服务器
#创建用户组 oinstalldba
创建用户oracle并设置其属于用户组oinstall,属于附加组dba
命令如下:
#groupadd oinstall
#groupadd dba
#useradd -g oinstall -G dba oracle
这一步主要是为了避免后面创建文件以及解压缩等一系列步骤中,要将文件所有者修改为oracle才能在安装过程中有足够的权限创建文件或子目录。

2.软件包依赖

官方文档中对于RHEL5及以上版本的Linux发行版,要求需要以下的软件包(更高版本也行)

shell
binutils-2.17.50.0.6 
compat-libstdc++-33-3.2.3 
elfutils-libelf-0.125 
elfutils-libelf-devel-0.125
elfutils-libelf-devel-static-0.125 
gcc-4.1.2 
gcc-c++-4.1.2 
glibc-2.5-24 
glibc-common-2.5 
glibc-devel-2.5 
glibc-headers-2.5 
kernel-headers-2.6.18 
ksh-20060214 
libaio-0.3.106 
libaio-devel-0.3.106 
libgcc-4.1.2 
libgomp-4.1.2 
libstdc++-4.1.2 
libstdc++-devel-4.1.2 
make-3.81 
sysstat-7.0.2 
unixODBC-2.2.11 

你可以使用以下命令查看上面这些软件包的版本是否大于等于上面的要求:

[oracle@izuf6b3rv931tl77hb3mcoz /]$ rpm -q binutils compat-libstdc++ elfutils-libelf elfutils-libelf-devel elfutils-libelf-devel-static gcc gcc-c++ glibc glibc-common glibc-devel glibc-headers kernel-headers ksh libaio libaio-devel libgcc libgomp libstdc++ libstdc++-devel make sysstat unixODBC unixODBC-devel
binutils-2.27-34.base.el7.x86_64
package compat-libstdc++ is not installed
elfutils-libelf-0.172-2.el7.x86_64
elfutils-libelf-devel-0.172-2.el7.x86_64
elfutils-libelf-devel-static-0.172-2.el7.x86_64
gcc-4.8.5-36.el7.x86_64
gcc-c++-4.8.5-36.el7.x86_64
glibc-2.17-260.el7.x86_64
glibc-common-2.17-260.el7.x86_64
glibc-devel-2.17-260.el7.x86_64
glibc-headers-2.17-260.el7.x86_64
kernel-headers-3.10.0-957.1.3.el7.x86_64
ksh-20120801-139.el7.x86_64
libaio-0.3.109-13.el7.x86_64
libaio-devel-0.3.109-13.el7.x86_64
libgcc-4.8.5-36.el7.x86_64
libgomp-4.8.5-36.el7.x86_64
libstdc++-4.8.5-36.el7.x86_64
libstdc++-devel-4.8.5-36.el7.x86_64
make-3.82-23.el7.x86_64
sysstat-10.1.5-17.el7.x86_64
unixODBC-2.3.1-11.el7.x86_64
unixODBC-devel-2.3.1-11.el7.x86_64
如提示有未安装,那建议你全部更新安装一遍

#yum install binutils compat-libstdc++ elfutils-libelf elfutils-libelf-devel elfutils-libelf-devel-static gcc gcc-c++ glibc glibc-common glibc-devel glibc-headers kernel-headers ksh libaio libaio-devel libgcc libgomp libstdc++ libstdc++-devel make sysstat unixODBC unixODBC-devel

3.配置内核参数

由于只是安装个Oracle用来学习那只需要使用官方文档中建议的最低配置就行
具体方法是:
编辑/etc/sysctl.conf文件
#vi /etc/sysctl.conf
在文件最后添加一下配置:
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 536870912
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586
为使上述配置生效而不重启系统,执行如下命令:
# /sbin/sysctl –p

4.为oracle用户添加shell配置

为了提高Oracle软件性能,需要为Oracle用户添加shell配置
具体步骤为:
1. /etc/security/limits.conf文件最后,添加以下参数:

#vi /etc/security/limits.conf

oracle           soft    nproc   2047
oracle           hard    nproc   16384
oracle           soft    nofile  1024
oracle           hard    nofile  65536
2. /etc/pam.d/login文件中添加一行:

session    required     pam_limits.so
3. /etc/profile文件添加以下脚本:

if [ $USER = "oracle" ]; then
      if [ $SHELL = "/bin/ksh" ]; then
            ulimit -p 16384
            ulimit -n 65536
      else
            ulimit -u 16384 -n 65536
      fi
fi

5.创建并配置环境变量

安装路径可以任选。在任意路径下创建安装目录并赋权限

命令如下

# mkdir /oracle/app
# chown -R oracle:oinstall /oracle
# chmod -R 775 /oracle

6.配置oracle用户环境变量:

此时要切换至Oracle用户:

#su – oracle
编辑shell脚本:

$vi .bash_profile
在脚本中添加如下环境变量:
export ORACLE_BASE=/oracle
export ORACLE_HOME=/oracle/app
export ORACLE_SID=oracleSID
export PATH=$ORACLE_HOME/bin:$PATH

7.安装包下载

复制链接至迅雷下载即可.或移步至oracle官网下载
其他版本可参考另一博文:Oracle11g下载地址--多平台下的32位和64位
下载完后使用任意ftp文件传输工具上传至linux主机,使用unzip命令解压。
解压完成后会生成一个database文件夹:
drwxr-xr-x 8 oracle oinstall       4096 Aug 21  2009 database
-rw-r--r-- 1 root   root     1239269270 Jan 14 10:55 linux.x64_11gR2_database_1of2.zip
-rw-r--r-- 1 root   root     1111416131 Jan 14 10:55 linux.x64_11gR2_database_2of2 (1).zip
进入database解压包,该目录下有可执行脚本 runInstaller

[oracle@izuf6b3rv931tl77hb3mcoz tmp]$ cd database/
[oracle@izuf6b3rv931tl77hb3mcoz database]$ ll
total 36
drwxr-xr-x 12 oracle oinstall 4096 Aug 17  2009 doc
drwxr-xr-x  4 oracle oinstall 4096 Aug 15  2009 install
drwxrwxr-x  2 oracle oinstall 4096 Aug 15  2009 response
drwxr-xr-x  2 oracle oinstall 4096 Aug 15  2009 rpm
-rwxr-xr-x  1 oracle oinstall 3226 Aug 15  2009 runInstaller
drwxrwxr-x  2 oracle oinstall 4096 Aug 15  2009 sshsetup
drwxr-xr-x 14 oracle oinstall 4096 Aug 15  2009 stage
-rw-r--r--  1 oracle oinstall 5402 Aug 18  2009 welcome.html
运行runInstaller脚本开始安装,此处可能会有一些错误、问题。我另外给大家讲解。
还有就是此时要使用oracle用户登陆图形界面,因为之后的安装是在图形界面下完成的。这个也放到以后讲。
如果前面都木有问题了,那么你将看到这个界面,终于来到了安装界面:
1.step 1 是一些更新的问题,把勾去掉跳过即可:
2. step 2 给出三个选项,分别是创建并配置一个新数据库;只安装数据库软件;升级已有数据库。选择第一项安装数据库:
3. step 3是选择配置桌面版还是服务器版,桌面版是最小化配置,这里为了练习选择服务器版的配置:
4.step 4 选择单实例服务器配置还是如果要配置分布式服务配置。自己练习自然选择单实例服务器配置就可以了:
5.step 5 选择典型安装还是高级安装。我们自己配置选择高级安装(注意截图中默认选择典型安装,我们要选第二个,不要被图片误导了):
6.step 6 选择语言,默认已选择英文,我们再加上简体中文:
7.step 7 选择数据库版本,这里选择第一个企业版:
8 step 8 选择安装路径,这个已经在环境变量里配置过在这里就不用改动了:
9.step 9 Inventory Directory目录用于记录Oracle的清单信息,清单信息中包括Oracle的安装路径等信息。我们新建一个 inventory目录存放这些信息:
10. step 10 创建数据库的类型:
    • 通用/事务处理:专为一般用途或交互较多的应用程序而设计。
    • 数据仓库:对数据存储应用程序进行优化。
  • 选一般的通用就可以:
  • 11.step 11 配置数据库名,和Oracle服务ID号,最好不要动,数据库名一定要记住:
  • 12. step 12 配置一下字符集,将字符集设置成UTF-8,其他的不用修改:
  • 13. step 13 配置系统信息邮件通知的,不用在意,跳过:
  • 14. step 14 用于配置数据存储的(数据文件存储位置),这里我们把数据存储在/oracle/oradata目录下,默认不用动:
  • 15. step 15 配置数据备份,这里我们只是用来学习选择不进行自动备份:
  • 16. step 16 配置账号密码,这里我为了图简单好记将所有的默认用户统一使用相同的密码,密码需要包含大、小写字母和数字:
  • 17. step 17 配置数据库用户组的,只要安装前的配置工作完成了,这一步可以直接使用默认的:
18 step 18 检测交换分区大小、内核参数以及依赖包是否安装。只要前面准备工作都完成了,下面的错误可以直接忽略(比如它要求的软件包,我们的版本实际上比它要求的还高,所以这里的报错没必要理会它),我们直接点击右上角忽略即可:
19. step 19 对前面所有配置的一个总结,我们可以直接点击完成:
20.step 20 只要前面工作都没问题,我们就安心的等待安装:
之后需要点击password management对数据库用户的密码进行一些配置:
然后运行脚本:

21.step 21 安装成功!
至此oracle数据库安装完毕。可以尝试使用sqlplus连接oracle数据库验证一下,在此不在赘述。
开启oracle学习的漫漫征途吧~
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2019/01/linuxoracle.html