mysql bit field

在前面的文章中,我分享了目前在项目中使用的一个很好用的python脚本,《IP log analysize and record》,python脚本很简单,懂得python的朋友应该都很容易看懂,在本片文章中,重点讲述一下在mysql操作中的一点注意事项。
首先,我们来分析一个场景:用户访问一个站点的时候,我们把用户的访问行为记录了下来,这点无论是Apache还是Nginx都能很好得把access log记录下来,可能一个用户一天会访问好多次,但是我们的统计需求往往只会要求判断某个用户在一段时间内的登录情况,比如腾讯朋友空间的日活跃情况,细节只是定位到天,好了,我们的pv就变成了uv,但是uv的明细表依然很庞大,我们可以继续压缩,把每个用户每个月的访问情况,压缩成一条记录,这个时候,Mysql的一个特殊的字段类型 bit就出场了,一般情况下我们定义为 bit(31)即可,每个月一张表,用户的访问情况可以如下: More

work tools – ip log analysis and record

收录一个工作中使用的日志分析脚本,使用python写成,简单明了,直接上代码:

#! /usr/bin/env python
# -*- coding: utf8

import MySQLdb
import datetime
import sys, time
import traceback
import devintool as t
from threading import Thread
import threading
import Queue as q
THREAD_NUM = 100
BATCH_SIZE = 1000

clients=[]

class Conn():
    def __init__(self, host, port, db="fb", user="", passwd="", charset="utf8"):
        self.host=host
        self.port=port
        self.db=db
        self.user=user
        self.passwd=passwd
        self.charset=charset
        self.is_open=False
        self.__conn = None

    def open(self):
        self.__conn = MySQLdb.connect(host=self.host, port=self.port, user=self.user,
            passwd=self.passwd, db=self.db,  charset=self.charset)
        self.is_open=True
        return self.__conn

    def close(self):
        self.__conn.close()
        self.is_open=False

    def cursor(self):
        return self.__conn.cursor()

stdoutMutex = threading.Lock()
class mysqlThread(Thread):
    #def __init__(self, host1, port1, db1, host2, port2, db2, queue):
    def __init__(self, host1, port1, db1, queue):
        Thread.__init__(self)
        self.queue=queue
        self.conn1=Conn(host=host1,port=port1,db=db1)
        self.cursor1=self.conn1.open().cursor()
        self.cursor1.execute('set autocommit=1')
        '''
	self.cursor2=self.conn2.open().cursor()
	self.conn2=Conn(host=host2,port=port2,db=db2)
        self.cursor2.execute('set autocommit=1')
	'''
        self._stop = threading.Event()


    def run(self):
        print "run"
        while True:
	    #try:
                sql = self.queue.get()
                if not self.cursor1:
                    self.cursor1 = self.conn1.open().cursor()
                    self.cursor1.execute('set autocommit=1')
                #if not self.cursor2:
                #    self.cursor2 = self.conn2.open().cursor()
                #    self.cursor2.execute('set autocommit=1')
                self.cursor1.execute(sql)
                #self.cursor2.execute(sql)
                self.queue.task_done()
                '''
          commit_cnt+=1
          print commit_cnt
          if commit_cnt%10000==0:
                stdoutMutex.acquire()
                print datetime.datetime.now()
                print commit_cnt 
                stdoutMutex.release()
                '''
            #except Exception,e:
	    #	print e
