SlideShare a Scribd company logo
1 of 60
mysqlnd 
an unknown powerful PHP extension
Hola ! 
 Julien PAULI 
 Working at Sensiolabs (product team : Blackfire) 
 PHP internals dev. and extensions writer 
 PHP 5.5 and 5.6 Release Manager 
 @julienPauli - jpauli.github.com - 
https://github.com/jpauli/
Schedule 
 The MySQL protocols 
 Two protocols : binary vs textual 
 Discussing with MySQL using libmysql 
 The PHP case 
 Introduction to mysqlnd 
 Why and how 
 Exploring mysqlnd capabilities 
 Memory savings 
 Statistics 
 Plugins API
MySQL communication 
 MySQL communicates with its clients using a 
specific protocol 
 MySQL protocol 
 Open Source 
 Detailed at 
http://dev.mysql.com/doc/internals/en/client-server-protocol. 
html
MySQL protocol example
MySQL protocols 
 When querying data, there exists 2 protocols 
 Textual protocol 
 Used for direct queries 
 Heavy (text), cannot represent types (int, float, etc...) 
 Everything is text 
 Easy to dump / understand / debug 
 Binary protocol 
 Used for prepared statements and stored proc 
 Light, efficient : can represent types (int, float...) 
 Not easy to dump / understand / debug
MySQL Textual Protocol 
 Everything is sent as text 
 Even int-type columns, or not-text-type columns 
SELECT * FROM sl_players 
INT type column 
DATETIME type column
MySQL Binary Protocol 
 Every column that is not of type CHAR is sent 
using the right type 
SELECT * FROM sl_players 
 More efficient, as there is no need to transform 
data back-and-forth 
id (MYSQL_T name (MYSQL_TYPE_STRING) YPE_LONG) : 4 bytes 
0260 00 00 22 00 47 00 00 0b 00 00 00 01 00 00 00 06 ..".G........... 
0270 6a 75 6c 69 65 6e 1b 6a 75 6c 69 65 6e 2e 70 61 julien.julien.pa 
0280 75 6c 69 40 f8 65 6e 73 69 6f 6c 61 62 73 2e 63 uli@.ensiolabs.c 
0290 6f 6d 0b 73 75 70 65 72 73 65 63 72 65 74 09 73 om.supersecret.s 
02a0 6f 6d 65 5f 73 61 6c 74 01 01 04 de 07 0b 19 3c ome_salt.......<
Buffered vs unbuffered 
queries
Buffered queries 
 A buffered query is a query whose resultset is 
allocated on the client side memory 
SELECT * FROM sl_players
Buffered queries 
 A buffered query is a query whose resultset is 
allocated on the client side memory 
 Eats client's memory and not server's 
 Emits every byte of the result at once, on the network 
 The server's resultset memory is free : you can issue 
another request immediately 
 The result is on the client side, you may then count it 
(num_rows) or seek() through it 
SELECT * FROM sl_players
Unbuffered queries 
 An unbuffered query is a query whose resultset 
is allocated on the server side memory 
SELECT * FROM sl_players 
OK
Unbuffered queries 
 An unbuffered query is a query whose resultset 
is allocated on the server side memory 
 Eats server's memory and not client's 
 Emits bytes of the result on the network as long as 
you ask for data (fetch operation) 
 The server's resultset memory is occupied : you can 
not issue another request until you free the resultset 
memory (mysqli_free_result()) 
 You may not seek() nor num_rows(), as the client 
doesn't know anything about the result's metadata 
SELECT * FROM sl_players 
OK
Buffered, unbuffered ? 
 PHP will issue buffered query by default 
/* disable default PHP buffered queries */ 
$mysqli->query($query_str, MYSQLI_USE_RESULT); 
$pdo->setAttribute(MYSQL_ATTR_USE_BUFFERED_QUERY, 0); 
 It is better that the (thousands of) clients handle 
the memory for their own result rather than the 
server does
Direct queries 
VS 
Prepared statements
Direct Queries 
SELECT * FROM sl_players 
OK 
time 
fetch()
Direct Queries 
 Client sends the query in one packet 
 The query is a full string with all arguments resolved 
etc... 
 The server answers with OK or KO packet 
 And then, depending on buffered/unbuffered mode, 
the server sends back the dataset into several packets 
 The textual protocol is used 
 MySQL must transform any non-text col to text 
 PHP can transform back the text to a useful type if 
mysqlnd is used
Direct Queries 
Query packet 
Response packets
Prepared statements 
SELECT * FROM sl_players WHERE id = ? 
OK : PSid = 42 
time 
fetch(PSid=42) 
compile() 
PS{42} 
prepare() 
execute(PSid=42[0 : 123]) 
OK 
CloseStatement(PSid=42) PS{42} 
OK
Prepared Statements (PS) 
 Client sends a PS packet 
 The query may contain placeholders for data to be fed later-on 
 The server answers with OK or KO packet 
 And compiles the query on its side, giving it a unique ID that is sent back to the 
client. This ID will be used for further communication 
 Client sends an Execute Statement Packet 
 Together with the PS ID and eventually the placeholders argument values. 
 Depending on buffered/unbuffered mode, the server sends back the 
resultset data into several packets 
 Client sends a Close Statement Packet 
 The server may now free the associated ressources, but usually it keeps the PS 
execution plan and compilation hot in memory for further use 
 The binary protocol is used
Prepared Statements (PS) 
 Much more network communication is involved 
 If the query is not reused later, this may waste 
network resources 
 However, binary protocol is used, this may save 
resources in some specific cases 
 No data transformation on either side 
 RAW binary data may be lighter than the equivalent 
textual representation
PHP 
& 
MySQL
PHP & MySQL communication 
 3 extensions 
 ext/mysql 
 ext/mysqli 
 ext/PDO 
 2 connectors 
 libmysql 
 mysqlnd
PHP's MySQL connectors 
 libmysql 
 mysqlnd
libmysql 
 The standard default connector for every project 
 Written in C 
 Own and developped by Oracle 
 Double licenced, read licencing for details 
 Usually updated by Oracle, packaged by OS 
packagers 
 "libmysqlclient" , under Debian 
 Implements the MySQL protocol 
 knows how to communicate with MySQL servers
libmysql example 
#include <stdio.h> 
#include <stdlib.h> 
#include <mysql/mysql.h> 
#include "mysql_example.h" /* Pour MYSQL_HOST, MYSQL_USER, MYSQL_PASS */ 
int main(int argv, char *argc[]) 
{ 
MYSQL_RES *results = NULL; MYSQL_ROW row; MYSQL *db = NULL; 
db = (MYSQL *)malloc(sizeof(MYSQL)); 
mysql_init(db); 
mysql_options(db, MYSQL_INIT_COMMAND, "SET NAMES UTF8;"); 
if(!mysql_real_connect(db, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, NULL, 0, NULL, 0)) { 
fprintf(stderr, "Failed to connect to host %s (%s)", MYSQL_HOST, mysql_error(db)); 
exit(EXIT_FAILURE); 
} 
mysql_set_character_set(db, "utf8"); 
mysql_select_db(db, "my_database"); 
mysql_query(db , "SELECT user_id AS id FROM users WHERE description='member' LIMIT 10000"); 
results = mysql_use_result(db); 
while(row = mysql_fetch_row(results)) { 
printf("%sn", row[0]); 
} 
mysql_free_result(results); 
exit(EXIT_SUCCESS); 
}
Main drawbacks 
 You must bind your project to libmysql 
