ホームページ > php教程 > php手册 > PHP ソースコード ext/mysql 拡張部分

PHP ソースコード ext/mysql 拡張部分

WBOY
リリース: 2016-06-13 12:23:11
オリジナル
1138 人が閲覧しました

私は外部モジュール拡張機能を作成しましたが、PHP ソース コード内の mysql 拡張機能を調べ始めています。これは PHP に統合できるため、組み込み拡張機能と見なす必要があります。
この拡張機能は、mysql データベースによって提供されるいくつかのインターフェイスを使用する必要があるため、mysql をインストールし、mysql.h の場所を決定する必要があります。
この拡張機能の場所は通常、PHP-source-code/ext/mysql の下にあります。
Linux では、注意が必要な主なファイルは config.m4、php_mysql.c、php_mysql_structs.h です。
ps: このディレクトリにはタグ ファイルがあるため、ctags のさまざまな機能を使用して関数やマクロ定義などを直接検索できます。
追記: Linux sudo mysql-dir/bin/mysqld_safe &
で mysql を起動すると、2 つのプロセスが実行されます:

コードをコピーコードは次のとおりです:


root 5297 0.0 0.0 5920 1416 pts/5 S 11:08 0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe
mysql 5320 1.4 1.1 202728 23796 ポイント/5 Sl 11:08 1:47 /usr/local/mysql/libexec/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/var --user= mysql -- pid-file=/usr/local/mysql/var/tj1clnxweb0004.pid --skip-external-locking --port=3306 --socket=/tmp/mysql.sock


--- --------------------------------------------------- -
最初に以下の読み取り値を記録します。 プロセスの詳細:
1. php_mysql_do_query_general 関数
この拡張機能によって提供される関数 mysql_query および mysql_unbuffered_query は、最終的に php_mysql_do_query_general を使用してコア関数を実行します。
最初にトレース モードを確認します:
if (MySG(trace_mode)) { .... }
php.ini に設定があります:
mysql.trace_mode = Off
そして if configured が open の場合は if 内の文が実行され、実行された文が select の場合は SQL 文のパフォーマンスを分析するために前に Explain が追加されます。
次に、mysql_use_result と mysql_store_result の違いを見てみましょう。
ご覧のとおり、mysql_query は mysql_store_result 関数を使用し、mysql_unbuffered_query は mysql_use_result を使用します。
記事 (http://school.cnd8.com/mysql/jiaocheng/25143_8.htm) を参照して、次のように要約します。
mysql_store_result はクエリを実行してすべての結果セットを取得し、それらをクライアントに保存します。クライアントで使用するためにそれらを準備します。これには、クライアントでより多くのメモリとパフォーマンスが必要です。
mysql_use_result はクエリのみを実行しますが、結果の取得が遅れます。これは、サービス フロントエンドで結果セットを維持することと同じです。
mysql_store_result を呼び出し、mysql_fetch_row を使用して結果を取得した後、戻り値が NULL の場合、結果はクライアントから直接取得されます。
mysql_use_result が呼び出され、mysql_fetch_row を使用して結果が取得される場合、結果が NULL の場合、結果は役に立たないか、ネットワーク接続エラーまたはその他の理由がある可能性があります。
結果セットのメンテナンス場所が異なるため、mysql_store_result の結果は、任意のシーク、合計数の取得、非順次アクセスなど、より多くの処理機能を提供できます。 mysql_use_result の結果セットは使用できません。
さらに、mysql_use_result の結果セットはサーバー側で維持されるため、クライアントは結果セット内の各行に対して mysql_fetch_row を呼び出す必要があるという要件が提示されます。そうしないと、結果セット内の残りのレコードが結果セットになります。次のクエリ結果がセットの一部であるため、「非同期」エラーが発生します。
それでは、なぜ mysql_use_result を使用する必要があるのでしょうか?この状況を見てください:
mysql と mysqldump はデフォルトで mysql_store_result を使用しますが、 --quick オプションが指定されている場合は、mysql_use_result が使用されます。
ということは、mysql_use_result は効率の点で有利ということですか?
mysql ヘルプ マニュアルを参照してください:
-q、--quick 結果をキャッシュせず、行ごとに出力します。これにより、出力が一時停止されると、
サーバーの速度が低下する可能性があります。
履歴ファイル。
Mysqldump ヘルプ マニュアル:
-q、--quick クエリをバッファせず、stdout に直接ダンプします。
なぜ、quick が mysql_use_result に対応するのかがよくわかりません。これを行うには、まず mysql_use_result を使用しない場合を判断します。 mysql_use_result の結果セットはサーバー側で保持されるため、クライアントプログラムがハングする可能性がある場合は使用しないでください。結果セット内の行間に操作が多すぎる場合は、これを使用しないでください。言い換えれば、クエリが完了し、結果がすぐに使い尽くされて解放されない場合は、mysql_use_result を使用しないでください。
効果を試すために、次のテスト コードを書きました:

コードをコピーします コードは次のとおりです:


$sql = sprintf ("select * from pet;");
$result = mysql_unbuffered_query($sql, $conn);
$rows = mysql_fetch_row($result);行);
$ sql = sprintf("ショップから * を選択");
$rows = mysql_fetch_row($result); ($rows);


