PHP源码之 ext/mysql扩展部分_PHP
我写过一个外部模块扩展,现在开始看PHP源码中的mysql扩展,它是可以被集成到PHP内部的,所以应该算是内置的扩展了。
该扩展需要用到mysql数据库提供的一些接口,所以需要安装了mysql,并能够确定mysql.h的位置。
该扩展的位置一般在 PHP-source-code/ext/mysql 下。
在linux下,主要需要注意的文件是: config.m4, php_mysql.c, php_mysql_structs.h。
ps:该目录下有tags文件,所以可以利用ctags的各种特性,直接找到函数、宏定义等。
ps:linux下mysql的启动 sudo mysql-dir/bin/mysqld_safe &
之后会有两个进程运行:
复制代码 代码如下:
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 pts/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来执行核心功能。
首先看下trace模式:
if (MySG(trace_mode)) { .... }
在php.ini中有配置:
mysql.trace_mode = Off
而如果配置是打开的,那么就会执行if中的句子,而如果执行的句子是select的话,就会在前面加上explain,分析sql句子的性能。
然后看一下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 的结果可以提供更多的处理函数,比如任意的seek、获取总数、非顺序访问等。而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 Don't cache result, print it row by row. This may slow
down the server if the output is suspended. Doesn't use
history file.
mysqldump的帮助手册:
-q, --quick Don't buffer query, dump directly to stdout.
那么在我没有彻底弄明白为什么quick对应着mysql_use_result的时候,先搞明白什么时候不要用mysql_use_result吧。由于mysql_use_result的结果集维护在服务器端,那么如果客户端程序可能被挂起,别用它。如果结果集的行与行之间有过多操作,别用它。也就是一句话,如果查询完,不是立马用完结果,free掉,那么就别用mysql_use_result。
为了尝试一下效果,写了以下测试代码:
复制代码 代码如下:
$sql = sprintf("select * from pet;");
$result = mysql_unbuffered_query($sql, $conn);
$rows = mysql_fetch_row($result);
var_dump($rows);
$sql = sprintf("select * from shop");
$result = mysql_unbuffered_query($sql, $conn);
$rows = mysql_fetch_row($result);
var_dump($rows);
执行的结果是,第二次fetch不会显示第一次的结果,但是php会报notice:
PHP Notice: mysql_unbuffered_query(): Function called without first fetching all rows from a previous unbuffered query in /home/yicheng/test-all/mysqltest/test.php on line 28
修改测试代码:
复制代码 代码如下:
$i = 1000000;
while($i--){
$sql = sprintf("select * from pet;");
$result = mysql_query($sql, $conn);
#$result = mysql_unbuffered_query($sql, $conn);
while($rows = mysql_fetch_row($result)){
}
if ($result){
mysql_free_result($result);
}
}
使用unbuffered的结果:
:!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);
#define ZEND_FETCH_RESOURCE2(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函数返回的其实是一个link id(resource(4) of type (mysql link)),通过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_RESOURCE2(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,就是使用default值),"MySQL-Link"是resource_type_name,le_link, le_plink是zend_fetch_resource的...部分,它们俩是static int类型的值。
由zend_fetch_resource可以看出,resource(4) of type (mysql link)的value.lval中包含了long型的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_get_server_info($conn));
#var_dump(mysql_stat($conn));
#var_dump(mysql_errno($conn));
#var_dump(mysql_error($conn));
#var_dump(mysql_info($conn));
--------------------------------------------
MYSQL源码中一些有用的struct
复制代码 代码如下:
typedef struct st_mysql
{
NET net; /* Communication parameters */
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 *fields;
MEM_ROOT field_alloc;
my_ulonglong affected_rows;
my_ulonglong insert_id; /* id if insert on table with NEXTNR */
my_ulonglong extra_info; /* Not used */
unsigned long thread_id; /* Id for connection in server */
unsigned long packet_length;
unsigned int port;
unsigned long client_flag,server_capabilities;
unsigned int protocol_version;
unsigned int field_count;
unsigned int server_status;
unsigned int server_language;
unsigned int warning_count;
struct st_mysql_options options;
enum mysql_status status;
my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
/*
Set if this is the original connection, not a master or a slave we have
added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
*/
my_bool rpl_pivot;
/*
Pointers to the master, and the next slave connections, points to
itself if lone connection.
*/
struct st_mysql* master, *next_slave;
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
/* needed for send/read/store/use result to work correctly with replication */
struct st_mysql* last_used_con;
LIST *stmts; /* list of all statements */
const struct st_mysql_methods *methods;
void *thd;
/*
Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
from mysql_stmt_close if close had to cancel result set of this object.
*/
my_bool *unbuffered_fetch_owner;
#if defined(EMBEDDED_LIBRARY) || defined(EMBEDDED_LIBRARY_COMPATIBLE) || MYSQL_VERSION_ID >= 50100
/* needed for embedded server - no net buffer to store the 'info' */
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 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 fields);
MYSQL_RES * (*use_result)(MYSQL *mysql);
void (*fetch_lengths)(unsigned long *to,
MYSQL_ROW column, unsigned int field_count);
void (*flush_use_result)(MYSQL *mysql);
#if !defined(MYSQL_SERVER) || defined(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;

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

