老王的技术手册
百度空间 | 百度首页 
               
 
文章列表
 
2009年07月01日 星期三 下午 05:13
作者:老王

用户注册之类的功能多半需要选择一下地区,所以有一份行政区划代码是很必要的,这份代码可以在国家统计局下载到(保存成file.txt文件,utf-8编码)。以前每次用时我都是现写转换代码,这次又重新写了一份,索性放到网上存着,免得以后麻烦,大家如果需要也可以瞧瞧。

首先创建一个表(utf-8编码):


CREATE TABLE `district` (
`id` int(10) unsigned NOT NULL,
`parent_id` int(10) unsigned NOT NULL,
`name` char(15) NOT NULL,
PRIMARY KEY (`id`)
);


然后编写一个脚本(utf-8编码):

set_time_limit(0);

define('ENGLISH_BLANK', chr(32));
define('CHINESE_BLANK', chr(227) . chr(128) . chr(128));

mysql_connect('localhost', 'root', '');
mysql_select_db('test');

mysql_query("SET NAMES 'utf8'");

$parent = array();

$handle = fopen('file.txt', 'r');
while (!feof($handle)) {
    $data = explode(CHINESE_BLANK, str_replace(
        ENGLISH_BLANK . ENGLISH_BLANK, CHINESE_BLANK, trim(fgets($handle))
    ));

    if (!is_numeric($id = array_shift($data))) {
        continue;
    }

    $level = 0;
    while (($value = array_shift($data)) !== false) {
        if ($value == '') {
            $level++;
        } else {
            break;
        }
    }
    $parent[$level] = $id;

    $parent_id = $level ? $parent[$level - 1] : 0;

    $name = $value;
    if (count($data)) {
        $name .= implode('', $data);
    }

    $sql = "
        INSERT INTO district (id, parent_id, name)
        VALUES ({$id}, {$parent_id}, '{$name}')
    ";

    mysql_query($sql);
}
fclose($handle);


注:有的地区名字带有*符号:SELECT * FROM `district` WHERE `name` LIKE '%*%',可以手动处理。

截止2008年12月31日的数据是3525行,运行后可以确认一下是否正确。如果想更高效,还可以把数据转换成先根遍历树风格的,恕不详述。
 
2009年06月28日 星期日 上午 10:41
作者:老王

命令ps aux中的TIME是指什么时间。

经验主义会让我们惯性的认为这个时间是程序运行的时间,实际上如果你通过man ps查看一下手册,就会发现这个时间实际上是程序累计占用的CPU时间。

如何判断64位CPU装了32位的操作系统。

总有一些运维人员这么干,所以不得不防。判断操作系统的位数很简单,只要使用uname -i即可,如果是32位的话,则一般显示i386,如果是64位的话,则一般显示x86_64。问题的重点在于判断CPU的位数,查看CPU的信息很简单,无非就是cat /proc/cpuinfo,但这里哪些信息能表明位数呢?高人可以通过model name来判断,不过对多数人来说,这样的方法缺少可操作性,更好的方法是查看flags里是否有lm选项,lm选项的意思是Long Mode. (64bit Extensions, AMD’s AMD64 or Intel’s EM64T).,有的话就说明是64位,没有就是32位。

CPU feature flags and their meanings

玩转TOP命令

top命令有很多方便的操作,比如执行top命令后按1键就可以展开CPU列表,按c键就可以查看命令完整路径。还可以通过shift+f或者shift+o把进程排序,更多参数通过按键h或者?查询。

管道符中变量范围的问题

先看一个例子,先用read命令给变量赋值,再分别打印:

echo "a b c" | read x y
echo $x
echo $y

结果你会发现$x, $y都没有设置。

echo "a b c" | (read x y; echo $x; echo $y)

这样就OK了,这是因为管道符后面产生的变量仅在子SHELL中有效,类似的还可以采用这样的方式:

echo "a b c" | while read x y; do
    echo $x; echo $y
done

watch监控程序

例如用watch监控mysql:watch -n 1 mysqladmin processlist

更方便的history功能

需要历史操作记录的时候,大家基本上都是采用history | grep ...的操作方式,实际上还有更方便的history功能,在man bash里的reverse-search-history部分能查看到相关介绍,操作方式就是ctrl+r,然后键入部分命令就会自动查找,找到后直接回车即可。比如说每次重启动nginx都要不厌其烦的kill -HUP `cat /path/to/nginx.pid`,通过使用reverse-search-history技巧,操作会方便快捷很多。
 
2009年06月27日 星期六 上午 10:18
作者:老王

Xtrabackuppercona开发的产品,可以看做是InnoDB Hotbackup的免费替代品。

先看看如何安装Xtrabackup,下载最新的版本,最简单的安装方式无疑是使用RPM包,不过如果你想使用源代码方式安装的话,则会发现其安装方式有点古怪,这是因为它采用的在MySQL源代码上打补丁构建的方式。

wget http://www.percona.com/mysql/xtrabackup/xtrabackup-0.8.tar.gz
tar zxf xtrabackup-0.8.tar.gz
cd xtrabackup-0.8
./configure
make

进行到这里时,千万别惯性使然接着make install,那样就会接着安装MySQL了,正确方法是接着:

cd innobase/xtrabackup/
make
make install

如此一来,就会在你的/usr/bin目录里安装上两个有用的工具:xtrabackup,innobackupex-1.5.1:

xtrabackup可以在不加锁的情况下备份innodb数据表,不过此工具不能操作myisam。
innobackupex-1.5.1是一个脚本封装,能同时处理innodb和myisam,但在处理myisam时需要加一个读锁。

按如上的介绍,由于操作myisam时需要加读锁,这会堵塞线上服务的写操作,而innodb没有这样的限制,所以数据库中innodb表类型所占的比例越大,则越有利。实际应用中一般是直接使用innobackupex-1.5.1方法,它主要有三种操作方式,按手册中的介绍:

Usage:
innobackup [--sleep=MS] [--compress[=LEVEL]] [--include=REGEXP] [--user=NAME]
           [--password=WORD] [--port=PORT] [--socket=SOCKET] [--no-timestamp]
           [--ibbackup=IBBACKUP-BINARY] [--slave-info] [--stream=tar]
           [--defaults-file=MY.CNF]
           [--databases=LIST] [--remote-host=HOSTNAME] BACKUP-ROOT-DIR
innobackup --apply-log [--use-memory=MB] [--uncompress] [--defaults-file=MY.CNF]
           [--ibbackup=IBBACKUP-BINARY] BACKUP-DIR
innobackup --copy-back [--defaults-file=MY.CNF] BACKUP-DIR

第一个命令行是热备份mysql数据库。

The first command line above makes a hot backup of a MySQL database.
By default it creates a backup directory (named by the current date
and time) in the given backup root directory. With the --no-timestamp
option it does not create a time-stamped backup directory, but it puts
the backup in the given directory (which must not exist). This
command makes a complete backup of all MyISAM and InnoDB tables and
indexes in all databases or in all of the databases specified with the
--databases option. The created backup contains .frm, .MRG, .MYD,
.MYI., .TRG, .TRN, .opt, and InnoDB data and log files. The MY.CNF
options file defines the location of the database. This command
connects to the MySQL server using mysql client program, and runs
ibbackup (InnoDB Hot Backup program) as a child process.

带有--apply-log选项的命令是准备在一个备份上启动mysql服务。

The command with --apply-log option prepares a backup for starting a MySQL
server on the backup. This command expands InnoDB data files as specified
in BACKUP-DIR/backup-my.cnf using BACKUP-DIR/ibbackup_logfile,
and creates new InnoDB log files as specified in BACKUP-DIR/backup-my.cnf.
The BACKUP-DIR should be a path name of a backup directory created by
innobackup. This command runs ibbackup as a child process, but it does not
connect to the database server.