実行の結果、2 回目のフェッチでは最初の結果は表示されませんが、PHP は次の通知を報告します。
PHP 通知: mysql_unbuffered_query(): 前のバッファリングされていないクエリから最初にすべての行をフェッチせずに関数が呼び出されました。 /home/yicheng/test-all/mysqltest/test.php 28 行目
テスト コードを変更します:

コードをコピーします コードは次のとおりです


$i = 1000000;
while($i--){
$sql = sprintf("select * from pet;"); mysql_query($sql, $conn);
#$result = mysql_unbuffered_query($sql, $conn);
while($rows = mysql_fetch_row($result)){

}
if ($result) {
mysql_free_result($result);
}
}

バッファなしを使用した結果:
:!time ./test.php
real 1m10.220s
user 0m17.853s
sys 0m9.541s
mysql_query の使用結果:
:!time ./test.php
real 1m11.191s
user 0m19.297s
sys 0m10.133s
時間差は大きくないようです
2. いくつかのリソース関連のマクロ定義

コードをコピーします コードは次のとおりです。

#define ZEND_VERIFY_RESOURCE(rsrc)
if (!rsrc) {
RETURN_FALSE;
}
#define ZEND_FETCH_RESOURCE( rsrc、rsrc_type、passed_id、default_id、resource_type_name、resource_type)
rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC、default_id、resource_type_name、NULL、1、resource_type);
ZEND_VERIFY_RESOURCE(rsrc); OURCE2 (rsrc、rsrc_type、passed_id、default_id、resource_type_name、resource_type1、resource_type2)
rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC、default_id、resource_type_name、NULL、2、resource_type1、resource_type2);
ZEND_VERIFY_RESOURCE(rsrc);
#define ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type)
zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type);
#define ZEND_GET_RESOURCE_TYPE_ID(le_id, le_type_name)
if (le_id == 0) ) {
le_id = zend_fetch_list_dtor_id(le_type_name);
}


mysql_connect 関数から返されるものは、実際にはマッピング可能なリンク ID (タイプ (mysql link) の resource(4)) です。 ZEND_FETCH_RESOURCE および ZEND_FETCH_RESOURCE2 マクロを通じて、対応する mysql リソースにアクセスします。どちらのマクロも zend_fetch_resource メソッドを呼び出しますので、このメソッドを見てみましょう。

ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, char *resource_type_name, int *found_resource_type, int num_resource_types, ...)
たとえば、mysql_list_dbs 関数で ZEND_FETCH_RESOURCE2 マクロを呼び出します。
ZEND_FETCH_RES OURCE2(mysql , php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink);
ここで、mysql は返された有効なリソースを保存します。php_mysql_conn * は返されたリソースのタイプを定義します。mysql_link、id は、passed_id に対応します。それぞれdefault_id (多くの関数呼び出しは特定のconnを渡さないため、単にデフォルト値を使用します)、「MySQL-Link」はresource_type_name、le_link、le_plinkはzend_fetch_resourceの部分であり、両方とも静的intです。値を入力します。
zend_fetch_resource からわかるように、タイプ (mysql リンク) の resource(4) の value.lval には長いタイプ ID が含まれています。 default_id が -1 の場合は、passed_id によって渡された ID が使用され、それ以外の場合は、default_id が ID として使用され、対応するリソースの検索に zend_list_find が使用されます。
いくつかの関数を見た後、この拡張機能は mysql によって提供される c インターフェイスをカプセル化したものにすぎないことがわかりました。しかし、パッケージは非常に標準化されており、安定しています。
さらに詳しく知りたい場合は、やはり MYSQL のソース コードを参照する必要があります。いくつかの重要なデータ構造を以下に示します。
----------------------------------------
チェックに関するいくつかの質問エラーは役に立つ php 関数である可能性があります:


