MySQL 日本語データが文字化け

以前にもありましたが、MySQLでの日本語の文字化け
データをインサートして内容を表示すると以下のような状態。

mysql> select * from temperature_new;
+———-+——-+———+——+——+——————+
|DATE     | KOSUI | AVERAGE | HIGH | LOW  | TENKI
| +———-+——-+———+——+——+——————+
| 20130301 | 16.5  | 13.6    | 17.6 | 7.9  | ?                |
| 20130302 | 0.0   | 8.7     | 12.0 | 4.8  | ?                |
| 20130303 | 0.0   | 6.8     | 9.7  | 3.7  | ????             |
| 20130304 | 0.5   | 6.4     | 9.4  | 4.2  | ?????            |
DB全体ではCharsetをUTF8に設定していましたが、実はCharsetはdatabaseごとの設定値で、databaseが作成された時点でcharsetは決定されます。このdatabase毎のcharsetはalterコマンドで変更が可能ですが、さらにその設定はテーブル作成時のdatabaseの設定によってテーブルごとの設定値となるようです。そして、テーブルごとのcharsetの設定値は変更も不可能の模様。
今回は以下のようにdatabaseのcharsetを変更後、さらにテーブルを再度作成して問題を解消できました。

mysql> show variables like ‘char%’;
+————————–+—————————-+
| Variable_name            | Value                      |
+————————–+—————————-+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+————————–+—————————-+
8 rows in set (0.00 sec)

mysql> alter database weather character set utf8
-> ; Query OK, 1 row affected (0.02 sec)

mysql> show variables like ‘char%’;
+————————–+—————————-+
| Variable_name            | Value                      |
+————————–+—————————-+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+————————–+—————————-+
8 rows in set (0.00 sec)

character_set_databaseはデータベース毎の設定で、connectしているdatabase毎に異なる値を示す可能性があります。

Specified JDBC Driver com.mysql.jdbc.Driver class not found

PCの引越しをしていますが、Eclipse上で以前作成したWebApplicationがローカルでDBにアクセスする際にエラーになりました。

一応、Reference Library には
mysql-connector-java-5.1.20-bin.jar
へのパスが張ってあるのですが、Driverのクラスが見つからないようでした。
最終的にはWeb Applibrary(WEB-INF/libへのファイルコピー)にファイルを追加することによって、動作しました。
Hibernate実行時に使用されるライブラリはWeb-INFに存在しないといけないのかも知れません。

 

MySQL DB のバックアップとリストア

Linuxサーバ(商用)側では毎日mysqldumpで全データベースのバックアップを取得しています。このバックアップを使用してDBをPCにリストアしようとしたのですが、バックスラッシュの処理なのでしょうか、エラーが出てしまい、リストアできませんでした。

C:\Users\XXXXXXXX\Downloads>mysql -u root -p serendipity < serendipity.dmp Enter password: ***** ERROR at line 238: Unknown command ‘\”.

いろいろ試しているうちに、Serendipityに関するバックアップの部分になにか問題があることがわかりました。とりあえず、全データベースのバックアップではなく、各DBに関して別個のバックアップも取るようなスクリプトもCronに追加しておきました。

再確認の為、Mysqlのバックアップとリストアのまとめ
バックアップ:
$ mysqldump -u root -x –all-databases > dump.sql
$ mysqldump -u root データベース名 > dump.sql
リストア:
$ mysql -u root -p < dump.sql
$ mysql -u root データベース名 < dump.sql

Jboss Hibernate上でのKeep Alive

先日の、Jboss上のHibernateがMySQLにアクセスできなくなるという話。
Jboss上のDBにアクセスできない
一つの解決方法として、Keep Aliveを組み込んでみました。
Jboss上にServletを作成し、起動時での自動起動及び、Threadの無限ループで30分ごとにサーチを掛けるだけの物です。このKeep Aliveを導入するまでは毎日朝、サーバにアクセスしようとするとHibernateがMySQLにアクセスできない現象が発生していましたが、このKeep Aliveを組み込んでからはその現象は解消しました。サーブレット内のコードはこんな感じです。

public class KeepAlive extends HttpServlet {
 private static final long serialVersionUID = 1L;
 static KeepAliveMain t = null;

    public KeepAlive() {
        super();
    }

  public void init(ServletConfig config) throws ServletException {
  t = new KeepAliveMain();
  t.start();
 }

 }
class KeepAliveMain extends Thread{

 public KeepAliveMain() {
  // TODO Auto-generated constructor stub
  super();
 }
 public void run(){
  Logger logger = Logger.getLogger(“mylog”);
  Date d = new Date();
  logger.warn(“”+d+”: “+this.getClass().getName()+” KeepAliveMain(service) started”);
  for (int i=0;;i++){
   d = new Date();
   logger.warn(“”+d+”: KeepAliveMain(service):”+i);
         YearDao yearDao = new YearDao();;
      List<Year> yearList = null;
   yearList = yearDao.searchAll();
   yearList.isEmpty();
   try {
    Thread.sleep(30*60*1000);
   } catch (Exception e){
    e.printStackTrace();
   }
  }
 }
}

GetやPostは実装しないで、init()だけで、localのThreadクラスに起動をかけているだけです。

自分のHackとしてはこれでもいいのですが、平行してネットで現象を調べていくと要は、Hibernateにデフォルトで付属しているコネクションプールは試験的なのもで長時間未使用状態が続くとMySQL(DB)側でコネクションを切断してしまうのにたいして、Hibernate側ではまだコネクションが残っていると考えて問題が発生するようです。
また、Jbossのログにはこんなメッセージが出ています。

09:26:48,260 INFO  [DriverManagerConnectionProvider] Using Hibernate built-in co
nnection pool (not for production use!)

Hibernateを使うのであればコネクションプールはThirdPartyのものを使えということのようです。Hibernateのマニュアルにもそのあたりの記述がありました。
次はこのコネクションプールの設定方法が調査項目になります。

Jboss上のDBにアクセスできない

最近、Jboss上のDBにWebService経由でアクセスしようとするとExceptionが発生してデータベースにアクセスできません。Jbossを再起動すれば解消するのですが、今日は少し調査してみました。
Jbossのコンソールログに現れるのは以下のメッセージです。

09:24:14,157 INFO  [STDOUT] Hibernate: select temperatur0_.date as date30_, temp
eratur0_.average as average30_, temperatur0_.high as high30_, temperatur0_.low a
s low30_ from temperature temperatur0_ where temperatur0_.date=?
09:24:14,371 WARN  [JDBCExceptionReporter] SQL Error: 0, SQLState: 08S01
09:24:14,371 ERROR [JDBCExceptionReporter] Communications link failure

The last packet successfully received from the server was 83,742,985 millisecond
s ago.  The last packet sent successfully to the server was 69 milliseconds ago.
09:24:14,466 ERROR [STDERR] AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode:
 faultString: org.hibernate.exception.JDBCConnectionException: could not execute
 query

おそらく、HibernateからMySQLへのコネクションがMySQL側では切断されているのにHibernate側ではまだそれが使用可能と思っているような気はします。Tomcatではこの現象は観察していません。もし、そうであれば、Hibernateが使えなくなったコネクションを切断して、最終的には新たなコネクションを再作成して動きそうな気はするのですが、一旦この状態になると自律的には解消しないようです。
Hibernateのマニュアルを少しみると、Connection Poolに関して、実装は試験用なのでThirdpartyのコードを使うことを推奨しているようにも見えました。そのようなライブラリもパッケージには入っているようです。
そのあたりも学習するとして、本当にIdle時間が長くてTimeoutしているのかどうか、ダミーのThreadから定期的にDBへのアクセスをさせてみようかなと思います。所謂KeepAliveですね。KeepAliveで状況が変わるかを確認してさらにTuningしてみようと思います。

Table Changes とMySQL triggerの設定

Hibernateのキャッシュ関連でテーブル変更の記録をとるTriggerとその記録Tableのサンプルを作成してみました。
作業中にHibernateがつかんでいるテーブルに関してはTriggerを作成することができませんでした、…実際にはテーブルに関して変更がロックされている感じでした。Tomcatを停止して作業すると瞬時に完了しました。

ログテーブルのSample:
CREATE TABLE table_changes (
  SERIAL_NO  MEDIUMINT NOT NULL AUTO_INCREMENT,
  DATETIME  DATETIME,
  TABLENAME VARCHAR(30),
  METHOD    VARCHAR(10),
  PRIMARY KEY (SERIAL_NO)
);

