2014年02月17日

dbd_st_prepare で { async => 1 } のとき
imp_sth->is_async = TRUE;
imp_sth->use_server_side_prepare = FALSE;


mysql_st_internal_execute
dbh の時
async = (bool) (imp_dbh->async_query_in_flight != NULL);
sth の時
async = imp_sth->is_async;
if(async) {
imp_dbh->async_query_in_flight = imp_sth;
} else {
imp_dbh->async_query_in_flight = NULL;
}
非同期で mysql_send_query が成功したら return 0


dbd_st_execute
if(imp_dbh->async_query_in_flight) {
DBIc_ACTIVE_on(imp_sth);
return 0;
}


dbd_st_fetch
if(imp_dbh->async_query_in_flight) {
if(mysql_db_async_result(sth, &imp_sth->result) <= 0) {
return Nullav;
}
}


dbd_st_finish
D_imp_dbh_from_sth;
if(imp_dbh->async_query_in_flight) {
mysql_db_async_result(sth, &imp_sth->result);
}


mysql_db_async_result
impl_sth->result imp_dbh->async_query_in_flight = NULL して、に結果を入れて 結果行数


mysql_db_async_ready
fds.fd = dbh->pmysql->net.fd;
fds.events = POLLIN;

retval = poll(&fds, 1, 0);


do(dbh, statement, attr=Nullsv, ...) で { async => 1 } のとき
use_server_side_prepare = FALSE; /* for now */
imp_dbh->async_query_in_flight = imp_dbh;


imp_dbh->async_query_in_flight が立ってたらだめなの
dbd_db_commit(SV* dbh, imp_dbh_t* imp_dbh)
dbd_db_rollback(SV* dbh, imp_dbh_t* imp_dbh) {
int dbd_st_execute(SV* sth, imp_sth_t* imp_sth)
int dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *param, SV *value,
IV sql_type, SV *attribs, int is_inout, IV maxlen) {
SV *mysql_db_last_insert_id(SV *dbh, imp_dbh_t *imp_dbh,
SV *catalog, SV *schema, SV *table, SV *field, SV *attr)

type_info_all(dbh)
_ListDBs(dbh)
do(dbh, statement, attr=Nullsv, ...)
ping(dbh)
quote(dbh, str, type=NULL)
void _async_check(dbh)

まとめ

  • libmysqlclient は関係なくて DBD::mysql 独自
  • server side prepared statement は使えない
  • execute とかで mysql_send_query したあと mysql_store_result せずに即座に戻って、 fetch とかする関数の最初に mysql_store_result を呼び出す感じであとで読むしてる
  • なので mysql_async_result 呼ばないで fetchrow_hashref とかいきなり呼んでも何も支障ないというか mysql_async_result 呼ぶだけコストかかる感じがある
  • fetch するか mysql_async_result 呼ぶまではトランザクション終了させたり新規のクエリは投げられない(同じ sth で)
  • mysql_async_ready は内部的に poll 呼んでるだけ
  • mysql_fd が読み込み可能状態じゃ無くても fetch とか mysql_async_result を急に呼び出しても何も問題ないが、単純にそこでブロックするだけだから async api 使う意味ない
  • mysql_db_async_ready は poll(&fds, 1, 0) してるだけで、 readable じゃなければ即戻ってきちゃうのでマジ使う意味ないので mysql_fd を自前で select してハンドリングしたほうがいい。とは言え、重いクエリを裏で投げてて perl 側で思い処理を並列にやるユースケースだと、 perl 側の処理終わったら mysql_async_ready 呼びまくってもいいけど、それって先に mysqld 側で処理終わってる前提なので、その前提外れると busy loop するから結局使わない方がいい
  • エラーメッセージが時たま内部の構造体のメンバ変数名だしてきてウケる
  • 大事なことですが、 mysqld から result が送られて来てからの respons 受信処理は非同期に出来ない。あくまでも mysqld 側のクエリが終わるまでの間を自由に使えるってこと

Posted by Yappo at 2014年02月17日 23:03 | TrackBack | Perl
Comments
Post a comment









Remember personal info?






コメントを投稿する前に↓の場所にnospamと入力してください。