$> gcc -lmysql -o example example_mysql.c 
 libmysql has its own memory allocator 
 When using buffered queries, libmysql will allocate 
memory - into the bound process address space - to 
store the results 
 In the case of PHP, this is a major drawback 
 libmysql provides its API 
 What if I want to go further ?
mysqlnd
mysqlnd
Introducing mysqlnd 
 mysql Native Driver 
 PHP extension 
 Low level layer : replaces libmysql 
 Complete new write of the MySQL protocol 
 Enables features for higher level extensions 
 ext/mysql , ext/mysqli and ext/pdo
mysqlnd : a PHP extension
mysqlnd: a strange PHP extension 
 This extension doesn't provide any function or 
class of its own. 
 In fact, it will extend the MySQL extensions 
 ext/mysql ext/mysqli ext/pdo 
 It will work on the low layer 
 It is released with PHP source code 
 Under the PHP licence
mysqlnd: default PHP connector ? 
 The extension has been released with PHP5.3 
 Activate at compile time --with-mysqli=mysqlnd 
 It is activated by default since 5.4 
 Cannot be built as shared (no mysqlnd.so) 
 However, check with your distro 
 For example, under Debian, it is not used by default 
$> apt-get install php5-mysqlnd
mysqlnd features 
 PHP licence, maintained by PHP developpers 
 Huge memory savings in case of read-only 
queries (very common) 
 Extremely detailed statistics about the PHP-MySQL 
communication 
 Highly extensible, in C, and in PHP 
 Many plugins exist 
 A nice API
mysqlnd architecture 
ext/mysql ext/mysqli ext/PDO 
memory allocator PHP communication 
Core 
MySQL protocols 
Statistics collector 
Network stack 
Plugins layer 
MySQL results 
MySQL PS 
Authenticator Charsets manager
mysqlnd : save your memory 
 PHP extensions will use by default buffered 
queries 
 With libmysql, libmysql will then allocate 
memory for the whole resultset into the PHP 
process 
 As soon as you fetch your results, PHP will 
allocate its own memory 
 Conclusion : memory is allocated twice (~roughly)
PHP mem usage with libmysql 
 Buffered resultset (default) 
echo "initial memory " . memory_usage(); 
$result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000"); 
echo "resultSet stored " . memory_usage(); 
while($results[] = mysqli_fetch_array($result)) { } 
echo "query result saved " . memory_usage(); 
mysqli_free_result($result); 
echo "resultSet freed " . memory_usage(); 
unset($results); 
echo "saved result freed " . memory_usage(); 
unset($db); 
echo "Db closed " . memory_usage(); 
$> phplibmysql/bin/php poc_mysqli.php 
initial memory ->3348 kB 
resultSet stored ->32508 kB 
query result saved ->454396 kB 
resultSet freed ->425468 kB 
saved result freed ->4092 kB 
Db closed ->4092 kB
PHP mem usage with libmysql 
 Unbuffered resultset 
echo "initial memory " . memory_usage(); 
$result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000", 
MYSQLI_USE_RESULT); 
echo "resultSet stored " . memory_usage(); 
while($results[] = mysqli_fetch_array($result)) { } 
echo "query result saved " . memory_usage(); 
mysqli_free_result($result); 
echo "resultSet freed " . memory_usage(); 
unset($results); 
echo "saved result freed " . memory_usage(); 
unset($db); 
echo "Db closed " . memory_usage(); 
$> phplibmysql/bin/php poc_mysqli.php 
initial memory ->3348 kB 
resultSet stored ->3348 kB 
query result saved ->425236 kB 
resultSet freed ->425236 kB 
saved result freed ->3860 kB 
Db closed ->3860 kB
Buffered, unbuffered query ? 
 Buffered 
$> phplibmysql/bin/php poc_mysqli.php 
initial memory ->3348 kB 
resultSet stored ->32508 kB 
query result saved ->454396 kB 
resultSet freed ->425468 kB 
saved result freed ->4092 kB 
Db closed ->4092 kB 
 Unbuffered 
$> phplibmysql/bin/php poc_mysqli.php 
initial memory ->3348 kB 
resultSet stored ->3348 kB 
query result saved ->425236 kB 
resultSet freed ->425236 kB 
saved result freed ->3860 kB 
Db closed ->3860 kB
Fetch mode ? 
echo "initial memory " . memory_usage(); 
$result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000"); 
while($results[] = mysqli_fetch_array($result)) { } 
echo "query result saved with fetch_array" . memory_usage(); 
unset($results);mysqli_data_seek($result,0); 
while($results[] = mysqli_fetch_row($result)) { } 
echo "query result saved with fetch_row" . memory_usage(); 
unset($results);mysqli_data_seek($result,0); 
while($results[] = mysqli_fetch_assoc($result)) { } 
echo "query result saved with fetch_assoc" . memory_usage(); 
initial memory ->3348 kB 
resultSet stored ->32508 kB 
query result saved with fetch_array->454396 kB 
query result saved with fetch_row->333564 kB 
query result saved with fetch_assoc->345084 kB
Quick points 
 Unbuffered ResultSets consume much less 
memory on the PHP side (but on the mysqld 
server side) 
 fetchAll()ing results from a buffered resultset is 
silly : duplicate the resultset in memory 
 Until you mysqli_free_result() it 
 You'd better fetch() each result in a sequencial way
mysqlnd saves memory 
 When using a buffered query (default) 
 The resultset is entirely transfered into the client (PHP) 
memory 
 Using mysqlnd : mysqlnd will take care of that 
 When fetching a result from a resultset 
 mysqlnd will not duplicate the result data 
 It will use internal PHP's zval refcount to save many 
memory 
 If you SELECT many data, or big fields (blobs), you'll 
see a very huge improvement
PHP mem usage with mysqlnd 
 Buffered resultset (default) 
initial memory ->86480 kB 
resultSet stored ->229632 kB 
query result saved ->234016 kB 
query result freed ->234016 kB 
resultSet freed ->134816 kB 
Db closed ->134816 kB 
initial memory ->88768 kB 
resultSet stored ->245104 kB 
query result saved ->414804 kB 
query result freed ->336628 kB 
resultSet freed ->198228 kB 
Db closed ->193924 kB 
mysqlnd 
libmysql
PHP mem usage with mysqlnd 
 Buffered resultset (default) 
==32226== 
==32226== HEAP SUMMARY: 
mysqlnd 
==32226== in use at exit: 0 bytes in 0 blocks 
==32226== total heap usage: 15,799 allocs, 15,799 frees, 120,705,322 bytes 
allocated 
==32226== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 
==32241== 
==32241== HEAP SUMMARY: 
libmysql 
==32241== in use at exit: 0 bytes in 0 blocks 
==32241== total heap usage: 14,452 allocs, 14,452 frees, 260,903,720 bytes 
allocated 
==32241== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
libmysql 
 Roughtly doubles your ResultSet memory space 
99.92% (257,473,815B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. 
->52.90% (136,314,880B) 0x69A01E: _zend_mm_alloc_int (zend_alloc.c:1908) 
| ->52.60% (135,528,448B) 0x69A1DE: _estrndup (zend_alloc.c:2503) 
| | ->52.60% (135,528,448B) 0x533BCE: php_mysqli_fetch_into_hash (mysqli.c:1191) 
| | ->52.60% (135,528,448B) 0x53F2E1: zif_mysqli_fetch_array (mysqli_nonapi.c:352) 
| | ->52.60% (135,528,448B) 0x70186A: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) 
| | ->52.60% (135,528,448B) 0x6D9D96: execute (zend_vm_execute.h:107) 
| | ->52.60% (135,528,448B) 0x6B4B98: zend_execute_scripts (zend.c:1236) 
| | ->52.60% (135,528,448B) 0x663D0C: php_execute_script (main.c:2308) 
| | ->52.60% (135,528,448B) 0x73BCDC: main (php_cli.c:1184) 
| | 
| ->00.31% (786,432B) in 1+ places, all below ms_print's threshold (01.00%) 
| 
->45.85% (118,130,675B) 0x52DD010: my_malloc (my_malloc.c:37) 
| ->45.84% (118,112,344B) 0x52E0583: alloc_root (my_alloc.c:219) 
| | ->45.83% (118,096,024B) 0x5307A40: cli_read_rows (client.c:1418) 
| | | ->45.83% (118,096,024B) 0x5305955: mysql_store_result (client.c:2957) 
| | | ->45.83% (118,096,024B) 0x53EF09: zif_mysqli_query (mysqli_nonapi.c:540) 
| | | ->45.83% (118,096,024B) 0x70186A: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) 
| | | ->45.83% (118,096,024B) 0x6D9D96: execute (zend_vm_execute.h:107) 
| | | ->45.83% (118,096,024B) 0x6B4B98: zend_execute_scripts (zend.c:1236) 
| | | ->45.83% (118,096,024B) 0x663D0C: php_execute_script (main.c:2308) 
| | | ->45.83% (118,096,024B) 0x73BCDC: main (php_cli.c:1184)
mysqlnd, memory : conclusion 
 When using SELECT queries 
 Especially : 
 if you SELECT many results 
 if you SELECT big results, such as blobs 
 And you stay in read-only : you don't modify the 
data you fetch (but just say, display it)
mysqlnd, memory : conclusion 
 When using SELECT queries 
 Especially : 
 if you SELECT many results 
 if you SELECT big results, such as blobs 
 And you stay in read-only : you don't modify the 
data you fetch (but just say, display it) 
 Then, mysqlnd will save memory for you 
 mysqlnd uses the PHP memory manager 
 the memory_limit , and the memory_get_usage() 
 libmysql does not
mysqlnd statistics
mysqlnd statistics
mysqlnd statistics 
 bytes_sent / bytes_received 
 result_set_queries / non_result_set_queries 
 no_index_used / bad_index_used 
 buffered_sets / unbuffered_sets 
 ps_buffered_sets / ps_unbuffered_sets 
 ps_prepared_never_executed / 