带有--copy-back选项的命令从备份目录拷贝数据,索引,日志到my.cnf文件里规定的初始位置。

The command with --copy-back option copies data, index, and log files
from backup directory back to their original locations.
The MY.CNF options file defines the original location of the database.
The BACKUP-DIR is a path name of a backup directory created by innobackup.

Xtrabackup还可以用来moving InnoDB tables between servers,更多的内容可以参考官方文档例子

参考链接:Xtrabackup online backup for InnoDB/XTraDB(pdf)
 
2009年06月25日 星期四 下午 07:43
作者:老王

升级法则第一条:最好不要升级。除非必要,否则任何改变现状的升级操作都有可能给你带来不必要的烦恼。

MySQL4升级到5,本来打算直接使用mysql_upgrade之类的工具升级数据文件,不过考虑从4到5变化太大,便决定使用mysqldump导出数据文件:

先在旧的MySQL4上导出数据:

/path/to/mysql4/bin/mysqldump --all-databases > backup.sql

再在新的MySQL5上导入数据:

/path/to/mysql5/bin/mysql < backup.sql

在导入SQL文件的时候遇到了Unknown command错误,网上查询,发现这个问题可能是由下列原因引起:

第一:可能是default-character-set设置错误。
第二:可能是max_allowed_packet设置过小。

不过这些配置我都已经在客户端配置文件$HOME/.my.cnf里设置过了,所以不可能是这些问题,最后发现竟然是因为在导入导出数据时使用了不同版本的工具所致,换成/path/to/mysql4/bin/mysq导入,不再出现Unknown command错误,兼容性做得不好啊,以后遇到类似问题要注意了。

第三:可能是因为导入导出数据时使用的工具版本不一致所致。

所有的原因中,第三点尤其容易被忽视,如果你遇到了类似的问题,不妨对照这三点一一排查。
 
2009年06月22日 星期一 下午 04:37
作者:老王

Tokyo Cabinet是一个高效键值数据库,不过和Redis相比,它没有内建的网络接口支持,所以得额外安装,作者已经写好了,就是Tokyo Tyrant

分别下载源代码:

wget http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.27.tar.gz
wget http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.29.tar.gz

注:tokyocabinet源代码包里的Makefile.in文件内有很多用法演示,强烈推荐看看。

两个软件包的安装都很简单,就是Linux下人人皆知的三板斧:

./configure & make & make install

安装完成后,执行ttserver命令就会启动服务,缺省情况下,没有给任何参数使用的是内存数据库。

网络接口Tokyo Tyrant支持HTTP操作方式,我们新开一个命令行窗口来验证一下:

curl -X PUT http://127.0.0.1:1978/foo -d bar
curl http://127.0.0.1:1978/foo

前面是通过执行ttserver命令的方式来启动服务的,实际上还有更优雅的方式,那就是通过ttservctl脚本。

vi /usr/local/sbin/ttservctl

通过ttservctl脚本启动服务缺省使用的是文件数据库,有四种类型的文件数据库,具体使用的是哪种可以通过ttservctl脚本里的dbname扩展名来判断:

.tch - Hash
.tcb - Btree
.tcf - Fixed-length
.tct - Table


每种文件数据库都分别对应这一个mgr命令行工具,可以通过如下命令来查看:

ls /usr/local/bin/*mgr(同时还有很多测试工具,ls /usr/local/bin/*test)

比如说,tch对应的就是tchmgr,tcb对应的就是tcbmgr,tcf对应的就是tcfmgr,tct对应的就是tctmgr。剩下的tcamgr相当于是一个数据抽象层,各种类型都能操作,而tcrmgr相当于是一个远程数据接口,它们的使用都不难,可以对照man手册自己试试:

tchmgr create db
tchmgr put ./db foo bar
tchmgr get ./db foo

如果使用tcamgr的话,在创建数据库的时候要指明扩展名,以便抽象层能判断出要创建的类型:

tcamgr create db.tch
tcamgr put ./db.tch foo bar
tcamgr get ./db.tch foo

要想测试tcrmgr的话,记得先启动ttservctl再测试:

tcrmgr put localhost foo bar
tcrmgr get localhost foo

相对比较NB的是Table类型数据库的使用,可以模拟保存关系数据库中的表:

tctmgr create articles
tctmgr put articles 1 "title" "foo_1" "content" "bar_1"
tctmgr put articles 2 "title" "foo_2" "content" "bar_2"

第一个操作:

tctmgr list -pv articles

会输出如下内容:

1 title foo_1 content bar_1
2 title foo_2 content bar_2

第二个操作:

tctmgr get articles 1

会输出如下内容:

title foo_1
content bar_1

第三个操作:

tctmgr search -pv articles title STREQ foo_2

会输出如下内容:

2 title foo_2 content bar_2

就好像操作关系数据库一样,STREQ在这里是等于的意思,在man tctmgr里能查到完整的命令列表:

The operator of the 'search' subcommand is one of "STREQ", "STRINC", "STRBW", "STREW", "STRAND", "STROR", "STROREQ", "STRRX", "NUMEQ", "NUMGT", "NUMGE", "NUMLT", "NUMLE", "NUMBT", "NUMOREQ", "FTSPH", "FTSAND", "FTSOR", and "FTSEX". If "~" preposes each operator, the logical meaning is reversed. If "+" preposes each operator, no index is used for the operator. The type of the '-ord' option is one of "STRASC", "STRDESC", "NUMASC", and "NUMDESC". This command returns 0 on success, another on failure.

具体的含义可以在API文档中关于tctdbqryaddcond的部分查到。

同时,网络接口Tokyo Tyrant不仅支持HTTP的操作方式,同时还兼容Memcached协议,这无疑是个很实惠的优点,比如说对于PHP来说,可以使用现成的Memcached扩展,而不用再费力写新的扩展:

$instance = new Memcache();
$instance->connect('127.0.0.1', '1978');
$instance->set('foo', 'bar');
echo $instance->get('foo');

不过这个优点也是有代价的,在使用Memcached方式连接Tokyo Tyrant时,Tokyo Tyrant会忽略flags,exptime,cas unique这几个标志位,其中忽略flags标志位意味着,PHP客户端要自己负责反序列化。同时,在使用Memcached方式连接Tokyo Tyrant时,就不能使用Tokyo Cabinet的高级功能了,这时的Tokyo Cabinet退化成一个彻彻底底的键值数据库。

和Memcached客户端相比,使用专用客户端功能会更丰富一些,PHP的不多,就PHPTyrant还像点样。

总体感觉,和Redis相比,Tokyo Cabinet的功能易用性要稍差一些,同时,由于Tokyo Cabinet是使用同步数据磁盘操作的方式,而Redis是使用异步数据磁盘操作的方式,所以Redis的效率也会更高一些,但反过来看,一旦出现故障,Redis丢失数据的可能性也要比Tokyo Cabinet大一些。还有一个明显的区别是,Redis会把所有的数据导入到内存里来操作,所以如果你的内存不够大的话,Tokyo Cabinet则会是更合理的选择。

相关链接:

DBMによるテーブルデータベース
DBMによるテーブルデータベース その参
采用tokyo cabinet搭建表格型DBM(需翻墙)
tokyo tyrant 在 php 上不能自动反序列化的问题
利用Tokyo Tyrant构建兼容Memcached协议、支持故障转移、高并发的分布式key-value持久存储系统

补充说明:不会翻墙的可以使用Web代理:zend2.com
 
     
 
 
文章分类
 
 
Os(29)
 
 
 
Php(56)
 
 
 
 
 
     
 
关注工具
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
     
 
在线资料
 
 
 
 
 
 
 
 
 
 
 
 
 
 
     
 
其它
 
已有人次访问本空间
 
订阅RSS  什么是RSS?

您也想拥有这样的空间?请点此申请。
     


©2009 Baidu