class iplogThread(Thread):
    def __init__(self, queue, date):
         Thread.__init__(self)
         self.queue = queue
         self.date = date
	 self.conn = Conn(host="log1.kdb.d.kaixin.com",port=3306,db="fb")
         self.cursor = self.conn.open().cursor()

    def run(self):
        user_cnt=0        
        id_begin=0
        while(1):
            print datetime.datetime.now()
            user_set = self.get_user_ids(self.cursor, id_begin, BATCH_SIZE) 
            if len(user_set)==0:
               PUT_DONE = 1
               break
               
            user_cnt+=len(user_set)
            print id_begin
            id_begin=int(user_set[-1][0])
            self.__handle(user_set) 
            print "%d, %d"%(len(user_set), user_cnt)
            print datetime.datetime.now()
            if len(user_set)=0 and user[1]<=3) and [str(user[1])] or ["_"])[0]
           locals()["user_set_type%s" % (type,)].append(user[0])

       for type in ("0", "1", "3", "_", "4", "__"):
           listName = "user_set_type%s" % (type,)
	   if len(locals()[listName])>0:
               str1 = ",".join("(%d, 1<<%d, 1<<%d)"%(id, self.date.day-1, self.date.day-1) for id in locals()[listName])
               str2 = ",".join("%d"%id for id in locals()[listName])
               str1 = str1.rstrip(',')
               str2 = str2.rstrip(',')
               sql = "insert ignore into user_login_%s (id, login_days, %s) values %s" %(self.date.strftime('%Y%m'),keyMap[listName],str1)
               #print sql
               self.queue.put(sql)
               #bit record log days
               sql = "update user_login_%s set login_days=login_days|1<<%d, %s=%s|1<<%d where id in (%s)"%(self.date.strftime('%Y%m'), (self.date.day-1), keyMap[listName], keyMap[listName], (self.date.day-1), str2)
               #print sql
               self.queue.put(sql)
	   else:
	       print "len=0:", keyMap[listName]
       
       '''
       #deal with Other
       str1 = ",".join("(%d, 1<<%d)"%(id, self.date.day-1) for id in user_set_typeOther)
       str2 = ",".join("%d"%id for id in user_set_typeOther)
       str1 = str1.rstrip(',')
       str2 = str2.rstrip(',')
       sql = "insert ignore into user_login_%s (id, login_days) values %s" %(self.date.strftime('%Y%m'), str1)
       self.queue.put(sql)
       sql = "update user_login_%s set login_days=login_days|1<<%d where id in (%s)"%(self.date.strftime('%Y%m'), (self.date.day-1), str2)
       self.queue.put(sql)
       '''
           
    def get_user_ids(self, cursor, id_begin=0, limit=10000):
        sql="select id, type from iplog_typeid_%s where id>%d order by id limit %d" % (self.date.strftime("%Y%m%d"), id_begin, limit)
        return t.get_set_cur(sql, cursor)

def getClients():
    sql = "select app_id from ClientDefine;"
    cursor = MySQLdb.connect(host="10.22.241.148", user="xiaoneilogs", passwd="Pycd8452", port=3306, db="xnstat", charset="utf8").cursor()
    rs = t.get_set_cur(sql, cursor)
    return [l[0] for l in rs]
         
if __name__ == "__main__":
    #try:
        if len(sys.argv)>1:
            date_str = sys.argv[1]
            print date_str
            date = datetime.datetime(int(date_str.split('-')[0]),int(date_str.split('-')[1]),int(date_str.split('-')[2]) )
            print date
        #x = raw_input('ok')
        else:
  	    date = (datetime.datetime.today() - datetime.timedelta(days=1)).date()
	print date

	clients=getClients()
	print "clients:n", clients

	conn1 = Conn(host="10.22.200.224", db="ugc_xn", port=3306)
	conn2 = Conn(host="123.125.45.215", db="user_login", port=3306)
	#for conn in (conn1,conn2):
	for conn in (conn1, ):
            sql = "create table if not exists user_login_%s like user_login; "%date.strftime('%Y%m') 
            print sql
            conn.open()
            conn.cursor().execute(sql)
            conn.close()
        queue =  q.Queue(THREAD_NUM)
        for i in range(THREAD_NUM):
            #th = mysqlThread(host1='10.22.200.224', port1=3306, db1='ugc_xn', host2='123.125.45.215',port2=3306, db2='user_login', queue=queue)
	    
    	    th = mysqlThread(host1='10.22.200.224', port1=3306, db1='ugc_xn', queue=queue)
            th.setDaemon(True)
            th.start()
        iplog = iplogThread(queue, date)
        iplog.start()    
        queue.join()
    #except Exception,e:
    #	print "Exception happened : ",e
    #	t.putout_except(e,os.path.dirname(os.path.realpath(__file__)))

work twitter-mysql insert or replace

When we need to insert some data into databases, we can utilise the basic “insert” sql, those we usually used in the past work,for example:

insert into someTable (colum1,colum2,..) values (val1, val2, ...);
insert into someTable values (val1, val2, val3 ...)

But in the development,we sometimes require some unique date in the database, in another word, when the sql insert some into the db, if find the same record has existed,then ignore it ,and continue to do the next query,

insert ignore into someTable (colum1,colum2,..) values (val1, val2, ...);
insert ignore into someTable values (val1, val2, val3 ...)

At the same time , some individuals assert that they may use the “replace” query to replace the “insert ignore”.
There are some attention that are alerted.
1.replace need the primary key or the unique index to update, thinking the below sql:

