2010年3月1日月曜日

MySQLで「Too many connections」のエラー

どうも、俺@週明け仕事中です。

週末、とあるシステムでMySQLの「Too many connections」が多発する障害が発生しました。
その時調べたメモです。

このエラーは、「コネクションの数が多すぎてもう接続できないよー」というものです。
MySQLの設定は
mysql> show global variables like '%max_connection%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 100 |
+-----------------+-------+
という状態です。
デフォルト値が「100」なのだそうで、まず単純にコネクション最大数を増やします。
mysql> set global max_connections = 256;
コネクション数が増えるので、CPU負荷とメモリ使用量に注意が必要です。

他に注目すべきは、
mysql> show status like '%threads_%';
+------------------------+--------+
| Variable_name | Value |
+------------------------+--------+
| Threads_cached | 6 |
| Threads_connected | 4 |
| Threads_created | 140909 |
| Threads_running | 3 |
+------------------------+--------+
うわー!エラいことなっとる!
ここの項目の見方は、
Threads_cached ... スレッドキャッシュでキャッシュされているスレッドの数。
Threads_connected ... 現在生成されているスレッドの数。
Threads_created ... 起動してから生成されたスレッドの数。この値が大きい場合はthread_cache_sizeの値を大きくした方が良いかも。
Threads_running ... 現在動作中のスレッド数。

と言うわけで、今回の件ではthread_cache_sizeの値を増やしておきます。
mysql> set global thread_cache_size = 64;
と、共にwait_timeoutの状況をチェック。
mysql> show global variables like 'wait_timeout%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| wait_timeout | 28800 |
+--------------------------+-------+
28800秒、つまり8時間に設定されているので、もう少し縮めて起きます。
mysql> set global wait_timeout = 3600;
1時間にしました。
wait_timeoutは接続があってスレッドが生成され待機状態(アイドル状態)になって○秒経過したら接続を切るというもの。
mysql_pconnect()やPDOでの持続的接続とかでも、wait_timeout秒数経過すると切断されます。(と、思う、、)
ちなみに、wait_timeouをmy.cnfに設定する場合は、
# vim /etc/my.cnf
set-variable = wait_timeout = 3600
のようにするらしい。


また経過監視します。以上どぇぇす。

2010年2月25日木曜日

[java]logback+slf4jでロギング

どうも、俺@仕事中です。
今日はlogbackを使ってログを取得する方法をメモします。
※OS:CentOS 4.3
※java:1.6.0_18

ライブラリを以下から取得。
Logback:http://logback.qos.ch/
SLF4j:http://www.slf4j.org/

ダウンロードしたアーカイブを解凍して、
slf4j-api-1.5.10.jar
logback-core-0.9.18.jar
logback-classic-0.9.18.jar
をjavaのCLASSPATHに通します。

では、サンプルソース。

import org.slf4.Logger;
import org.slf4j.LoggerFactory;

public class LogSample {
private static Logger logger = LoggerFactory.getLogger(LogSample.class);

public static void main(String[] args) {
logger.info("INFO");
logger.debug("DEBUG");
}
}

で、設定ファイル(logback.xml)を作成します。これもCLASSPATHの通ったディレクトリへ設置します。
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!-- ファイル出力 -->
<appender name="FILE_OUT" classs="ch.qos.logback.core.rolling.RollingFileAppender">
<File>sample.log</File>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] %class{0} %line : %msg %n</pattern>
</layout>

<!-- 日付でローテート -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>sample.%d{yyyy_MM_dd}.log</FileNamePattern>
</rollingPolicy>
</appender>



# <!-- ファイルサイズでローテート -->
# <appenderclass="ch.qos.logback.core.rolling.RollingFileAppender">
# <File>sample.log</File>
# <layout class="ch.qos.logback.classic.PatternLayout">
# <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] %class{0} %line : %msg %n</pattern>
# </layout>
# <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
# <FileNamePattern>sample.log.%i</FileNamePattern>
# <MinIndex>1</MinIndex>
# <MaxIndex>10</MaxIndex>
# </rollingPolicy>
# <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
# <MaxFileSize>512MB</MaxFileSize>
# </triggeringPolicy>
# </rollingPolicy>
# </appender>