ps_prepared_once_executed
mysqlnd statistics
mysqlnd statistics from PHP 
$db = mysqli_connect('theserver', 'read-only', 'ro', 'mydb'); 
$result = mysqli_query($db,"SELECT user_id, date FROM users WHERE LIMIT 5"); 
mysqli_data_seek($result, 5); 
$data = mysqli_fetch_row($result); 
var_dump($data); 
mysqli_free_result($result); 
var_dump(mysqli_get_connection_stats($db)); 
["buffered_sets"]=> 
string(1) "1" 
["rows_fetched_from_server_normal"]=> 
string(1) "5" 
["rows_buffered_from_client_normal"]=> 
string(1) "5" 
["rows_fetched_from_client_normal_buff 
ered"]=> 
string(1) "1" 
["connect_success"]=> 
string(1) "1" 
...
Using mysqlnd stats 
class MyMysqli extends Mysqli 
{ 
public function __destruct() 
{ 
$stats = $this->get_connection_stats(); 
$this->close(); 
if($diff = $stats["rows_fetched_from_server_normal"] - 
($stats["rows_fetched_from_client_normal_unbuffered"] + 
$stats["rows_fetched_from_client_normal_buffered"])) { 
trigger_error("You didn't use *$diff* selected results", 
E_USER_NOTICE); 
} 
} 
}
JSMysqlndBundle 
 https://github.com/johannes/JSMysqlndBundle
mysqlnd plugins API
mysqlnd plugins API
mysqlnd existing plugins 
 mysqlnd_qc 
 Implement query results cache 
 mysqlnd_uh 
 User Handler : take hand using PHP callbacks 
 mysqlnd_ms 
 Master/slave connection management 
 mysqlnd_mux 
 Connection multiplexer 
 mysqlnd_memcache 
 Client part for MySQL InnoDB Memcached Daemon 
Plugin
mysqlnd plugins capabilities 
 Lots of hooks 
 On connection 
 On queries 
 On ResultSet creation 
 On the statistics manager 
 You can do whatever you want hooking between 
PHP and MySQL
Not only in C ! 
 mysqlnd_uh 
 Publishes the mysqlnd plugin API to userland 
class conn_proxy extends MysqlndUhConnection { 
public function query($res, $query) { 
debug_print_backtrace(); 
return parent::query($res, $query); 
} 
} 
class stmt_proxy extends MysqlndUhPreparedStatement { 
public function prepare($res, $query) { 
debug_print_backtrace(); 
return parent::prepare($res, $query); 
} 
} 
mysqlnd_uh_set_connection_proxy(new conn_proxy()); 
mysqlnd_uh_set_statement_proxy(new stmt_proxy());
Thanks !

More Related Content

What's hot

Understanding PHP memory
Understanding PHP memoryUnderstanding PHP memory
Understanding PHP memoryjulien pauli
 
Understanding PHP objects
Understanding PHP objectsUnderstanding PHP objects
Understanding PHP objectsjulien pauli
 
Php and threads ZTS
Php and threads ZTSPhp and threads ZTS
Php and threads ZTSjulien pauli
 
Quick tour of PHP from inside
Quick tour of PHP from insideQuick tour of PHP from inside
Quick tour of PHP from insidejulien pauli
 
The Php Life Cycle
The Php Life CycleThe Php Life Cycle
The Php Life CycleXinchen Hui
 
PHP 7 OPCache extension review
PHP 7 OPCache extension reviewPHP 7 OPCache extension review
PHP 7 OPCache extension reviewjulien pauli
 
How PHP Works ?
How PHP Works ?How PHP Works ?
How PHP Works ?Ravi Raj
 
When e-commerce meets Symfony
When e-commerce meets SymfonyWhen e-commerce meets Symfony
When e-commerce meets SymfonyMarc Morera
 
PHP Tips for certification - OdW13
PHP Tips for certification - OdW13PHP Tips for certification - OdW13
PHP Tips for certification - OdW13julien pauli
 
PHP Optimization
PHP OptimizationPHP Optimization
PHP Optimizationdjesch
 
PHP 5.6 New and Deprecated Features
PHP 5.6  New and Deprecated FeaturesPHP 5.6  New and Deprecated Features
PHP 5.6 New and Deprecated FeaturesMark Niebergall
 
The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6Wim Godden
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Wim Godden
 
How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to productionSean Hess
 
Streams, sockets and filters oh my!
Streams, sockets and filters oh my!Streams, sockets and filters oh my!
Streams, sockets and filters oh my!Elizabeth Smith
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in PerlLaurent Dami
 

What's hot (20)

Understanding PHP memory
Understanding PHP memoryUnderstanding PHP memory
Understanding PHP memory
 
Understanding PHP objects
Understanding PHP objectsUnderstanding PHP objects
Understanding PHP objects
 
Php and threads ZTS
Php and threads ZTSPhp and threads ZTS
Php and threads ZTS
 
Quick tour of PHP from inside
Quick tour of PHP from insideQuick tour of PHP from inside
Quick tour of PHP from inside
 
The Php Life Cycle
The Php Life CycleThe Php Life Cycle
The Php Life Cycle
 
Building Custom PHP Extensions
Building Custom PHP ExtensionsBuilding Custom PHP Extensions
Building Custom PHP Extensions
 
PHP7 is coming
PHP7 is comingPHP7 is coming
PHP7 is coming
 
PHP 7 OPCache extension review
PHP 7 OPCache extension reviewPHP 7 OPCache extension review
PHP 7 OPCache extension review
 
How PHP Works ?
How PHP Works ?How PHP Works ?
How PHP Works ?
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
When e-commerce meets Symfony
When e-commerce meets SymfonyWhen e-commerce meets Symfony
When e-commerce meets Symfony
 
PHP Tips for certification - OdW13
PHP Tips for certification - OdW13PHP Tips for certification - OdW13
PHP Tips for certification - OdW13
 
PHP Optimization
PHP OptimizationPHP Optimization
PHP Optimization
 
PHP 5.6 New and Deprecated Features
PHP 5.6  New and Deprecated FeaturesPHP 5.6  New and Deprecated Features
PHP 5.6 New and Deprecated Features
 
The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6The why and how of moving to PHP 5.5/5.6
The why and how of moving to PHP 5.5/5.6
 
Key features PHP 5.3 - 5.6
Key features PHP 5.3 - 5.6Key features PHP 5.3 - 5.6
Key features PHP 5.3 - 5.6
 
Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011Caching and tuning fun for high scalability @ FrOSCon 2011
Caching and tuning fun for high scalability @ FrOSCon 2011
 
How to deploy node to production
How to deploy node to productionHow to deploy node to production
How to deploy node to production
 
Streams, sockets and filters oh my!
Streams, sockets and filters oh my!Streams, sockets and filters oh my!
Streams, sockets and filters oh my!
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
 

Viewers also liked

Arduino - SymfonyCon 2014 Lighting Talks
Arduino - SymfonyCon 2014 Lighting TalksArduino - SymfonyCon 2014 Lighting Talks
Arduino - SymfonyCon 2014 Lighting TalksPiotr Pasich
 
Big Data! Great! Now What? #SymfonyCon 2014
Big Data! Great! Now What? #SymfonyCon 2014Big Data! Great! Now What? #SymfonyCon 2014
Big Data! Great! Now What? #SymfonyCon 2014Ricard Clau
 
Symfony Under Control by Maxim Romanovsky
Symfony Under Control by Maxim RomanovskySymfony Under Control by Maxim Romanovsky
Symfony Under Control by Maxim Romanovskyphp-user-group-minsk
 
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServer
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServerUnder the Hood: Open vSwitch & OpenFlow in XCP & XenServer
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServerThe Linux Foundation
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
MySQL 5.7 Fabric: Introduction to High Availability and Sharding
MySQL 5.7 Fabric: Introduction to High Availability and Sharding MySQL 5.7 Fabric: Introduction to High Availability and Sharding
MySQL 5.7 Fabric: Introduction to High Availability and Sharding Ulf Wendel
 
HTTP Plugin for MySQL!
HTTP Plugin for MySQL!HTTP Plugin for MySQL!
HTTP Plugin for MySQL!Ulf Wendel
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group ReplicationUlf Wendel
 

Viewers also liked (10)

Arduino - SymfonyCon 2014 Lighting Talks
Arduino - SymfonyCon 2014 Lighting TalksArduino - SymfonyCon 2014 Lighting Talks
Arduino - SymfonyCon 2014 Lighting Talks
 
Big Data! Great! Now What? #SymfonyCon 2014
Big Data! Great! Now What? #SymfonyCon 2014Big Data! Great! Now What? #SymfonyCon 2014
Big Data! Great! Now What? #SymfonyCon 2014
 
Symfony Under Control by Maxim Romanovsky
Symfony Under Control by Maxim RomanovskySymfony Under Control by Maxim Romanovsky
Symfony Under Control by Maxim Romanovsky
 
Save Repository From Save
Save Repository From SaveSave Repository From Save
Save Repository From Save
 
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServer
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServerUnder the Hood: Open vSwitch & OpenFlow in XCP & XenServer
Under the Hood: Open vSwitch & OpenFlow in XCP & XenServer
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
A walk through system layers
A walk through system layersA walk through system layers
A walk through system layers
 
MySQL 5.7 Fabric: Introduction to High Availability and Sharding
MySQL 5.7 Fabric: Introduction to High Availability and Sharding MySQL 5.7 Fabric: Introduction to High Availability and Sharding
MySQL 5.7 Fabric: Introduction to High Availability and Sharding
 
HTTP Plugin for MySQL!
HTTP Plugin for MySQL!HTTP Plugin for MySQL!
HTTP Plugin for MySQL!
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group Replication
 

Similar to Mysqlnd, an unknown powerful PHP extension

Built-in query caching for all PHP MySQL extensions/APIs
Built-in query caching for all PHP MySQL extensions/APIsBuilt-in query caching for all PHP MySQL extensions/APIs
Built-in query caching for all PHP MySQL extensions/APIsUlf Wendel
 
The mysqlnd replication and load balancing plugin
The mysqlnd replication and load balancing pluginThe mysqlnd replication and load balancing plugin
The mysqlnd replication and load balancing pluginUlf Wendel
 
Presentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - WebinarPresentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - WebinarOrient Technologies
 
The PHP mysqlnd plugin talk - plugins an alternative to MySQL Proxy
The PHP mysqlnd plugin talk - plugins an alternative to MySQL ProxyThe PHP mysqlnd plugin talk - plugins an alternative to MySQL Proxy
The PHP mysqlnd plugin talk - plugins an alternative to MySQL ProxyUlf Wendel
 
MySQL PHP native driver : Advanced Functions / PHP forum Paris 2013
 MySQL PHP native driver  : Advanced Functions / PHP forum Paris 2013   MySQL PHP native driver  : Advanced Functions / PHP forum Paris 2013
MySQL PHP native driver : Advanced Functions / PHP forum Paris 2013 Serge Frezefond
 
20141011 mastering mysqlnd
20141011 mastering mysqlnd20141011 mastering mysqlnd
20141011 mastering mysqlnddo_aki
 
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLHTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLUlf Wendel
 
Barcelona mysqlnd qc
Barcelona mysqlnd qcBarcelona mysqlnd qc
Barcelona mysqlnd qcAnis Berejeb
 
Mysqlnd Query Cache
Mysqlnd Query CacheMysqlnd Query Cache
Mysqlnd Query CacheAnis Berejeb
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalabilityWim Godden
 
Tips
TipsTips
Tipsmclee
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalabilityWim Godden
 
The power of mysqlnd plugins
The power of mysqlnd pluginsThe power of mysqlnd plugins
The power of mysqlnd pluginsUlf Wendel
 
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011Ulf Wendel
 
Mysqlppt3510
Mysqlppt3510Mysqlppt3510
Mysqlppt3510Anuja Lad
 
Php &amp; my sql - how do pdo, mysq-li, and x devapi do what they do
Php &amp; my sql  - how do pdo, mysq-li, and x devapi do what they doPhp &amp; my sql  - how do pdo, mysq-li, and x devapi do what they do
Php &amp; my sql - how do pdo, mysq-li, and x devapi do what they doDave Stokes
 

Similar to Mysqlnd, an unknown powerful PHP extension (20)

Built-in query caching for all PHP MySQL extensions/APIs
Built-in query caching for all PHP MySQL extensions/APIsBuilt-in query caching for all PHP MySQL extensions/APIs
Built-in query caching for all PHP MySQL extensions/APIs
 
The mysqlnd replication and load balancing plugin
The mysqlnd replication and load balancing pluginThe mysqlnd replication and load balancing plugin
The mysqlnd replication and load balancing plugin
 
Presentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - WebinarPresentation of OrientDB v2.2 - Webinar
Presentation of OrientDB v2.2 - Webinar
 
The PHP mysqlnd plugin talk - plugins an alternative to MySQL Proxy
The PHP mysqlnd plugin talk - plugins an alternative to MySQL ProxyThe PHP mysqlnd plugin talk - plugins an alternative to MySQL Proxy
The PHP mysqlnd plugin talk - plugins an alternative to MySQL Proxy
 
MySQL PHP native driver : Advanced Functions / PHP forum Paris 2013
 MySQL PHP native driver  : Advanced Functions / PHP forum Paris 2013   MySQL PHP native driver  : Advanced Functions / PHP forum Paris 2013
MySQL PHP native driver : Advanced Functions / PHP forum Paris 2013
 
20141011 mastering mysqlnd
20141011 mastering mysqlnd20141011 mastering mysqlnd
20141011 mastering mysqlnd
 
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLHTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
 
Barcelona mysqlnd qc
Barcelona mysqlnd qcBarcelona mysqlnd qc
Barcelona mysqlnd qc
 
Mysqlnd Query Cache
Mysqlnd Query CacheMysqlnd Query Cache
Mysqlnd Query Cache
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalability
 
Tips
TipsTips
Tips
 
Caching and tuning fun for high scalability
Caching and tuning fun for high scalabilityCaching and tuning fun for high scalability
Caching and tuning fun for high scalability
 
The power of mysqlnd plugins
The power of mysqlnd pluginsThe power of mysqlnd plugins
The power of mysqlnd plugins
 
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011
MySQL native driver for PHP (mysqlnd) - Introduction and overview, Edition 2011
 
Performance Tuning
Performance TuningPerformance Tuning
Performance Tuning
 
Php
PhpPhp
Php
 
Mysqlppt3510
Mysqlppt3510Mysqlppt3510
Mysqlppt3510
 
Mysqlppt3510
Mysqlppt3510Mysqlppt3510
Mysqlppt3510
 
Php &amp; my sql - how do pdo, mysq-li, and x devapi do what they do
Php &amp; my sql  - how do pdo, mysq-li, and x devapi do what they doPhp &amp; my sql  - how do pdo, mysq-li, and x devapi do what they do
Php &amp; my sql - how do pdo, mysq-li, and x devapi do what they do
 
Php
PhpPhp
Php
 

More from julien pauli

Doctrine with Symfony - SymfonyCon 2019
Doctrine with Symfony - SymfonyCon 2019Doctrine with Symfony - SymfonyCon 2019
Doctrine with Symfony - SymfonyCon 2019julien pauli
 
PHP Internals and Virtual Machine
PHP Internals and Virtual MachinePHP Internals and Virtual Machine
PHP Internals and Virtual Machinejulien pauli
 
Basics of Cryptography - Stream ciphers and PRNG
Basics of Cryptography - Stream ciphers and PRNGBasics of Cryptography - Stream ciphers and PRNG
Basics of Cryptography - Stream ciphers and PRNGjulien pauli
 
Mastering your home network - Do It Yourself
Mastering your home network - Do It YourselfMastering your home network - Do It Yourself
Mastering your home network - Do It Yourselfjulien pauli
 
Communications Réseaux et HTTP avec PHP
Communications Réseaux et HTTP avec PHPCommunications Réseaux et HTTP avec PHP
Communications Réseaux et HTTP avec PHPjulien pauli
 
PHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_ExtensionsPHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_Extensionsjulien pauli
 
PHPTour 2011 - PHP5.4
PHPTour 2011 - PHP5.4PHPTour 2011 - PHP5.4
PHPTour 2011 - PHP5.4julien pauli
 
Patterns and OOP in PHP
Patterns and OOP in PHPPatterns and OOP in PHP
Patterns and OOP in PHPjulien pauli
 
ZendFramework2 - Présentation
ZendFramework2 - PrésentationZendFramework2 - Présentation
ZendFramework2 - Présentationjulien pauli
 
AlterWay SolutionsLinux Outils Industrialisation PHP
AlterWay SolutionsLinux Outils Industrialisation PHPAlterWay SolutionsLinux Outils Industrialisation PHP
AlterWay SolutionsLinux Outils Industrialisation PHPjulien pauli
 
Apache for développeurs PHP
Apache for développeurs PHPApache for développeurs PHP
Apache for développeurs PHPjulien pauli
 

More from julien pauli (14)

Doctrine with Symfony - SymfonyCon 2019
Doctrine with Symfony - SymfonyCon 2019Doctrine with Symfony - SymfonyCon 2019
Doctrine with Symfony - SymfonyCon 2019
 
Php engine
Php enginePhp engine
Php engine
 
Dns
DnsDns
Dns
 
PHP Internals and Virtual Machine
PHP Internals and Virtual MachinePHP Internals and Virtual Machine
PHP Internals and Virtual Machine
 
Basics of Cryptography - Stream ciphers and PRNG
Basics of Cryptography - Stream ciphers and PRNGBasics of Cryptography - Stream ciphers and PRNG
Basics of Cryptography - Stream ciphers and PRNG
 
Mastering your home network - Do It Yourself
Mastering your home network - Do It YourselfMastering your home network - Do It Yourself
Mastering your home network - Do It Yourself
 
Tcpip
TcpipTcpip
Tcpip
 
Communications Réseaux et HTTP avec PHP
Communications Réseaux et HTTP avec PHPCommunications Réseaux et HTTP avec PHP
Communications Réseaux et HTTP avec PHP
 
PHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_ExtensionsPHPTour-2011-PHP_Extensions
PHPTour-2011-PHP_Extensions
 
PHPTour 2011 - PHP5.4
PHPTour 2011 - PHP5.4PHPTour 2011 - PHP5.4
PHPTour 2011 - PHP5.4
 
Patterns and OOP in PHP
Patterns and OOP in PHPPatterns and OOP in PHP
Patterns and OOP in PHP
 
ZendFramework2 - Présentation
ZendFramework2 - PrésentationZendFramework2 - Présentation
ZendFramework2 - Présentation
 
AlterWay SolutionsLinux Outils Industrialisation PHP
AlterWay SolutionsLinux Outils Industrialisation PHPAlterWay SolutionsLinux Outils Industrialisation PHP
AlterWay SolutionsLinux Outils Industrialisation PHP
 
Apache for développeurs PHP
Apache for développeurs PHPApache for développeurs PHP
Apache for développeurs PHP
 

Recently uploaded

『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书rnrncn29
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxMario
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxAndrieCagasanAkio
 
Top 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxTop 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxDyna Gilbert
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxmibuzondetrabajo
 
SCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is prediSCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is predieusebiomeyer
 
Film cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasaFilm cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasa494f574xmv
 
PHP-based rendering of TYPO3 Documentation
PHP-based rendering of TYPO3 DocumentationPHP-based rendering of TYPO3 Documentation
PHP-based rendering of TYPO3 DocumentationLinaWolf1
 
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书rnrncn29
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书zdzoqco
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119APNIC
 

Recently uploaded (11)

『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
『澳洲文凭』买詹姆士库克大学毕业证书成绩单办理澳洲JCU文凭学位证书
 
Company Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptxCompany Snapshot Theme for Business by Slidesgo.pptx
Company Snapshot Theme for Business by Slidesgo.pptx
 
TRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptxTRENDS Enabling and inhibiting dimensions.pptx
TRENDS Enabling and inhibiting dimensions.pptx
 
Top 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptxTop 10 Interactive Website Design Trends in 2024.pptx
Top 10 Interactive Website Design Trends in 2024.pptx
 
Unidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptxUnidad 4 – Redes de ordenadores (en inglés).pptx
Unidad 4 – Redes de ordenadores (en inglés).pptx
 
SCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is prediSCM Symposium PPT Format Customer loyalty is predi
SCM Symposium PPT Format Customer loyalty is predi
 
Film cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasaFilm cover research (1).pptxsdasdasdasdasdasa
Film cover research (1).pptxsdasdasdasdasdasa
 
PHP-based rendering of TYPO3 Documentation
PHP-based rendering of TYPO3 DocumentationPHP-based rendering of TYPO3 Documentation
PHP-based rendering of TYPO3 Documentation
 
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
『澳洲文凭』买拉筹伯大学毕业证书成绩单办理澳洲LTU文凭学位证书
 
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
办理多伦多大学毕业证成绩单|购买加拿大UTSG文凭证书
 
IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119IP addressing and IPv6, presented by Paul Wilson at IETF 119
IP addressing and IPv6, presented by Paul Wilson at IETF 119
 

Mysqlnd, an unknown powerful PHP extension

  • 1. mysqlnd an unknown powerful PHP extension
  • 2. Hola !  Julien PAULI  Working at Sensiolabs (product team : Blackfire)  PHP internals dev. and extensions writer  PHP 5.5 and 5.6 Release Manager  @julienPauli - jpauli.github.com - https://github.com/jpauli/
  • 3. Schedule  The MySQL protocols  Two protocols : binary vs textual  Discussing with MySQL using libmysql  The PHP case  Introduction to mysqlnd  Why and how  Exploring mysqlnd capabilities  Memory savings  Statistics  Plugins API
  • 4. MySQL communication  MySQL communicates with its clients using a specific protocol  MySQL protocol  Open Source  Detailed at http://dev.mysql.com/doc/internals/en/client-server-protocol. html
  • 6. MySQL protocols  When querying data, there exists 2 protocols  Textual protocol  Used for direct queries  Heavy (text), cannot represent types (int, float, etc...)  Everything is text  Easy to dump / understand / debug  Binary protocol  Used for prepared statements and stored proc  Light, efficient : can represent types (int, float...)  Not easy to dump / understand / debug
  • 7. MySQL Textual Protocol  Everything is sent as text  Even int-type columns, or not-text-type columns SELECT * FROM sl_players INT type column DATETIME type column
  • 8. MySQL Binary Protocol  Every column that is not of type CHAR is sent using the right type SELECT * FROM sl_players  More efficient, as there is no need to transform data back-and-forth id (MYSQL_T name (MYSQL_TYPE_STRING) YPE_LONG) : 4 bytes 0260 00 00 22 00 47 00 00 0b 00 00 00 01 00 00 00 06 ..".G........... 0270 6a 75 6c 69 65 6e 1b 6a 75 6c 69 65 6e 2e 70 61 julien.julien.pa 0280 75 6c 69 40 f8 65 6e 73 69 6f 6c 61 62 73 2e 63 uli@.ensiolabs.c 0290 6f 6d 0b 73 75 70 65 72 73 65 63 72 65 74 09 73 om.supersecret.s 02a0 6f 6d 65 5f 73 61 6c 74 01 01 04 de 07 0b 19 3c ome_salt.......<
  • 10. Buffered queries  A buffered query is a query whose resultset is allocated on the client side memory SELECT * FROM sl_players
  • 11. Buffered queries  A buffered query is a query whose resultset is allocated on the client side memory  Eats client's memory and not server's  Emits every byte of the result at once, on the network  The server's resultset memory is free : you can issue another request immediately  The result is on the client side, you may then count it (num_rows) or seek() through it SELECT * FROM sl_players
  • 12. Unbuffered queries  An unbuffered query is a query whose resultset is allocated on the server side memory SELECT * FROM sl_players OK
  • 13. Unbuffered queries  An unbuffered query is a query whose resultset is allocated on the server side memory  Eats server's memory and not client's  Emits bytes of the result on the network as long as you ask for data (fetch operation)  The server's resultset memory is occupied : you can not issue another request until you free the resultset memory (mysqli_free_result())  You may not seek() nor num_rows(), as the client doesn't know anything about the result's metadata SELECT * FROM sl_players OK
  • 14. Buffered, unbuffered ?  PHP will issue buffered query by default /* disable default PHP buffered queries */ $mysqli->query($query_str, MYSQLI_USE_RESULT); $pdo->setAttribute(MYSQL_ATTR_USE_BUFFERED_QUERY, 0);  It is better that the (thousands of) clients handle the memory for their own result rather than the server does
  • 15. Direct queries VS Prepared statements
  • 16. Direct Queries SELECT * FROM sl_players OK time fetch()
  • 17. Direct Queries  Client sends the query in one packet  The query is a full string with all arguments resolved etc...  The server answers with OK or KO packet  And then, depending on buffered/unbuffered mode, the server sends back the dataset into several packets  The textual protocol is used  MySQL must transform any non-text col to text  PHP can transform back the text to a useful type if mysqlnd is used
  • 18. Direct Queries Query packet Response packets
  • 19. Prepared statements SELECT * FROM sl_players WHERE id = ? OK : PSid = 42 time fetch(PSid=42) compile() PS{42} prepare() execute(PSid=42[0 : 123]) OK CloseStatement(PSid=42) PS{42} OK
  • 20. Prepared Statements (PS)  Client sends a PS packet  The query may contain placeholders for data to be fed later-on  The server answers with OK or KO packet  And compiles the query on its side, giving it a unique ID that is sent back to the client. This ID will be used for further communication  Client sends an Execute Statement Packet  Together with the PS ID and eventually the placeholders argument values.  Depending on buffered/unbuffered mode, the server sends back the resultset data into several packets  Client sends a Close Statement Packet  The server may now free the associated ressources, but usually it keeps the PS execution plan and compilation hot in memory for further use  The binary protocol is used
  • 21. Prepared Statements (PS)  Much more network communication is involved  If the query is not reused later, this may waste network resources  However, binary protocol is used, this may save resources in some specific cases  No data transformation on either side  RAW binary data may be lighter than the equivalent textual representation
  • 23. PHP & MySQL communication  3 extensions  ext/mysql  ext/mysqli  ext/PDO  2 connectors  libmysql  mysqlnd
  • 24. PHP's MySQL connectors  libmysql  mysqlnd
  • 25. libmysql  The standard default connector for every project  Written in C  Own and developped by Oracle  Double licenced, read licencing for details  Usually updated by Oracle, packaged by OS packagers  "libmysqlclient" , under Debian  Implements the MySQL protocol  knows how to communicate with MySQL servers
  • 26. libmysql example #include <stdio.h> #include <stdlib.h> #include <mysql/mysql.h> #include "mysql_example.h" /* Pour MYSQL_HOST, MYSQL_USER, MYSQL_PASS */ int main(int argv, char *argc[]) { MYSQL_RES *results = NULL; MYSQL_ROW row; MYSQL *db = NULL; db = (MYSQL *)malloc(sizeof(MYSQL)); mysql_init(db); mysql_options(db, MYSQL_INIT_COMMAND, "SET NAMES UTF8;"); if(!mysql_real_connect(db, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, NULL, 0, NULL, 0)) { fprintf(stderr, "Failed to connect to host %s (%s)", MYSQL_HOST, mysql_error(db)); exit(EXIT_FAILURE); } mysql_set_character_set(db, "utf8"); mysql_select_db(db, "my_database"); mysql_query(db , "SELECT user_id AS id FROM users WHERE description='member' LIMIT 10000"); results = mysql_use_result(db); while(row = mysql_fetch_row(results)) { printf("%sn", row[0]); } mysql_free_result(results); exit(EXIT_SUCCESS); }
  • 27. Main drawbacks  You must bind your project to libmysql $> gcc -lmysql -o example example_mysql.c  libmysql has its own memory allocator  When using buffered queries, libmysql will allocate memory - into the bound process address space - to store the results  In the case of PHP, this is a major drawback  libmysql provides its API  What if I want to go further ?
  • 30. Introducing mysqlnd  mysql Native Driver  PHP extension  Low level layer : replaces libmysql  Complete new write of the MySQL protocol  Enables features for higher level extensions  ext/mysql , ext/mysqli and ext/pdo
  • 31. mysqlnd : a PHP extension
  • 32. mysqlnd: a strange PHP extension  This extension doesn't provide any function or class of its own.  In fact, it will extend the MySQL extensions  ext/mysql ext/mysqli ext/pdo  It will work on the low layer  It is released with PHP source code  Under the PHP licence
  • 33. mysqlnd: default PHP connector ?  The extension has been released with PHP5.3  Activate at compile time --with-mysqli=mysqlnd  It is activated by default since 5.4  Cannot be built as shared (no mysqlnd.so)  However, check with your distro  For example, under Debian, it is not used by default $> apt-get install php5-mysqlnd
  • 34. mysqlnd features  PHP licence, maintained by PHP developpers  Huge memory savings in case of read-only queries (very common)  Extremely detailed statistics about the PHP-MySQL communication  Highly extensible, in C, and in PHP  Many plugins exist  A nice API
  • 35. mysqlnd architecture ext/mysql ext/mysqli ext/PDO memory allocator PHP communication Core MySQL protocols Statistics collector Network stack Plugins layer MySQL results MySQL PS Authenticator Charsets manager
  • 36. mysqlnd : save your memory  PHP extensions will use by default buffered queries  With libmysql, libmysql will then allocate memory for the whole resultset into the PHP process  As soon as you fetch your results, PHP will allocate its own memory  Conclusion : memory is allocated twice (~roughly)
  • 37. PHP mem usage with libmysql  Buffered resultset (default) echo "initial memory " . memory_usage(); $result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000"); echo "resultSet stored " . memory_usage(); while($results[] = mysqli_fetch_array($result)) { } echo "query result saved " . memory_usage(); mysqli_free_result($result); echo "resultSet freed " . memory_usage(); unset($results); echo "saved result freed " . memory_usage(); unset($db); echo "Db closed " . memory_usage(); $> phplibmysql/bin/php poc_mysqli.php initial memory ->3348 kB resultSet stored ->32508 kB query result saved ->454396 kB resultSet freed ->425468 kB saved result freed ->4092 kB Db closed ->4092 kB
  • 38. PHP mem usage with libmysql  Unbuffered resultset echo "initial memory " . memory_usage(); $result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000", MYSQLI_USE_RESULT); echo "resultSet stored " . memory_usage(); while($results[] = mysqli_fetch_array($result)) { } echo "query result saved " . memory_usage(); mysqli_free_result($result); echo "resultSet freed " . memory_usage(); unset($results); echo "saved result freed " . memory_usage(); unset($db); echo "Db closed " . memory_usage(); $> phplibmysql/bin/php poc_mysqli.php initial memory ->3348 kB resultSet stored ->3348 kB query result saved ->425236 kB resultSet freed ->425236 kB saved result freed ->3860 kB Db closed ->3860 kB
  • 39. Buffered, unbuffered query ?  Buffered $> phplibmysql/bin/php poc_mysqli.php initial memory ->3348 kB resultSet stored ->32508 kB query result saved ->454396 kB resultSet freed ->425468 kB saved result freed ->4092 kB Db closed ->4092 kB  Unbuffered $> phplibmysql/bin/php poc_mysqli.php initial memory ->3348 kB resultSet stored ->3348 kB query result saved ->425236 kB resultSet freed ->425236 kB saved result freed ->3860 kB Db closed ->3860 kB
  • 40. Fetch mode ? echo "initial memory " . memory_usage(); $result = mysqli_query($db,"SELECT user_id, date FROM users LIMIT 800000"); while($results[] = mysqli_fetch_array($result)) { } echo "query result saved with fetch_array" . memory_usage(); unset($results);mysqli_data_seek($result,0); while($results[] = mysqli_fetch_row($result)) { } echo "query result saved with fetch_row" . memory_usage(); unset($results);mysqli_data_seek($result,0); while($results[] = mysqli_fetch_assoc($result)) { } echo "query result saved with fetch_assoc" . memory_usage(); initial memory ->3348 kB resultSet stored ->32508 kB query result saved with fetch_array->454396 kB query result saved with fetch_row->333564 kB query result saved with fetch_assoc->345084 kB
  • 41. Quick points  Unbuffered ResultSets consume much less memory on the PHP side (but on the mysqld server side)  fetchAll()ing results from a buffered resultset is silly : duplicate the resultset in memory  Until you mysqli_free_result() it  You'd better fetch() each result in a sequencial way
  • 42. mysqlnd saves memory  When using a buffered query (default)  The resultset is entirely transfered into the client (PHP) memory  Using mysqlnd : mysqlnd will take care of that  When fetching a result from a resultset  mysqlnd will not duplicate the result data  It will use internal PHP's zval refcount to save many memory  If you SELECT many data, or big fields (blobs), you'll see a very huge improvement
  • 43. PHP mem usage with mysqlnd  Buffered resultset (default) initial memory ->86480 kB resultSet stored ->229632 kB query result saved ->234016 kB query result freed ->234016 kB resultSet freed ->134816 kB Db closed ->134816 kB initial memory ->88768 kB resultSet stored ->245104 kB query result saved ->414804 kB query result freed ->336628 kB resultSet freed ->198228 kB Db closed ->193924 kB mysqlnd libmysql
  • 44. PHP mem usage with mysqlnd  Buffered resultset (default) ==32226== ==32226== HEAP SUMMARY: mysqlnd ==32226== in use at exit: 0 bytes in 0 blocks ==32226== total heap usage: 15,799 allocs, 15,799 frees, 120,705,322 bytes allocated ==32226== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) ==32241== ==32241== HEAP SUMMARY: libmysql ==32241== in use at exit: 0 bytes in 0 blocks ==32241== total heap usage: 14,452 allocs, 14,452 frees, 260,903,720 bytes allocated ==32241== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
  • 45. libmysql  Roughtly doubles your ResultSet memory space 99.92% (257,473,815B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->52.90% (136,314,880B) 0x69A01E: _zend_mm_alloc_int (zend_alloc.c:1908) | ->52.60% (135,528,448B) 0x69A1DE: _estrndup (zend_alloc.c:2503) | | ->52.60% (135,528,448B) 0x533BCE: php_mysqli_fetch_into_hash (mysqli.c:1191) | | ->52.60% (135,528,448B) 0x53F2E1: zif_mysqli_fetch_array (mysqli_nonapi.c:352) | | ->52.60% (135,528,448B) 0x70186A: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) | | ->52.60% (135,528,448B) 0x6D9D96: execute (zend_vm_execute.h:107) | | ->52.60% (135,528,448B) 0x6B4B98: zend_execute_scripts (zend.c:1236) | | ->52.60% (135,528,448B) 0x663D0C: php_execute_script (main.c:2308) | | ->52.60% (135,528,448B) 0x73BCDC: main (php_cli.c:1184) | | | ->00.31% (786,432B) in 1+ places, all below ms_print's threshold (01.00%) | ->45.85% (118,130,675B) 0x52DD010: my_malloc (my_malloc.c:37) | ->45.84% (118,112,344B) 0x52E0583: alloc_root (my_alloc.c:219) | | ->45.83% (118,096,024B) 0x5307A40: cli_read_rows (client.c:1418) | | | ->45.83% (118,096,024B) 0x5305955: mysql_store_result (client.c:2957) | | | ->45.83% (118,096,024B) 0x53EF09: zif_mysqli_query (mysqli_nonapi.c:540) | | | ->45.83% (118,096,024B) 0x70186A: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) | | | ->45.83% (118,096,024B) 0x6D9D96: execute (zend_vm_execute.h:107) | | | ->45.83% (118,096,024B) 0x6B4B98: zend_execute_scripts (zend.c:1236) | | | ->45.83% (118,096,024B) 0x663D0C: php_execute_script (main.c:2308) | | | ->45.83% (118,096,024B) 0x73BCDC: main (php_cli.c:1184)
  • 46. mysqlnd, memory : conclusion  When using SELECT queries  Especially :  if you SELECT many results  if you SELECT big results, such as blobs  And you stay in read-only : you don't modify the data you fetch (but just say, display it)
  • 47. mysqlnd, memory : conclusion  When using SELECT queries  Especially :  if you SELECT many results  if you SELECT big results, such as blobs  And you stay in read-only : you don't modify the data you fetch (but just say, display it)  Then, mysqlnd will save memory for you  mysqlnd uses the PHP memory manager  the memory_limit , and the memory_get_usage()  libmysql does not
  • 50. mysqlnd statistics  bytes_sent / bytes_received  result_set_queries / non_result_set_queries  no_index_used / bad_index_used  buffered_sets / unbuffered_sets  ps_buffered_sets / ps_unbuffered_sets  ps_prepared_never_executed / ps_prepared_once_executed
  • 52. mysqlnd statistics from PHP $db = mysqli_connect('theserver', 'read-only', 'ro', 'mydb'); $result = mysqli_query($db,"SELECT user_id, date FROM users WHERE LIMIT 5"); mysqli_data_seek($result, 5); $data = mysqli_fetch_row($result); var_dump($data); mysqli_free_result($result); var_dump(mysqli_get_connection_stats($db)); ["buffered_sets"]=> string(1) "1" ["rows_fetched_from_server_normal"]=> string(1) "5" ["rows_buffered_from_client_normal"]=> string(1) "5" ["rows_fetched_from_client_normal_buff ered"]=> string(1) "1" ["connect_success"]=> string(1) "1" ...
  • 53. Using mysqlnd stats class MyMysqli extends Mysqli { public function __destruct() { $stats = $this->get_connection_stats(); $this->close(); if($diff = $stats["rows_fetched_from_server_normal"] - ($stats["rows_fetched_from_client_normal_unbuffered"] + $stats["rows_fetched_from_client_normal_buffered"])) { trigger_error("You didn't use *$diff* selected results", E_USER_NOTICE); } } }
  • 57. mysqlnd existing plugins  mysqlnd_qc  Implement query results cache  mysqlnd_uh  User Handler : take hand using PHP callbacks  mysqlnd_ms  Master/slave connection management  mysqlnd_mux  Connection multiplexer  mysqlnd_memcache  Client part for MySQL InnoDB Memcached Daemon Plugin
  • 58. mysqlnd plugins capabilities  Lots of hooks  On connection  On queries  On ResultSet creation  On the statistics manager  You can do whatever you want hooking between PHP and MySQL
  • 59. Not only in C !  mysqlnd_uh  Publishes the mysqlnd plugin API to userland class conn_proxy extends MysqlndUhConnection { public function query($res, $query) { debug_print_backtrace(); return parent::query($res, $query); } } class stmt_proxy extends MysqlndUhPreparedStatement { public function prepare($res, $query) { debug_print_backtrace(); return parent::prepare($res, $query); } } mysqlnd_uh_set_connection_proxy(new conn_proxy()); mysqlnd_uh_set_statement_proxy(new stmt_proxy());