FreeBSDでZFSをちょっとだけ試してみる

かなり前からかなり気になってたZFSを試そうと思い立った。データベースサーバに利用できるかもしれないという妄想とともに。

面倒なことは嫌いなんでコマンドだけ調べてさっくりいけるか試してみる。

構成:
FreeBSD 7.3-R i386

Pentium4

# sudo atacontrol list
ATA channel 0:
 Master: acd0 <LITE-ON CD-ROM LTN-4891S/NDS3> ATA/ATAPI revision 7
 Slave:       no device present
ATA channel 1:
 Master:      no device present
 Slave:       no device present
ATA channel 2:
 Master:  ad4 <ST3160812AS/3.ADH> SATA revision 2.x
 Slave:   ad5 <ST3160023AS/3.18> SATA revision 1.x
ATA channel 3:
 Master:  ad6 <Maxtor 6L080M0/BACE1G10> SATA revision 1.x
 Slave:   ad7 <FB080C4080/HPF0> SATA revision 1.x

# df
Filesystem         1K-blocks      Used     Avail Capacity  Mounted on
/dev/ad4s1a           507630    151778    315242    32%    /
devfs                      1         1         0   100%    /dev
/dev/ad4s1e           507630        16    467004     0%    /tmp
/dev/ad4s1f        146304578    457280 134142932     0%    /usr
/dev/ad4s1d          2008622      9642   1838292     1%    /var
homenfs:/usr/home  465826084 193902918 234657080    45%    /usr/home
homenfs:/usr/ports 465826084 193902918 234657080    45%    /usr/ports

(FreeBSD) はじめてのZFS

これの通りに適当にやってみる。i386だとカーネル再構築しろってかいてあるけど、きっとそんなのは7.1とかの出来事だから7.,3なら大丈夫だぜと信じてそのままやる。

ハンドブックはチラ見だけする。英語あんまりわかんない。

#echo 'zfs_enable="YES"' >> /etc/rc.conf
#/etc/rc.d/zfs start
# kldstat
Id Refs Address    Size     Name
 1    9 0xc0400000 a2208c   kernel
 2    1 0xc0e23000 6a500    acpi.ko
 3    1 0xc465d000 23000    linux.ko
 4    1 0xc486c000 123000   zfs.ko
 5    1 0xc498f000 3000     opensolaris.ko

# zpool create example /dev/ad5
cannot create 'example': permission denied

ぐぬぬうごかない。
2chもチラ見しながら

70 名前:名無しさん@お腹いっぱい。[sage] 投稿日:2010/01/14(木) 04:55:01
# gpart add -s 100m -t freebsd-zfs ad6
でad6p3を作成して