コードをコピー コードは次のとおりです:

error_reporting(E_ALL); #var_dump(mysql_get_host_info($conn));

#var_dump(mysql_get_proto_info($conn));
#var_dump(mysql_stat($conn)); 🎜># var_dump(mysql_errno($conn));
#var_dump(mysql_error($conn));


--- ---------------------------------------------------
MYSQL ソース コードのいくつかの便利な構造体


コードをコピー

コードは次のとおりです:


typedef struct st_mysql
{
NET net; /* 通信パラメータ */
gptr Connector_fd; /* ConnectorFd for SSL */
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*info;
char *db;
struct charset_info_st *charset;
MYSQL_FIELD *フィールド;
MEM_ROOT フィールド_alloc;
my_ulonglongaffected_rows;
my_ulonglong insert_id; /* NEXTNR を使用してテーブルに挿入する場合の ID */
my_ulonglong extra_info; /* 使用されません */
unsigned long thread_id; /* サーバーの接続用の ID */
unsigned long packet_length;
符号なし int ポート;
unsigned long client_flag,server_capabilities;
unsigned int プロトコルバージョン;
unsigned int field_count;
unsigned int server_status;
unsigned int サーバー言語;
unsigned int warning_count;
struct st_mysql_options オプション;
列挙型 mysql_status ステータス;
my_bool free_me; /* mysql_close で空いている場合 */
my_bool 再接続; /* 自動再接続の場合は 1 に設定 */
/* セッション全体のランダムな文字列 */
char scramble[SCRAMBLE_LENGTH 1];
/*
これが元の接続であり、
mysql_rpl_probe() または mysql_set_master()/ mysql_add_slave() によって追加したマスターまたはスレーブではない場合に設定します
*/
my_bool rpl_pivot ;
/*
マスターへのポインタ、および次のスレーブ接続は、単独の接続の場合は
それ自体を指します。
*/
struct st_mysql* マスター、*next_slave;
struct st_mysql* last_used_slave; /* ラウンドロビンのスレーブ選択に必要 */
/* レプリケーションで正しく動作するために結果の送信/読み取り/保存/使用に必要 */
struct st_mysql* last_used_con;
LIST *stmts; /* すべてのステートメントのリスト */
const struct st_mysql_methods *methods;
void *thd;
/*
MYSQL_RES または MYSQL_STMT のブール型フラグを指します。 close がこのオブジェクトの結果セットをキャンセルする必要がある場合は、mysql_stmt_close からこのフラグを
に設定します。
*/
my_bool *unbuffered_fetch_owner;
#定義されている場合(EMBEDDED_LIBRARY) ||定義済み(EMBEDDED_LIBRARY_COMPATIBLE) || MYSQL_VERSION_ID >= 50100
/* 組み込みサーバーに必要 - 「情報」を保存するためのネット バッファーがありません */
char *info_buffer;
#endif
} MYSQL;
typedef struct st_mysql_methods
{
my_bool (*read_query_result)(MYSQL *mysql);
my_bool (*advanced_command)(MYSQL *mysql,
enum enum_server_command コマンド,
const char *header,
unsigned long header_length,
const char *arg,
unsigned long arg_length,
my_bool Skip_check、
MYSQL_STMT *stmt);
MYSQL_DATA *(*read_rows)(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
unsigned int フィールド);
MYSQL_RES * (*use_result)(MYSQL *mysql);
void (*fetch_lengths)(unsigned long *to,
MYSQL_ROW カラム, unsigned int field_count);
void (*flush_use_result)(MYSQL *mysql);
#if !define(MYSQL_SERVER) ||定義済み(EMBEDDED_LIBRARY)
MYSQL_FIELD * (*list_fields)(MYSQL *mysql);
my_bool (*read_prepare_result)(MYSQL *mysql, MYSQL_STMT *stmt);
int (*stmt_execute)(MYSQL_STMT *stmt);
int (*read_binary_rows)(MYSQL_STMT *stmt);
int (*unbuffered_fetch)(MYSQL *mysql, char **row);
void (*free_embedded_thd)(MYSQL *mysql);
const char *(*read_statistics)(MYSQL *mysql);
my_bool (*next_result)(MYSQL *mysql);
int (*read_change_user_result)(MYSQL *mysql, char *buff, const char *passwd);
int (*read_rows_from_cursor)(MYSQL_STMT *stmt);
#endif
} MYSQL_METHODS;

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート