MYSQLでのバイナリ取り扱いが難しい

MYSQLを使用した「らじる☆らじる」の録音と再生  で紹介していた録音が先週の早朝(2018年1月24日午前6時過ぎ)に突然動作しなくなりました。

そのような時刻に何か設定変更をしているはずもなく、停電などによるサーバー停止なども確認できませんでした。

色々原因を探っていたところ、どうやらMYSQLのinto dumfile 文とload_file()関数が期待通りの挙動をしなくなっていたことが先日わかりました。

具体的には、

 select sound into dumpfile "$file" from t_sound;

で、secure_file_priv で指定されたディレクトリにファイルを作成すると、所有者が通常とは異なるユーザ(ユーザー名:mysql)となってしまうのです。このため、作成したファイル$fileが消去も含めてアドミニストレータ権限でないとできなくなっていたのです。

同様に、load_file()関数も所有者がmysqlであるファイルでないと、NULL値となってしまっていました。

時間帯を考慮すると、おそらく自動アップデートによりレビジョンアップが行われたのだと推測できます。この動作は「ファイルはすべてのユーザーから読み取り可能」「上記の条件が満たされていないために、ファイルを読み取ることができない場合、この関数は NULL を返します。」というload_file()関数の仕様を満たしています。しかし、私が期待していた「ゆるい」動作ではなくなってしまったということです。

MYSQLでのバイナリデータの取り扱いを更に増やしてゆこうと考えていたところだったので困っています。バイナリを使わない下記のような方法も考えてみましたが、mysqldへの負担が半端ではなかったため、現在停止させています。

 

 


登録側

#!/bin/bash

mysql nhkradio << _SQL_
create table if not exists t_sound(
 seq int,
 estimate datetime,
 sub_seq int,
 sound int,
 INDEX(estimate)
);
create table if not exists t_volume(
 seq int primary key auto_increment,
 DLdate datetime,
 estimate datetime,
 number int,
 fullname varchar(100),
 rms double,
 INDEX(estimate)
);
_SQL_

if [ -z $num ] ; then echo "num が不明";exit;fi
if [ -z "$estimate" ] ; then echo "推定時刻が空白";exit;fi
if [ -z "$fullname" ] ; then echo "URL が不明";exit;fi
if [ -z "$rms" ] ; then echo "音量 が不明";exit;fi
if [ ! -e $num.raw ]; then echo "rawファイルがない";exit;fi

seq=`\
mysql nhkradio -N << _SQL_
  insert into t_volume(DLdate,estimate,number,fullname,rms) 
     value(now(),"$estimate",$num,"$fullname",$rms);
  delete from t_sound where estimate
                    <now() - interval 48 hour;
  delete from t_volume where estimate
                    <now() - interval 48 hour;
  select last_insert_id();
_SQL_`

cat $num.raw |\
  od -w2 -t d2 -v -An |\
  awk -v seq="$seq" -v estimate="$estimate" \
     '{OFS=","}{print seq,estimate,NR,$1}' > loadfile.txt
mysql nhkradio << _SQL_
 load data local infile "loadfile.txt" into table t_sound
 fields terminated by "," (seq,estimate,sub_seq,sound);
_SQL_
rm loadfile.txt

 

再生側

#!/bin/bash
date1=`getparstr $# "$*" "date1"`
date2=`getparstr $# "$*" "date2"`

temp=`mktemp ./XXXX`
mysql nhkradio -N << _SQL_  > $temp
  select sound from t_sound
   where "$date1"<=estimate and estimate<="$date2"
   order by seq,sub_seq;
_SQL_

scilab -nw << _SCILAB_
 fd=mopen('$temp','r');
 a=mfscanf(-1,fd,'%d');
 mclose(fd);
 y=a/(2^15);
 wavwrite(y, 8000, 'playback.wav');
_SCILAB_
#sox -r 8000 -c 1 -b 16 -e signed-integer playback.raw playback.wav
aplay playback.wav
rm $temp playback.wav