<logger name="com.blogger.koexuka.app">
<level value="warn" />
<appender-ref ref="FILE_OUT" />
</logger>
以上どぇぇーす。

2010年1月29日金曜日

Zend_Db_Table_Row::refresh()について

どうも、俺@仕事中@スノボ前です。

今日久しぶりにZend_Framework案件でソース書いてて、抽象クラスZend_Db_Table_Row_Abstractの
protected $_cleanData
protected $_data
って「これわな~に?おいしいの?」と思ってました。

オブジェクトに値をセットしてvar_dump($zend_db_table_row)してみると、両方のフィールドに同じ値がセットされています。
公式にも詳しい説明がなかったのですが、
どうやらこれは、DBからSELECTしてきたデータは「$_creanData」に、後でセットした値が「$_data」に入っているようです。
で、
$zend_db_table_row->refresh()
メソッドを使ってrefresh()すると、$_dataフィールの値がリセットされて$_cleanDataになりました!

つまり、フォームからユーザがデータを入力してエラーチェックした結果、エラーが存在して元に値に戻したいとき、refresh()メソッドで値を元に戻せちゃいます。
なんて便利な!


以上、どえぇぇぇぇす。

2010年1月23日土曜日

rubyでロジックとビューの分離

どうも、俺@rubyはじめました、です。
Web系の仕事してて、これだけ「ruby」という単語を目にすることが多く「Ruby on railsを真似たフレームワークが・・」と耳にするのでちょっとカジっとかないと、という訳ではじめましたruby。
個人的に「phpとperlとjavaしか知りません」だと対外的に格好つかないかなと思ったわけです。


で、まだまだ勉強し始めなのですが、
WEBアプリを作る際にruby(RoRではない)でロジックとビューを分ける方法について。
例えばphpでは、
// ロジック側(logic.php)
<?php
$a = "foo";
$b = "bar";

require "view.tpl.php";
とロジックを書いておけば、ビューでは
// ビュー側(view.tpl.php)
<html>
<body>
$aの値はです。
$bの値はです。
とできます。

同じようなことをrubyでやるには、
1)ヒアドキュメントを使う
// ロジック側(logic.rb)
a = "foo"
b = "bar"

print "Content-type:text/html\n\n"

print <<__HTML_END__
"<html>
<body>
$aの値は" + a + "です。
$bの値は" + b + "です。"
__HTML_END__

2)ERBを使う
// ロジック側(logic.rb)
require "erb"

print "Content-type:text/html\n\n"

a = "foo"
b = "bar"
tplFile = "view.tpl.html"
erb = ERB.new(File.read(tplFile))
erb.run
としてビュー側で
// ビュー側(view.tpl.html)
<html>
<body>
aの値は<%=a%>です。
bの値は<%=b%>です。
とやります。

というか、もっとスマートな方法あれば教えてください!
もっと勉強します。。

以上っっっっです。

2010年1月21日木曜日

vimで画面分割を移動する

どうも、俺@仕事もうちょいです。
今日はvimで画面分割して右にあるものを左へ、左へあるものを右へ、
または上にあるものを下へ、上にあるものを右へ左へなどやる方法についてです。

上下分割
:sp

ファイルを指定して上下分割
:sp [filename]


左右分割
:vsp

ファイルを指定して左右分割
:vsp [filename]


右の画面を左へ
(右側の画面にフォーカスを合わせた状態で)
Ctrl+w L

上の画面を下へ
(上側の画面にフォーカスを合わせた状態で)
Ctrl+w J


つまり画面を移動させるには、Ctrl+w & viのキーバインドでOKなのです。
H(左)J(下)K(上)L(右)


以上でぇぇす。