Download as pdf or txt
Download as pdf or txt
You are on page 1of 45

<Insert Picture Here>

Building High Performance and High Traffic PHP Applications with MySQL Part 2: Best Practices
Johannes Schlter & Ulf Wendel MySQL Engineering: Connectors & Client Connectivity Wei-Chen Chiu MySQL Product Marketing Manager

About MySQL
Founded in 1995 Acquired by Sun Microsystems in February 2008 Acquired by Oracle in January 2010 The Worlds Most Popular Open Source Database MySQL Commercial Editions Available

2011 Oracle Corporation Proprietary and Confidential

Oracles Investment in MySQL


Make MySQL a Better MySQL
- #1 Open Source Database for Web Applications - MySQL 5.5 GA Better Performance and Scalability

Develop, Promote and Support MySQL


- Improve engineering, consulting and support - MySQL Track at Oracle OpenWorld 2011 - Leverage 24x7, World-Class Oracle Support

MySQL Community Edition


- Source and binary releases - GPL license

2011 Oracle Corporation Proprietary and Confidential

MySQL Customers

Web

OEM / ISVs

SaaS, Hosting

Telecommunication s

Enterprise 2.0

MySQL Powers the Web


2011 Oracle Corporation Proprietary and Confidential

<Insert Picture Here>

Building High Performance and High Traffic PHP Applications with MySQL Part 2: Best Practices
Johannes Schlter MySQL Engineering: Connectors & Client Connectivity

<Insert Picture Here>

Introduction

PHP and MySQL

PHP Application

ext/mysql

mysqli

PDO_mysql

mysqlnd / libmysql

MySQL Server

PHP and MySQL

PHP Application

ext/mysql

mysqli

PDO_mysql

mysqlnd / libmysql Today we're mostly talking about this MySQL Server

Basic Assumptions for PHP Web Applications

Huge number of of short connections A web request should be handled in way less than a second Many requests happen in parallel Database server close to Web-Server Low latency Sometimes MySQL installed on the same machine as the Web server

<Insert Picture Here>

Connection Basics

Connection Stages

1.Establish Transport Layer Connection 2.MySQL Handshake 3.Authentication 4.MySQL Commands

Transport Layer

Unix Domain Socket Local communication on Unix/Linux systems /tmp/mysql.sock Windows Named Pipes Local communication on Windows systems TCP/IP Socket Network-based communication TCP Port 3306

Connecting using Unix Domain Socket

mysql_connect('localhost', 'user', 'password');

mysql_connect(':/tmp/mysql.sock', 'user', 'password'); new mysqli('localhost', 'user', 'password', 'schema', 0, '/tmp/mysql.sock'); new PDO('mysql:unix_socket=/tmp/mysql.sock', 'user', 'password');
Default Location when using localhost compiled in php.ini

Persistent Connections
The initial problem Establishing a connection takes time A solution Re-Use an existing MySQL connections over multiple requests

The problem there A connection has associated resources Session variables, temporary tables, PS handles, ..
A solution Reset the connection using change_user MySQL call The consequence Saves transport creation and initial MySQL handshake

<Insert Picture Here>

Connection Options

Setting Options While Connecting

$mysqli = mysqli_init(); $mysqli->options( MYSQLI_OPT_CONNECT_TIMEOUT, 5); $mysqli->ssl_set($key, $cert, $ca, $capath, $cipher); $mysqli->real_connect( 'localhost', 'my_user', 'my_password', 'my_db');

Compression

MySQL compresses each packet individually Each returned row is (usually) one packet Compression costs CPU to reduce network IO With bad luck compression consumes more IO SELECT id FROM table Will most likely show bad compression ratio, even with many rows SELECT complete_article_text FROM table Might have good compression ratio

Encryption

Encryption is being enabled during the initial

handshake All subsequent communication (incl. authentication) will be encrypted


Passwords will always be transferred in a scrambled safe manner only

SSL handshake time (incl. certificate validation etc.)

takes relatively long

Encryption Alternative: stunnel

stunnel is a daemon holding an encrypted connection

between two hosts


MySQL server and Web server

SSL Handshake happens only once MySQL doesn't see encryption http://stunnel.org

Character Sets

MySQL has a rich support for character set and

encodings Character set can be changed using


SQL: SET NAMES API: mysql_set_charset, mysqli::set_charset, PDO DSN

Always use these API calls to set the character set so

escape routines know about it!

<Insert Picture Here>

Query Execution

Buffered and Unbuffered Result Sets

Buffered Results Copies the complete result set to the client (PHP) Minimal memory usage on Server

Unbuffered Results Copies rows in sequence as needed Minimal memory usage on Client

Result Sets

$result= $mysqli->query($sql, $mode); $mode is either MYSQLI_STORE_RESULT (buffered) or MYSQLI_USE_RESULT (unbuffered) Free buffered result sets mysqli_free_result($result);

MySQL Multi Query

Execute multiple queries in one go