# zpool create testpool ad6p3
でプールを作ろうとしたら↓こんなエラー出て作れない(´・ω・`)
cannot create ‘testpool’: permission denied
ZFS: vdev failure, zpool=testpool type=vdev.open_failed
>>19と同様にシングルユーザーモードでもダメ

で、細かく情報見れないかと
# sysctl vfs.zfs.debug=1
ってやって、
# zpool create testpool ad6p3
をもう一度実行したら何故かプール作成成功…

何度か試したけど、デバッグ有効だと成功したり失敗したりする。
(デバッグ無効だと全然成功しない)
正直、原因が全く分からない…誰か心当たりある人いないですか?

aa

# sudo sysctl vfs.zfs.debug=1
vfs.zfs.debug: 1 -> 1
# zpool create example /dev/ad5
cannot create 'example': permission denied

reagan# tail -100 /var/log/messages
May 28 13:11:04 host sudo:     root : TTY=ttyp2 ; PWD=/ ; USER=root ; COMMAND=/sbin/sysctl vfs.zfs.debug=1
May 28 13:11:08 host kernel: vdev_geom_open_by_path:461[1]: Found provider by name /dev/ad5.
May 28 13:11:08 host kernel: vdev_geom_attach:112[1]: Attaching to ad5.
May 28 13:11:08 host kernel: vdev_geom_attach:133[1]: Created geom and consumerfor ad5.
May 28 13:11:08 host kernel: vdev_geom_detach:173[1]: Closing access to ad5.
May 28 13:11:08 host kernel: vdev_geom_detach:177[1]: Destroyed consumer to ad5.
May 28 13:11:08 host kernel: vdev_geom_detach:185[1]: Destroyed geom zfs::vdev.
May 28 13:11:08 host kernel: vdev_geom_open_by_path:472[1]: guid mismatch for provider /dev/ad5: 17463456876647191018 != 0.
May 28 13:11:08 host kernel: vdev_geom_open_by_guid:430[1]: Searching by guid [17463456876647191018].
May 28 13:11:10 host kernel: vdev_geom_open_by_guid:444[1]: Search by guid [17463456876647191018] failed.
May 28 13:11:10 host kernel: vdev_geom_open_by_path:461[1]: Found provider by name /dev/ad5.
May 28 13:11:10 host kernel: vdev_geom_attach:112[1]: Attaching to ad5.
May 28 13:11:10 host kernel: vdev_geom_open:516[1]: Provider /dev/ad5 not found.
May 28 13:11:10 host root: ZFS: vdev failure, zpool=example type=vdev.open_failed

なんかguidがどうのこうので失敗してるらしい。参った。

しょうがないのでkernelの値をいじる。

KVA_PAGESについての記述が/usr/src/sys/i386/conf/NOTESにあった

# Change the size of the kernel virtual address space.  Due to
# constraints in loader(8) on i386, this must be a multiple of 4.
# 256 = 1 GB of kernel address space.  Increasing this also causes
# a reduction of the address space in user processes.  512 splits
# the 4GB cpu address space in half (2GB user, 2GB kernel).  For PAE
# kernels, the value will need to be double non-PAE.  A value of 1024
# for PAE kernels is necessary to split the address space in half.
# This will likely need to be increased to handle memory sizes >4GB.
# PAE kernels default to a value of 512.
#
options         KVA_PAGES=260

値を追加して適当にmakeする。

%uname -a
FreeBSD host.l2tp.org 7.3-RELEASE FreeBSD 7.3-RELEASE #0: Fri May 28 13:34:47 JST 2010     root@host.l2tp.org:/usr/src/sys/i386/compile/toZFS  i386

うまくいったらしい。

# zpool create example /dev/ad5
cannot create 'example': permission denied

でも動かない・・・。

面倒になってきたのでここで終了。
amd64ならさくっと解決したりして。

きっとハードウェアのguid取得あたりで64bit必要なのに32bitしかないとかでこけてるんだ、っていう妄想をしながら次回へ。

preとかcodeとかでソースコードをきれいに表示できるらしい

I ♥ WordPress ソースコードを表示させるのに使うべきHTMLタグは?

自分もいままでソースコードの引用などに何を使っていいかしらなかったけど、結論としたらpreにcodeを入れ子にすればいいらしい。

またうまくページスクロールを出したりするには


/* Browser specific (not valid) styles to make preformatted text wrap */		

pre {
 white-space: pre-wrap;       /* css-3 */
 white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
 white-space: -pre-wrap;      /* Opera 4-6 */
 white-space: -o-pre-wrap;    /* Opera 7 */
 word-wrap: break-word;       /* Internet Explorer 5.5+ */
}

とすればいいらしい

FreeBSDをインストールしようとしたらRead Error: 0x04が出た

FreeBSDをインストールしようとしたらRead Error: 0x04が出た。

今回利用したのはFreeBSD7.3-R amd64。

インストールしようとしたマシンは、pentium4なマシン。おそらくamd64に対応してなかったのだろう。

以前似たような現象があったけど、そのときはブートまではうまくいき、その後で64bitに対応してねーよ、と出た気がする。

freebsdでマルチスレッドなテストコードを書いてみた。

freebsdでマルチスレッドなテストコードを書いてみた。

よいサンプルコードがあったので拝借。ありがとうございます。

コンピューター:C言語講座:マ ルチスレッドについて

このサンプルコードは、スレッドを二本作成、それぞれで適当な計算をsleepかましながらさせる、終了って流れ。

これを複数のスレッドを張りながらメモリの使用量をみてみる。

#include        <stdio.h>
#include        <sys/types.h>
#include        <pthread.h>
#define THREADS_NUM 1500

void *counter(void *arg)
{
int     i;
pid_t    pid;
pthread_t thread_id;

pid=getpid();
thread_id=pthread_self();

for(i=0;i<10;i++){
usleep(100000);
printf(“[%d][%d]%d\n”,pid,thread_id,i);
}

return(arg);
}

void main()
{
pid_t   p_pid;
pthread_t thread_id[THREADS_NUM];
int status, i;
void *result;

p_pid=getpid();

printf(“[%d]start\n”,p_pid);

for(i=0; i<THREADS_NUM; i++){
status=pthread_create(&thread_id[i],NULL,counter,(void *)NULL);
if(status!=0){
fprintf(stderr,”pthread_create : %s”,strerror(status));
}
else{
printf(“[%d]thread_id=%d\n”,p_pid,thread_id[i]);
}
}
for(i=0; i<THREADS_NUM; i++){
pthread_join(thread_id[i],&result);
printf(“[%d]thread_id%d = %d end\n”,p_pid, i, thread_id[i]);
}
printf(“[%d]end\n”,p_pid);
}

なんかインデントが消えてしまうので見にくい。

これを実行してみる。

PID USERNAME   THR PRI NICE   SIZE    RES STATE    TIME   WCPU COMMAND

29648 yousan       1   8    0  5720K  1060K nanslp 0   0:00  0.00% mt   (何もしてないとき)

29648 yousan    1500   8    0   193M   111M STOP   1   0:00  1.27% mt (一瞬で制限の1500本到達)

すれっどが1500本で188MBのメモリを仮想メモリとして割り当てようとしたらしい。一本あたり125KBの仮想メモリが必要っぽい。先述の問題ほどメモリいらないぽ。残念。

mysqlが必要とするメモリが多そうな件について

mysqlでサーバをたてていると、予想外に確保しようとするメモリが多いことに気がついた。

事前に計算で求まる気がしてたんだけど、どうやらそれだけではだめっぽい。

テスト用のサーバ設定でmymemcheckしたときのメモリ使用の概算が下記。

[ minimal memory ]
ref
* 『High Performance MySQL』, Solving Memory Bottlenecks, p125

global_buffers
key_buffer_size                     402653184   384.000 [M]
innodb_buffer_pool_size             402653184   384.000 [M]
innodb_log_buffer_size                8388608     8.000 [M]
innodb_additional_mem_pool_size      20971520    20.000 [M]
net_buffer_length                     1048576  1024.000 [K]

thread_buffers
sort_buffer_size                         8192     8.000 [K]
myisam_sort_buffer_size                  8192     8.000 [K]
read_buffer_size                         8192     8.000 [K]
join_buffer_size                        32768    32.000 [K]
read_rnd_buffer_size                     8192     8.000 [K]

max_connections                            3000

min_memory_needed = global_buffers + (thread_buffers * max_connections)
= 835715072 + 65536 * 3000
= 1032323072 (984.500 [M])

[ 32bit Linux x86 limitation ]
ref
* http://dev.mysql.com/doc/mysql/en/innodb-configuration.html

* need to include read_rnd_buffer.
* no need myisam_sort_buffer because allocate when repair, check alter.

2G > process heap
process heap = innodb_buffer_pool + key_buffer
+ max_connections * (sort_buffer + read_buffer + read_rnd_buffer)
+ max_connections * stack_size
= 402653184 + 402653184
+ 3000 * (8192 + 8192 + 8192)
+ 3000 * 262144
= 1665466368 (1.551 [G])

2G > 1.551 [G] … safe

[ maximum size of innodb_log_file_size ]
ref
* http://dev.mysql.com/doc/mysql/en/innodb-start.html

1MB < innodb_log_file_size < MAX_innodb_log_file_size < 4GB

MAX_innodb_log_file_size = innodb_buffer_pool_size * 1/innodb_log_files_in_group
= 402653184 * 1/2
= 201326592 (192.000 [M])

innodb_log_file_size < MAX_innodb_log_file_size
5242880 < 201326592
5.000 [M] < 192.000 [M] … safe

この計算だと最小で1GBぐらい、最大で1.5GBぐらいだと思われてた。

特にスレッドあたりのバッファを64KBぐらいにしたつもりだったので、そこだけで3000本のコネクションで192MB消費する予定。

で、実験用にphpからコネクションをがばがば張るコードを書いてみた。

<?php
define(‘MAX_CONNECTION’, 1400);

function main(){
for($i=0; $i<MAX_CONNECTION; $i++){
$pdo[$i] = new PDO
(‘mysql:host=db.l2tp.org;dbname=test’,
‘root’,
‘password’
);
usleep(100000 );
}

try {
$stmt = $pdo[$i]->query(“SELECT * FROM test3;”);
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
echo implode(“, “, $row) . PHP_EOL;
}
} catch (PDOException $e){
var_dump($e->getMessage());
}

$pdo = null;

}
main();
?>

なんかしらないけどこのコードがうまく通らない。途中で落ちる。

Fatal error: Uncaught exception 'PDOException' with message
 'SQLSTATE[HY000] [1135] Can't create a new thread (errno 35);
 if you are not out of available memory, you can consult the manual
for a possible OS-dependent bug' in /usr/home/yousan/phptest/thread_max.php:10

ウェイトをかけてtopでメモリをみながらやってみた。

topの各項目とそれぞれの値

PID USERNAME   THR PRI NICE   SIZE    RES STATE    TIME   WCPU COMMAND

71331 mysql       22  44    0   967M   135M ucond    0:00  0.00% mysqld   (何もしてないとき)

71331 mysql       31   4    0  1035M   135M sbwait   0:00  0.00% mysqld (コードを実行開始)
71331 mysql       68   4    0  1183M   136M sbwait   0:00  0.00% mysqld
71331 mysql      100   4    0  1311M   137M sbwait   0:00  0.00% mysqld
71331 mysql      127   4    0  1419M   137M sbwait   0:00  0.00% mysqld
71331 mysql      163   4    0  1564M   139M sbwait   0:00  0.00% mysqld
71331 mysql      225   4    0  1816M   144M sbwait   0:00  0.00% mysqld (順調にSIZEが増える)
71331 mysql      279   4    0  2035M   147M sbwait   0:00  0.00% mysqld
71331 mysql      307   4    0  2149M   150M sbwait   0:00  0.00% mysqld
71331 mysql      343   4    0  2295M   152M sbwait   0:00  0.00% mysqld
71331 mysql      362   4    0  2372M   154M sbwait   0:00  0.00% mysqld
71331 mysql       22  44    0   974M   141M ucond    0:00  0.00% mysqld (落ちた)

なぜだかガンガンSIZEの値が増えていって、2G超えて2.5GBにさしかかろうかというところで落ちてる。稼働してるサーバがFreeBSDの32bit版だったので、おそらくメモリによる制限だと思われる。

このSIZEが結構増えることがやっかいで、おかげさまでスワップアウトとかしてくれる。

気になるのは各項目の値。SIZEってなんだろう、RESって何だろう状態。調べてみた。

SIZE はプロセスサイズの合計 (text, data, stack)
RES は現在のメモリ常駐量 (SIZE と RES はいずれもキロバイト単位)

On-line Manual of “top”

SIZEの値は仮想メモリ的なものらしい。これの増減についてみてみると、当初22スレッドで967MBスタートから、68スレッドで1183MB、362スレッドでは2372MBになっているので、

22->68では46スレッド、216MB増え、68->362では294スレッド、1189MB増えてる。

適当に表にまとめる。

スレッド数 SIZE(MB) RES スレッド差分 SIZE差分 RES差分 SIZE/スレッド
22 967 135 9 68 0 7.555555556
31 1035 135 37 148 1 4
68 1183 136 32 128 1 4
100 1311 137 27 108 0 4
127 1419 137 36 145 2 4.027777778
163 1564 139 62 252 5 4.064516129
225 1816 144 54 219 3 4.055555556
279 2035 147 29 114 3 3.931034483
308 2149 150 35 146 2 4.171428571
343 2295 152 19 77 2 4.052631579
362 2372 154

だいたい、1コネクションあたり4MBのSIZEが増えるらしい。RESの方は値が小さかったので大きくみてみると、

31->343スレッドの増加で17MB増えてるので、44.87KB/スレッドの増加。MB以下が切り捨てってことはこれがスレッドあたりで実際に確保されるメモリだろうか。

スレッドのオーバーヘッドがあるがためにそんなことになってそうだ。マルチスレッドの時のオーバーヘッドを調べないと。

次回へつづく

mysqlでレプリケーションをやめる

mysqlでレプリケーションをやめる方法。

とめるんじゃなくて、やめる。スレーブじゃなくなるってこと。

mysql> change master to master_host = ”;

12.6.2.1. CHANGE MASTER TO 構文

これでいいはず。

ログをどうこうするにはpurge master or slave logsを使えばいいんだけど、change master to でホスト名を空文字にした時点でスレーブのログはなくなりました。

12.5.1.1. PURGE BINARY LOGS Syntax

q4mについて

先日、某勉強会にてQ4M(Queue for MySQL)なるものを耳にしたのでちょっと調べてみた。

最初は自分の思い込みがあって、パッケージとかデーモン的なもので、mysqlにたいするクエリを順次処理してくれるプロキシサーバ的なものかと思ってた。

でも実際には全然違うもので、mysqlのストレージエンジンの一つとして存在し、insert とselectによって。queueを実現するもの、なのだそうだ。

ウノウラボ Unoh Labs: Q4Mを触ってみる
思ってたようなものではなくてちょっと残念だけど、またいつの日か使うことがくるかもしれないのでメモ。

Javascriptで画像のサイズを取得

Javascriptで画像のロード後の縦横のピクセルを取得する方法(jQuery使用)。
単純な物だしjQuery無しでも出来ると思うけど、主に動的に画像をロードしてdivのサイズとか決定したり、画像の横幅がわからないのに、cssでmargin: auto;したい時に使う。

  var img = $("#img"); // 画像のidからオブジェクトを取得

  // 画像のロードイベント(つまり画像のロードが完了したら発動
  $(img).load(function(){
    var width = $(this).width();
    var height = $(this).height();

    window.alert("width:" + width + ", height:" + height);
  });

画像のロード完了前に同じ事をしても、ロード前なので画像のサイズは取得出来ない。0とかが返って来るはず。img要素のloadイベントはsrcで指定した画像のロードが完了した時点で発動するみたい。

\’が付いてるtermの修正方法

  1. \’が付いてるtermのnameを\’無しに全て置換する
  2. 1のtermと1のtermのnameが被るterm(\’が付いてなかったterm)を洗い出す
  3. 2のtermを参照しているtaxonomyを洗い出す
  4. 3のtaxonomyの中から、正しくないtermを参照しているtaxonomyを洗い出す
  5. 4のtaxonomyを参照しているrelationshipを洗い出し、正しいtermを参照しているtaxonomyを参照させる
  6. 正しいtermが無い場合は作成してそれを参照させる
  • 正しいtermとはnameをsanitize_titleした物とslugが一致している物とする
  • 正しくないterm及びそのtermを参照しているtaxonomyは削除する
  • catlist、suggestlistを再生成する
  • 全てのサイトで行う

修正版。

  1. \’が付いてるtermとtaxonomyを直す。
    \’が付いてるtermとそのtermの\’を取ったtermが重複しているものを探して
    それを参照しているtaxonomyが\’無しのtermを参照するように直す。
    \’無しのtermが存在しない場合は作成する。
  2. 重複するtermを参照するtaxonomyとrelationshipsを直す。
    重複するtermを参照するtaxonomy、つまり重複するtaxonomyを探して1つに減らす。
    減らす基準としてはrelationshipsが参照するtaxonomyが多い物を残すのが良いが
    検索する効率が悪いので、term_taxonomy_idでorder byをして1つめに出てきたもの
    にする。
    例えば4つの重複するtaxonomyが有った場合、1つ目のtaxonomyを選択して、残りの
    3つのtaxonomyを参照するrelationshipsに1つ目のtaxonomyを参照させる。
    3つのtaxonomyとtermは削除する。
  3. slugを修正する。
    wp_termsのnameとslugが一致するか確かめて、一致しない場合は正しいslugに直す。
    slugが重複する場合があるので、重複した物はエラーとして扱いterm_idを控える。
    エラーとして出てきたtermを見て対策を考える。
  4. taxonomyから参照されていないtermを削除する。
termから\’を取り除く。
重複するtermを洗い出し、それに関連するtaxonomyを洗い出す。
洗い出したtermを一つにし、洗い出したtaxonomyを一つにしてtermに関連づける。
洗い出したtaxonomyに影響するrelationshipsを修正する。