Triggerのサンプル:
CREATE TRIGGER triggerHourlyInsert AFTER insert ON hourly FOR EACH ROW
  INSERT INTO table_changes  (DATETIME,TABLENAME,METHOD)
         VALUES (now(),’hourly’,'insert’);
CREATE TRIGGER triggerHourlyUpdate AFTER update ON hourly FOR EACH ROW
  INSERT INTO table_changes  (DATETIME,TABLENAME,METHOD)
         VALUES (now(),’hourly’,'update’);
CREATE TRIGGER triggerHourlyDelete AFTER delete ON hourly FOR EACH ROW
  INSERT INTO table_changes  (DATETIME,TABLENAME,METHOD)
         VALUES (now(),’hourly’,'delete’);

こんな感じで管理が必要なテーブルに対してTriggerを設置しておけばそのテーブルに対する変更の履歴をいつでも確認することが可能となります。

 

sarコマンドのsteal項目

AWSのminimum構成に色々載せて遊んでいるわけですが、その中の一つにApatcheのアクセスログからアクセス相手のアドレスなどの集計を取っています。本来は新規のログのみの解析を行い統計結果だけを集積していくべきですが、サーバ開始ごろに作った機能でしたのでアクセスログ1行についてMySQLの1レコードを作成して保存。さらに1時間に1回そのログのテーブルからアクセス元のIPアドレスリストを作成するという作業をさせています。SQLでいうとこんな感じ。
createSQL(){
print SELECT distinct IPADDRESS INTO OUTFILE \”/tmp/address1_$$.lst\” FROM accesses ORDER BY IPADDRESS;
}
Kshellの中でセレクト文をtempファイルに作成してそれをmysqlの入力にして実行しています。ここでaccessesテーブルのサイズが現在4万件程度です。
 訂正:CPUの使用率が高かったのはこの部分ではありませんでした。検索結果を元に各項目に対してさらにSQL文を作って大量にバッチ処理をしている部分でした。一つ一つの構文は単純なselect文でしたが500行くらいあったのでそこでCPUの使用率が上昇していたみたいです

このコマンドが非常に時間が掛かっていることに最近気がつきました。5分以上掛かっているかも知れません。topで見てもmyslqdのCPU使用率は高止まりしています。さらにsarの出力をみると、こんな感じでした。
03:40:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
03:50:01 AM     all      0.09      0.09      0.10      1.06      0.02     98.64
04:00:01 AM     all      0.12      0.00      0.07      0.48      0.02     99.32
04:10:01 AM     all      0.07      0.00      0.09      0.25      0.02     99.58
04:20:01 AM     all      7.85      0.00      0.29      4.04     37.44     50.37
04:30:01 AM     all      0.22      0.00      0.28      0.47      0.03     99.00
04:40:01 AM     all      0.06      0.00      0.08      0.12      0.04     99.70
カラムがずれていますが、ここで気がついたのが%stealのところ。4:20のところで37.44という数値になっています。マニュアルにはこうありました。
 %steal
                     Percentage of time spent in involuntary wait by the  vir-
                     tual  CPU  or  CPUs  while  the  hypervisor was servicing
                     another virtual processor.
AWSのサーバはVirtualなので実際にはもっとキャパシティの大きなシステム上に動作している小さなエンティティと考えられます。この小さなVirtualサーバがCPUを使用したくても規定値以上は使用できないため”steal”の数値が上昇しているようです。実サーバで単にCPUの使用率が100%になっているのと基本的には同じことと思いますが、過去の経験ではCPUの使用率が100%になるとサーバ全体の動作に関しても問題が派生することが多いのですが、Virtual環境の場合、より大きな環境のコントロール下での状況なのでもしかしたらよりこの一つのサーバ環境としてはより安定的なのではと感じました。
まあ、SQLのクエリーが遅いことに関してはどちらも同じとは思いますが…..

MySQL テーブルコピーの方法

ネットで調べたテーブルのコピー方法。

結構使えるのでメモ。特にDBを超えてコピーもできるので試験環境用のデータベースを作ったりするのにも便利。

こんな感じ。