PHP et Python ont chacun leurs propres avantages et choisissent en fonction des exigences du projet. 1.Php convient au développement Web, en particulier pour le développement rapide et la maintenance des sites Web. 2. Python convient à la science des données, à l'apprentissage automatique et à l'intelligence artificielle, avec syntaxe concise et adaptée aux débutants.

Le PHP reste important dans le développement Web moderne, en particulier dans la gestion de contenu et les plateformes de commerce électronique. 1) PHP a un écosystème riche et un fort soutien-cadre, tels que Laravel et Symfony. 2) L'optimisation des performances peut être obtenue via Opcache et Nginx. 3) PHP8.0 introduit le compilateur JIT pour améliorer les performances. 4) Les applications natives dans le cloud sont déployées via Docker et Kubernetes pour améliorer la flexibilité et l'évolutivité.

PHP est un langage de script largement utilisé du côté du serveur, particulièrement adapté au développement Web. 1.Php peut intégrer HTML, traiter les demandes et réponses HTTP et prend en charge une variété de bases de données. 2.PHP est utilisé pour générer du contenu Web dynamique, des données de formulaire de traitement, des bases de données d'accès, etc., avec un support communautaire solide et des ressources open source. 3. PHP est une langue interprétée, et le processus d'exécution comprend l'analyse lexicale, l'analyse grammaticale, la compilation et l'exécution. 4.PHP peut être combiné avec MySQL pour les applications avancées telles que les systèmes d'enregistrement des utilisateurs. 5. Lors du débogage de PHP, vous pouvez utiliser des fonctions telles que error_reportting () et var_dump (). 6. Optimiser le code PHP pour utiliser les mécanismes de mise en cache, optimiser les requêtes de base de données et utiliser des fonctions intégrées. 7

PHP convient au développement Web, en particulier dans le développement rapide et le traitement du contenu dynamique, mais n'est pas bon dans les applications de la science des données et de l'entreprise. Par rapport à Python, PHP présente plus d'avantages dans le développement Web, mais n'est pas aussi bon que Python dans le domaine de la science des données; Par rapport à Java, PHP fonctionne moins bien dans les applications au niveau de l'entreprise, mais est plus flexible dans le développement Web; Par rapport à JavaScript, PHP est plus concis dans le développement back-end, mais n'est pas aussi bon que JavaScript dans le développement frontal.

La position de MySQL dans les bases de données et la programmation est très importante. Il s'agit d'un système de gestion de base de données relationnel open source qui est largement utilisé dans divers scénarios d'application. 1) MySQL fournit des fonctions efficaces de stockage de données, d'organisation et de récupération, en prenant en charge les systèmes Web, mobiles et de niveau d'entreprise. 2) Il utilise une architecture client-serveur, prend en charge plusieurs moteurs de stockage et optimisation d'index. 3) Les usages de base incluent la création de tables et l'insertion de données, et les usages avancés impliquent des jointures multiples et des requêtes complexes. 4) Des questions fréquemment posées telles que les erreurs de syntaxe SQL et les problèmes de performances peuvent être déboguées via la commande Explication et le journal de requête lente. 5) Les méthodes d'optimisation des performances comprennent l'utilisation rationnelle des indices, la requête optimisée et l'utilisation des caches. Les meilleures pratiques incluent l'utilisation des transactions et des acteurs préparés

PHP est toujours dynamique et occupe toujours une position importante dans le domaine de la programmation moderne. 1) La simplicité de PHP et le soutien communautaire puissant le rendent largement utilisé dans le développement Web; 2) sa flexibilité et sa stabilité le rendent exceptionnelle dans la gestion des formulaires Web, des opérations de base de données et du traitement de fichiers; 3) PHP évolue et optimise constamment, adapté aux débutants et aux développeurs expérimentés.

Les raisons pour lesquelles PHP est la pile technologique préférée pour de nombreux sites Web incluent sa facilité d'utilisation, son soutien communautaire solide et son utilisation généralisée. 1) Facile à apprendre et à utiliser, adapté aux débutants. 2) Avoir une énorme communauté de développeurs et des ressources riches. 3) Largement utilisé dans WordPress, Drupal et d'autres plateformes. 4) Intégrez étroitement aux serveurs Web pour simplifier le déploiement du développement.

PHP et Python ont chacun leurs propres avantages et conviennent à différents scénarios. 1.PHP convient au développement Web et fournit des serveurs Web intégrés et des bibliothèques de fonctions riches. 2. Python convient à la science des données et à l'apprentissage automatique, avec une syntaxe concise et une bibliothèque standard puissante. Lors du choix, il doit être décidé en fonction des exigences du projet.