replace into tableA values(val1, val2, ...);
replace into tableA select val1, val2, ... form tableB
replact into tableA set colum1 = val1, colum2 = val2, ....., columN = concat(valN, "some constant");

Notice: if use the “concat” ,the updated data can not include NULL value, for instance, concat(“tom”, NULL, “david”), the result will be NULL, it can not be the “tomdavid”
2. if some want to update a special line, the next sql is good:

insert ignore into tableA (colum1, colum2, ..., columN) values (val1, val2, ..., valN); //Use ignore key word
update tableA set columN = columN | 1<< [$constant]           //calculate the new colum value 

LD生病了

今天怎么说呢,可以说是个阴晴不定的天气吧。帝都终于结束了一周的阴雨绵绵的日子,难得太阳出来露脸了,天气一如既往地闷热,下午LP大人说闹肚子变厉害了,浑身没有力气,害怕对宝宝有影响,于是直奔医院,不巧的是妇产医院的急诊居然都没法看内科,连个靠谱的医生都没有,不过免费给听了下胎心,一切正常,稍微放心了点,然后一合计,直奔朝阳医院,继续急诊,妇产科,转肠道科,化验结果很“美好”,没啥问题,回来注意饮食就是了,拿了盒“思密达”回家,一路畅通不表。
想来应该是昨天中午的饭闹的,估计是冷热混着吃,导致肠胃紊乱了,回到家先熬自制盐水【一大碗水,2勺白糖,2/3勺食盐,烧开,趁热喝】据说效果还不错,主要是保持体内的电解质平衡,希望睡一觉一切就变好了吧:)
晚饭主打 白米粥+小咸菜 了,养养胃先。

Use crontab to finish works which will deal with access logs and load into infobright database

在昨天的文章中,我们讲述了如何使用Python来访问Java程序,在今天我们继续聊聊脚本的知识。最近由于业务的需要,给数据运维人员搞了个先进的数据查询引擎-Infobright,有关infobright的鼎鼎大名早已经是如雷贯耳,数据压缩上确实很牛叉,可以参考《Infobright数据仓库搭建》《Infobright的数据类型以及优化相关》。这几篇都跟mysql优化类似,但是略有不同还是注意的好,为了更好的优化效果,比如我在创建数据库表的时候就把原来的Varchar类型的字段创建成了Char,因为varchar的效率很低。
数据引擎搭建起来了,接下来我们需要自动的把数据加载到我们的数据库,由于众所周知的原因,目前社区办的ICE只支持load加载数据,所以我们得把我们的日志文件先处理成Infobright能够接受的类型,比如常见的csv格式。然后使用脚本自动的把我们的结果数据搞到数据库里面就可以了。
第一个脚本,完成日志目录的创建,日志合并,日志处理

#!/bin/sh

export LOG_DIR=/data1/remote-log-server/log/
today=`date "+%Y-%m-%d"`
yestoday=`date -d '1 days ago' "+%Y-%m-%d"`

GameLoginPath=$LOG_DIR/gamelogin/$today

#merge yesterday log
/bin/cat $LOG_DIR/gamelogin/$yestoday/gamelogin.log.* > $LOG_DIR/gamelogin/$yestoday/gamelogin.log
#use python script deal with access log to infobright data format
/usr/bin/python /data1/weige/python/gamelogin_weige.py $yestoday 99
#auto load data which can be accepted by infobright engine
/bin/sh /data1/remote-log-server/update_data_to_db.sh $yestoday

#create today log dir
if [ ! -d "$GameLoginPath" ]; then
        /bin/mkdir -p "$GameLoginPath"
fi

接下来的章节,我们将详细分拆解释我们这个脚本中间运行的这三个脚本,同时进一步对resin容器进行优化。

Use jpype in python scripts

JPype is an effort to allow python programs full access to java class libraries. This is achieved not through re-implementing Python, as Jython/JPython has done, but rather through interfacing at the native level in both Virtual Machines.
JPype是一个高效的python库,它允许python程序和java类互通。它并非是一个重新实现的Python,就像Jython和JPython那样,而是通过在虚拟机native层面上实现。
Eventually, it should be possible to replace Java with python in many, though not all, situations. JSP, Servlets, RMI servers and IDE plugins are all good candidates.
实际上,它应该可以在许多的场景下使用python来替换Java,当然了并非所有的都能替换。像 JSP, Servlets, RMI servers and IDE plugins都是很好的替换对象。
—————————————–强行分割一下吧—————————————-
最近学习写一些用来处理日志log的python脚本,但是到连接到线上数据库的时候出现了点小小的麻烦,因为众所周知,renren的代码是java的,连接数据库都被java做了封装,不能显示的看到具体那台数据库【实际上开发者也无需关心,我们只需要一个配置文件,具体指向什么地方,后面是一台机器还是多台,都不在操心。】就想找到一个python能直接访问java程序的解决方案,翻来翻去就找到JPype了,它的源码好久没更新,不过最近更新了一下,最新的版本是0.5.4.1,可以通过这个链接下载
安装很简单,直接直接python setup.py install就可以了(安装过程中显示的warning可以不必理会)。用于测试是否安装成功的Hello World代码如下:

from jpype import *
startJVM(getDefaultJVMPath())
java.lang.System.out.println("hello world")
shutdownJVM()

运行结果如下:

[root@SJSWT45-26 wei]# python testp2j.py
hello world
JVM activity report     :
        classes loaded       : 30
JVM has been shutdown

2.  启动JVM

依靠startJVM这个函数来完成,一个使用的例子是这样的:

vmPath = jpype.getDefaultJVMPath()
jpype.startJVM(vmPath, "-Xms32m", "-Xmx256m", "-mx256m", "-Djava.class.path=/home/some-lib.jar:")

startJVM的第一个参数是JVM库所在的路径(和JAVA_HOME不是一回事儿),通常可以用jpype.getDefaultJVMPath()来自动获取系统默认JVM的路径。如果系统中安装了多个JDK,希望从中选择一个,则可以手动注明这个路径。比如Mac OSX下可以写成“/System/Library/Frameworks/JavaVM.framework/Libraries/libjvm_compat.dylib”

剩下的都是发送给JVM的启动参数,每个逗号见是一个参数。因为这里是不支持带空格的参数写法的,所以例子里特意把classpath参数写成了-Djava.class.path=…的形式。注意这里需要手工保证参数的正确性,jpype是不会对错误的参数给出提示的,它的反应很简单,就是在后面用到这个JVM的时候报一些怎么也想不明白的错误……所以,使用jpype遇到任何问题,首先检查传给startJVM的各参数正确性。

3.  如何调用一个Java函数

主要靠JPackage语句来实现,比如

Document = jpype.JPackage('org').w3c.dom.Document

可以把Java里面的org.w3c.dom.Document映射给Python里面的Document变量。
java和javax两个包不需要以这种方式来调用,直接类似jpype.java.lang.System.out.println()这样就可以了。

有时候我们会遇到类似TypeError: Package org.w3c.dom.Document is not Callable”这样的错误。通常这时用到的Java指令在jar里面,而这个jar没有被正确导入,所以JVM找不到它。也就是说,遇到这种错误时,要去检查startJVM函数中的-Djava.class.path=参数的设置,通常都是因为这里的路径写错了造成的。

4.  如果捕捉Java异常

可以在Python里使用 jpype.JavaException指代所有的Java异常,比如像下面这样:

import jpype
jpype.startJVM(jpype.getDefaultJVMPath())
try:
    jpype.java.lang.Integer("x1")
except jpype.JavaException, ex:
    print ex.javaClass(), ex.message()
    print ex.stacktrace()    
jpype.shutdownJVM()

如果要捕获特定的Java异常呢,则需要用到jpype.JException,比如像下面这样捕获的就是java.lang.NumberFormatException

import jpype
jpype.startJVM(jpype.getDefaultJVMPath())
try:
    jpype.java.lang.Integer("x1")
except jpype.JException(jpype.java.lang.NumberFormatException), ex:
    print ex.javaClass(), ex.message()
    print ex.stacktrace()    
jpype.shutdownJVM()

5.  如何处理Java的函数多态

Java里面是允许参数格式不同的多个同名函数的,Python里面则不允许。这样在通过jpype调用Java api里面的函数时,有时会因为参数的类型乱掉而报错。那么怎么能调用到Java里面的特定函数呢?没办法,做强制类型转换吧。

比如jpype.java.lang.System.out.println(1)实际会调用println(int),那么如果我们想调用println(byte)%,则可以写成jpype.java.lang.System.out.println(JByte(1))这样。。

6.  如何重启JVM

jpype提供的shutdownJVM()方法实际调用的是JNI接口的unload实现,但是Sun对unload的实现有点问题,造成的结果就是jpype调用shutdownJVM()以后就没法再startJVM()了(会报错)。什么?您问关掉JVM干嘛还要重新开启它,这个折腾个什么劲?答案很简单:因为有时在未知的黑暗角落隐藏着邪恶的源头——内存泄露。。

既然jpype没法重启JVM,那么只好把jpype放到processing里面来用,需要重启时,就杀掉当前进 程,重新启动一个新进程好了。。(processing安装很简单,Python 2.6官方发行版已经带了,之前的版本则可以easy_install processing)

下面给出一个processing下用jpype的例子:

import jpype
import processing

def java_loop(pipe, id):
    jpype.startJVM(jpype.getDefaultJVMPath())
    while True:
        jpype.java.lang.System.out.println(pipe.recv() + ' ' + id)
        pipe.send(None)

head1, head2 = processing.Pipe()
p = processing.Process(target = java_loop, args = [head2, '(JVM 1)'])
p.setDaemon(True)
p.start()
head1.send("Hello message from")
head1.recv()
p.terminate()

head1, head2 = processing.Pipe()
p = processing.Process(target = java_loop, args = [head2, '(JVM 2)'])
p.setDaemon(True)
p.start()
head1.send("Hello message from")
head1.recv()

这里用到的pipe.recv()要小心,一旦阻塞可能会与twisted之类的框架产生冲突。一个可能的解决办法是在recv()之前用pipe.poll()函数检测一下管道里面是否有待接收数据,如果没有就等一会重新poll()就是了。[poll()自称是非阻塞的,因为它只阻塞当前线程;而recv()则会阻塞当前进程,于是twisted就不干了]

nightmare

可爱的领导大人晚上又做噩梦了,梦的男猪脚当然是可怜的我,哎,居然是我和ex做那等苟且之事,早都断了联系n年了,居然还能想到一起,不过我坚信这是“责之愈切,爱之愈深”所导致的。怀胎十月确实不容易,我要进一步多多关心

xtrabackup对数据库进行备份

一个大型的网站,数据的完整性往往是重中之重,因此,我们一般会使用传统的master-slave的架构来确保能有多份数据副本,但是,这种结构有其不 足之处,如被执行”delete”、”truncate”、”drop”,亦或是不可抗拒的原因造成的数据丢失情况,因此,这时就需要我们能够留下数据快 照,以便在发生这样情况的时候,尽可能的挽救我们的数据。

数据快照的方式多种多样,这里介绍一个现在正在使用的方式:使用xtrabackup(以下都以version=1.6为例)进行数据热备。

Xtrabackup是由percona开发的一个开源软件,此软件可以说是innodb热备工具ibbackup的一个 开源替代品。这个软件是由2个部分组成的:xtrabackup和innobackupex。Xtrabackup专门用于innodb引擎和 xtraDB引擎;而innobackupex是专门用于myisam和innodb引擎,及混合使用的引擎。如果你想使用源代码方式安装的话,则会发现其安装方式有点古怪,这是因为它采用的在MySQL源代码上打补丁构建的方式。

tar zxf xtrabackup-0.8.tar.gz
cd xtrabackup-0.8
./configure
make
##进行到这里时,千万别惯性使然接着make install,那样就会接着安装MySQL了,正确方法是接着:
cd innobase/xtrabackup/
make
make install

在备份数据的过程中,我们需要解决几个问题:

1、数据库服务器空间不足,就现有服务器来说,一般都是600G硬盘,往往数据文件就有300G+,因此,本机备份不可取,而且也不太能满足容灾的需要

2、备份的维护成本,尽量使备份能够可配置化。

为了解决上面2个问题,我们这样来操作:

先做下面几个假设,以便能够进行讲解:

1、假设我们需要备份的database在服务器IP:A,并且在A上已经安装xtrabackup

2、假设我们要将数据备份到服务器IP:B

在B上执行的脚本片段如下:

for .. in {…..};do

……

#在本地后台启动1234监听,以便接受备份文件

nc -d -l 1234 > /data/$A/20100118000001.tar &

#ssh到服务器A执行备份,并将备份包推送到备份机B上。同时记录下log。

ssh $A ‘innobackupex-1.5.1 –stream=tar –include=’renren.*’ –throttle=500 –socket=/data/mysql/backup/my
sql.sock –defaults-file=/data/dbbackup/my.cnf –user=root –password=xxxxxxx –slave-info /data/dbbackup | nc
$B 1234′ < /dev/null > /data/xtrabackup.log 2>&1

……

done;

从上面脚本片段我们能看出:我们使用了xtrabackup的备份脚本 innobackupex-1.5.1,对上面涉及到的参数进行解释:

–stream=tar : 告诉xtrabackup,备份需要以tar的文件流方式输出。

–include=’renren.*’:备份包含的库表,如例:意思是要备份renren库中所有的表。如果需要全备份,则省略这个参数;如果需 要备份renren库下的2个表:tableA & tableB,则写成:–include=’renren.tableA|renren.tableB’;再如果renren库下只有2个前缀是 table的表,你还可以写成:–include=’renren.table*’。

–throttle=500:xtrabackup在备份过程中,IO操作比较多,因此需要限定一下IO操作。以免服务器压力过大,不过好像作用不太明显,也不知道是不是设置的还是过大。待测…

–socket=/data/mysql/backup/mysql.sock:指定mysql.sock所在位置,以便备份进程登录mysql.

–defaults-file=/data/dbbackup/my.cnf :如果您的/etc/my.cnf中没有使用如[mysqld3306]的片段启动mysql,则不需要这行参数,如果使用了上面的片段,那么 xtrabackup是无法解析/etc/my.cnf文件的(严格上来说是会解析错误),所以,我们需要手工完成一个my.cnf文件,文件片段如下, 只需要指定6个参数即可让xtrabackup正常工作,各参数意思请参考mysql文档:

[mysqld] datadir=/data/var
innodb_data_home_dir = /data/ibdata
innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend
innodb_log_group_home_dir = /data/iblogs
innodb_log_files_in_group = 2
innodb_log_file_size = 1G

–user=root –password=xxxxxxx :登录账号密码,root用户

–slave-info :告诉xtrabackup,最后备份文件中包含slave信息

xtrabackup可以在不加锁的情况下备份innodb数据表,不过此工具不能操作myisam。innobackupex-1.5.1是一个脚本封装,能同时处理innodb和myisam,但在处理myisam时需要加一个读锁。 更多的使用方法和注意事项,可以参考这篇文章

周末记事-weekend diary

每个周末总是安排地很充实,能跟亲爱的人儿在一起,尽可能地多做点事情,分担下LP的劳累,我想我也就能做这些了吧,尽量能让领导高兴点,小宝宝能够健康快乐的成长着,对准爸爸来说,也是一件快乐的事情。简单的列举下周末的事情吧:
1.周六,卫生大扫除,把油头满面的灶台给清理出来了,当然了过程是艰辛的,结果是快乐的。
2.和领导一起,包藕夹,剁肉馅,然后是炸,首次使用老妈教的方法,成果还不错,味道也得到领导的一致认可。
3.周日,去安装速通卡,拖了这么久还是装了,没花钱,在小区门口装的。整体满意。
4.陪领导逛街,购得鞋子一双,走路效果满意,然后是大快朵颐,在外面解决饭饭的问题,大悦城的一家西餐还不错,菜品都小巧玲珑的,不过一顿饭点了7、8种,最后才58大元,还是可以接受的。
5.逛超市,疯狂购物,储备一周的基本物资,还有想到的长远物资,纸巾、面粉之类的,最后200多块就没了。
6.汽车加油,200块。
猛然发现Cross朗庭的底商入住率好高啊,大体上看了一眼,有好伦哥,麦当劳,呷哺,等等的,新天地周边建设地真是越来越好了,赞啊。房价过了这阵子,估计应该还能涨点吧。

心情种种

昨天晚上看了个电视节目,讲“家庭煮夫”的,看的还是很感人的。不知道什么意思的,可以参考百科的解释。个人感觉其实做煮夫也没什么的,我就乐在其中,LP大人喜欢我做的菜,为什么不做呢?而且在家吃饭比在外面吃要划算多了,还卫生,何乐不为呢?最多就是洗锅刷碗略显麻烦,就当锻炼身体就是了。
LP说今天小家伙在肚子里动的很频繁,看来是什么影响了吧,希望他/她平平安安的吧。
参加公司的职业经理人培训,感觉收获还是有的,至少提出来一些解决问题的办法估计也能可行,记录下今天的,主要是将讲解解决问题的8个钥匙,深入讲解的是如何分析问题,冰山分析法,定位问题的表面原因和根本原因,然后予以解决;产品创新方面,强制关联分析法,比较耳目一新,以后的工作实践中可以尝试一下。实际上解决任何问题都要客观的面对,别强加上去一堆本来不存在的理由,这样可能会让解决办法偏离轨道。