$query = "SELECT id FROM t1;"; $query .= "SELECT id FROM t2"; if ($mysqli->multi_query($query)) { do { if ($result = $mysqli->use_result()) { while ($row = $result->fetch_row()) { /* ... */ } $result->close(); } if ($mysqli->more_results()) { /* print divider or such */ } } while ($mysqli->next_result()); }

MySQL Multi Query

Pros of Multi Query: Reduced latency in communication Base technology needed for stored procedures Cons of Multi Query: No automatic association of a result set to a query Higher risk of danger with SQL injection Security: $mysql->multi_query( 'SELECT * FROM t WHERE id = '.$_GET['id']);
$_GET['id'] = '23; DROP TABLE t';

Under the Hood The MySQL Protocol

The client's request is a small packet (COM_QUERY)

including little meta data and the query test The server will respond with an OK package if there are no result sets or an error package or
An result set header package Followed by a field header packages for each field (column) containing field meta data (types, max length, ) Followed by a row package for each row All data is transferred as string Followed by an EOF package

<Insert Picture Here>

Prepared Statements

Prepared Statements

Client
SELECT foo FROM bar WHERE id = 42

Server

Create Execution plan Query database Resultset(s)

Prepared Statements Client SELECT foo FROM bar WHERE id = ? Server

Create basic Execution plan

Handle
Handle Param 1: 42 Resultset(s)

Query database

Under the Hood The MySQL Protocol

A COM_PREPARE package is similar to COM_QUERY The server responds with either OK or ERR, the OK package returns a statement ID The COM_EXECUTE package refers to this ID and also includes all bound values The result is similar to COM_QUERY

Prepared Statements and Persistent Connections

With persistent connections the connection is held But PS handles are freed pscache is an experimental plugin helping We will talk about plugins in

part 3 of this series.

Prepared Statements and PDO

The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. http://php.net/intro.pdo It is heavily build around Prepared Statements (PS) For handling PS it has to do two things:
Mapping placeholders Do PS emulation (optional)

PDO Parameter Handling: PHP Bug #54929

<?php $query = "/* ' */ select ? as f1, 'bar' as f2"; $pdo = new PDO("mysql:dbname=...;host=...", "...", "..."); $stmt = $pdo->prepare($query); if (!$stmt->execute(array("foo"))) { $errInfo = $stmt->errorInfo(); print_r($errInfo); } ?>

PDO Emulation <?php $pdo = new PDO(mysql:host=localhost;dbname=test, user, password);


$query = $pdo->prepare( SELECT id FROM table LIMT ?, ?); $query->bindValue(1, $_GET[offset]); $query->bindValue(2, $_GET[limit]); $query->execute(); SELECT id FROM table LIMIT '1', '2'

PDO Emulation

Even $pdo->query($sql); will go through the prepared statements API in PDO MySQL historically did not support all statements to be prepared
OPTIMIZE TABLE, ANALYZE TABLE, ALTER TABLE,

PDO falls back on emulation, even if emulation failed due to other errors PDO developers decided to use emulation by default PDO::MYSQL_ATTR_DIRECT_QUERY

<Insert Picture Here>

Monitor The Performance

mysqlnd Statistics

Around 150 statistic values collected mysqli_get_client_stats (), mysqli_get_connection_stats()

Statistics Cookbook

Check PS Execution Ratio


$stats = mysqli_get_client_stats(); echo $stats['com_execute'] / $stats['com_prepare'];

Check for unprocessed rows


$mysqli->close(); $stats = mysqli_get_client_stats(); echo $stats['rows_skipped_normal'] + $stats['rows_skipped_ps'];

Do more with mysqlnd plugins

mysql_query()

mysqli::query()

PDO::query()

mysqlnd Query Plugin Hook Wire Protocol

Plugin Hook
Network

mysqlnd Plugins

mysqlnd client proxy


Load Balancing Read / Write splitting Failover Monitoring Query Logging Query Auditing Performance Caching Sharding

Learn more in Part 3 of this series!

Learn More: Resources


Use MySQL with PHP http://dev.mysql.com/usingmysql/php/ Read Connector/PHP User Manual http://dev.mysql.com/doc/refman/5.1/en/apis-php.html Download Free MySQL White Papers http://dev.mysql.com/why-mysql/white-papers/ View MySQL Training Courses http://www.oracle.com/education/mysql

Follow MySQL Updates on Facebook http://www.facebook.com/mysql

MySQL at Oracle OpenWorld 2011


OpenWorld
31 MySQL Sessions in the Database Track 12 Community Driven Sessions on Sunday 3 Demo Pods 1 Hands-on Lab MySQL Workbench Register Now:
http://www.oracle.com/openworld/register/packages/index.html

MySQL Community Reception


October 4 @ 7pm San Francisco Marriott Marquis Open to everyone! RSVP Now: http://bit.ly/MySQLCommunityReception

The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracles products remains at the sole discretion of Oracle.

<Insert Picture Here>

Thank You!
Johannes Schlter johannes.schlueter@oracle.com Ulf Wendel Ulf.wendel@oracle.com

You might also like