BUZZ NEEDS YOUR VOTES!



Posts Tagged “mySQL”

The problem that most people face when setting up a UTF-8 database in mySQL is that without calling ‘SET NAMES’ in the mySQL client prior to issuing any queries (PHP, C++ etc …) that the client connection will actually in most cases default to  latin-1.

However as of mySQL 5.x or higher you can issue a statement in the my.cnf file calling init_connect.

This will trigger a series of defined commands / queries every time a non super user connects (So if you are using root to connect to your mySQL database, stop reading now and slap yourself HARD).

i.e.

[mysqld]
init_connect=’SET collation_connection = utf8_general_ci’
init_connect=’SET NAMES utf8′
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci

Restart mySQL and check the mysqld.log has not returned any errors (Or your event viewer if you are using windows).

Every client connection will now default to utf-8 encoding and not latin-1, removing the need to add a SET NAMES call on every connection.

This will work for PHP, C++, ruby etc… as the client encoding is now handeled server side, rather that waiting on the client to issue a SET NAMES command.

Comments No Comments »

The downside of a development server is … it’s for development.

It is  not always cost effective to have the exact same setup as you you have in your production environment …

Especially if you have a multi server setup.

So I find myself today moving /var/lib/mysql … being as the OS drive is very small, and pulling down a near 20GB database backup and then trying to rebuild the database on the same drive … well as you can imagine caused a few problems *doh*


/etc/init.d/mysql stop
mv /var/lib/mysql /raid_5/

So surely you just symlink … right?


ln -s /raid_5/mysql /var/lib/mysql
/etc/init.d/mysql start

Well then answer would be no … upon importing the backup


mysql < backup.sql
Can't create table './database/table.frm' (errno: 121)

A nice errorno: 121


/etc/init.d/mysql stop
rm -rf /var/lib/mysql
mkdir /var/lib/mysql
chown mysql:mysql /var/lib/mysql
mount --bind /raid_5/mysql /var/lib/mysql
/etc/init.d/mysql start

et voila …

Data directory is relocated and the import working smoothly. Feel free to suggest any “cleaner” methods.

Comments No Comments »

“adimpleo” Latin for “to perform”, seemed a fitting name for dbStat.

dbStat is currently being re-worked to include the use of rrdtool among other features, “adimpleo” is to be geared towards providing an “under the hood” view of LAMP based web applications.

Expect screenshots soon.

Comments 2 Comments »

So I thought maybe it’s time for an update.

The project is moving, albeit slowly, and I realy do not like the current PHP implementation, I want to move towards a C++ version, and I will do so as soon as I figure out how to do CLI “update/refresh” …

i.e. See how W GET works with the progress bar and kbps all in text, I have NO idea how that works.

I am also looking at adding RRDTOOL support.

Anyway here’s the current sample output:

[buzz@server01 .sysadmin]$ ./dbstat.php summary

----- mySQL dbStat v1.1 Summary Report-----

10 Databases checked

exampledb1: 13 tables (0 VIEWS 13 INNODB 0 MYISAM) 0.77MB DATA 0.64MB INDEX
exampledb2: 15 tables (0 VIEWS 14 INNODB 1 MYISAM) 0.22MB DATA 0.19MB INDEX
exampledb3: 62 tables (0 VIEWS 0 INNODB 62 MYISAM) 0.45MB DATA 0.5MB INDEX
exampledb4: 3 tables (0 VIEWS 0 INNODB 3 MYISAM) 0.02MB DATA 0.01MB INDEX
exampledb5: 4 tables (0 VIEWS 0 INNODB 4 MYISAM) 0.02MB DATA 0.01MB INDEX
exampledb6: 4 tables (0 VIEWS 0 INNODB 4 MYISAM) 39.81MB DATA 22.22MB INDEX
exampledb7: 3 tables (0 VIEWS 0 INNODB 3 MYISAM) 0.04MB DATA 0.01MB INDEX
exampledb9: 599 tables (8 VIEWS 1 INNODB 590 MYISAM) 8702.79MB DATA 4559.42MB INDEX
exampledb10: 22 tables (0 VIEWS 21 INNODB 1 MYISAM) 6.66MB DATA 2.26MB INDEX

Detail:

----- START mySQL dbStat v1.1 Detail Report: exampledb9 -----
exampledb9: 599 tables (8 VIEWS 1 INNODB 590 MYISAM) 8893.7MB DATA 4583.54MB INDEX
--- Table Index Ratio Report index:data (457 Tables) ---
exampledb9.table1: 315.0769:1
exampledb9.table2: 315.0769:1
exampledb9.table3: 157.5385:1
exampledb9.table4: 146.2857:1
exampledb9.table5: 128.0000:1

… (I’ve truncated this very long list)

--- Table Fragmentation Report (2 Tables) ---
exampledb9.atable: 0.6067
exampledb9.atable: 0.1285
--- Table Low Size Report (47 Tables) ---
exampledb9.atable: 0 bytes
exampledb9.atable: 0 bytes
exampledb9.atable: 0 bytes
exampledb9.atable: 0 bytes
exampledb9.atable: 0 bytes

… (Truncated again)

--- Table Detail Report (591 Tables) ---
SCHEMA.TABLENAME: ENGINE: ROWS: TOTAL SIZE (MB): DATA SIZE (MB): DATA PERCENTAGE OF TOTAL (%): INDEX SIZE (MB): INDEX PERCENTAGE OF TOTAL (%): LAST UPDATE TIME
exampledb9.a_table: MyISAM: 28906414: 3272.43531003: 3031.82567548: 92.6474: 204.63809450: 7.3526: 2008-05-22 11:59:42

.. (truncated)

----- END mySQL dbStat v1.1 Detail Report: exampledb9 -----

Comments No Comments »

Trent Hornibrook has started a mysql dba blog, so I thought i’d provide some linkage :-)

These two articles cover how to use the mysql explain syntax for “debugging” sql queries so be sure to read part 1 and part 2

Comments No Comments »

To often I get passed code to review that quite frankly is so full of holes it wouldn’t make an adequate sieve…

So in this quick blog I outline a few simple and easily implemented steps to ensure as you start out in the world of PHP, your first site isn’t hacked within 5 minutes, leaving you a whimpering wrek …

PHP DON’T EXAMPLE 1:

Passing RAW globals to mysql!

i.e.

$sql = "SELECT * FROM users WHERE email='.$_GET['email'].”‘ and password=’”.$_GET['password']“‘;”;
$result = mysql_query($sql);

So what is wrong with the above? SQL INJECTION welcome to a world where people want to break your website, simply because they can …

I am not going to add more description, just click through to the wiki pedia entry linked above …

To avoid this PHP comes with two functions mysql_escape_string() and mysql_real_escape_string()

An example taken from the mysql_real_escape_string() page:

Example#2 An example SQL Injection Attack

<?php
// Query database to check if there are any matching users
$query = “SELECT * FROM users WHERE user=’{$_POST['username']}’ AND password=’{$_POST['password']}’”;
mysql_query($query);
// We didn’t check $_POST['password'], it could be anything the user wanted! For example:
$_POST['username'] = ‘aidan’;
$_POST['password'] = “‘ OR ”=’”;
// This means the query sent to MySQL would be:
echo $query;
?>

The query sent to MySQL:

SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''

This would allow anyone to log in without a valid password.

So in summary READ the mysql_real_escape_string() page, and even if you don’t implement the “best practice” example on that page PLEASE make sure you at least escape $_SESSION $_GET $_POST inputs with a mysql escape function!

Comments 3 Comments »

So you’ve recently made a change to your mysql installation and see the following in

 /var/lib/mysql/server.err

 080317 14:08:50 mysqld started
080317 14:08:50 [ERROR] Fatal error: Can’t change to run as user ‘mysql’ ; Please check that the user exists!
080317 14:08:50 [ERROR] Aborting

080317 14:08:50 [Note] /usr/sbin/mysqld: Shutdown complete

080317 14:08:50 mysqld ended

 This is a problem that many a time spent on google has not found the result, so I am writing here what exactly to do in this situation …

 First off

cd /var/lib/mysql

Now run ls -la

 No doubt you will see something similar to this:

drwx--x--x 2 27 mysql 4096 Mar 17 14:05 mysql

Notice the “27 mysql”, the user no longer existsing in /etc/passwd.

This is fairly simple to fix.

adduser mysql
chown mysql:mysql -R /var/lib/mysql

Now start up Mysql i.e. “service start mysql” and everyhing _should_ be fine. 

Comments No Comments »

I have been working on a script as of late to aid in the ever ongoing process of optimizing a web applications “back end”, inevitably the database, and underlying code.

Thus dbstat was born, the current version is not for release _just yet_ , as some tweaks are still needed, at the moment it only supports reporting for a single database at any one time.

v 0.5 Features list.

  1. Dynamic / Fixed row size checking. (Dynamic size rows can cause table fragmentation).
  2. MyISAM / InnoDB  checking (Reports total number of tables using these engines).
  3. Index threshold testing.
  4. Table fragmentation threshold testing.
  5. Table size threshold testing.
  6. Database size reporting.

At the moment this is currently written in PHP, and is quite heavily scripted I will be looking to move to C++ for a v1.0 for the release, for calculations sake and to remove the need to install PHP.

I will post more information as the project develops, I will be looking to release the program and source under GPL by version 1.

By version 1, I intend to have included the following:

  1. User interactive reporting. (On even of threshold being exceeded, prompt user to fix or skip, with cursory notes*)
  2. Table de-fragmentation.
  3. Reporting to include suggested fixes.

*Cursory notes  to describe the fix, and possible implications of actioning it.

So watch this space, and please leave requests via comments :)

Comments 1 Comment »

** Note I am not the “Buzz” from 3dbuzz.com this is just a coincidence **

All right lets begin…

First off you will need to understand how to take advantage of mySQL’s inbuilt fulltext search functionality.

First lets create the table, using the cli or your favorite GUI (i.e. mysql administrator) to run the following SQL statement.

Code:

CREATE DATABASE sion_ft;

USE sion_ft;

CREATE TABLE sion_ft_tutorial (

Id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,

Title VARCHAR (255),

Body LONGTEXT

)

ENGINE=myISAM;

ALTER TABLE sion_ft_tutorial ADD FULLTEXT search (title,body);

Ok we have now created a database, changed to use that database, and created that databases first table, then altered the table to add a fulltext index for both the “title” and “body” columns, and called this index “search”.

Notice the “ENGINE=myISAM;”, unfortunately it seems InnoDB does not support full text indexes. At least that’s the problem I ran into using mySQL 4.x.

Now before we go any further we need to put some data into that database so it can be searched.

Code:

INSERT INTO sion_ft_tutorial (title,body) VALUES

('Sion Fulltext tutorial at 3dbuzz', 'Posted originally by sion at the 3dbuzz forums…'),

('3DBUZZ.com ', 'Look Listen Learn, forums vtm's and more'),

('I am hungry', 'Lets order pizza!!' ),

('hi Ho Hi Ho', 'A forum trolling I will go' ),

('PHP problems?', 'Go to 3dbuzz forums, where some nutter called sion roams.' );

Ok now we have inserted 5 rows of data into the table, we will use this data when testing our fulltext search.

Before we begin with the PHP we need to construct the SQL statement to use the FULL text feature, so keep that CLI OPEN!

Code:

SELECT * FROM sion_ft_tutorial WHERE MATCH(title,body) AGAINST('sion');

+----+----------------------------------+----------------------------------------------------------+

| id | title | body |

+----+----------------------------------+----------------------------------------------------------+

| 1 | Sion Fulltext tutorial at 3dbuzz | Posted originally by sion at the 3dbuzz forum􏺅 |

| 5 | PHP problems? | Go to 3dbuzz forum, where some nutter called sion roams. |

+----+----------------------------------+----------------------------------------------------------+

Ok so the search is now working no we need to get the relevance score working.

Code:

SELECT *, MATCH(title,body) AGAINST('sion') AS score FROM sion_ft_tutorial WHERE MATCH(title,body) AGAINST('sion');

+----+----------------------------------+----------------------------------------------------------+------------------+

| id | title | body | score |

+----+----------------------------------+----------------------------------------------------------+------------------+

| 1 | Sion Fulltext tutorial at 3dbuzz | Posted originally by sion at the 3dbuzz forum􏺅 | 0.53033631317832 |

| 5 | PHP problems? | Go to 3dbuzz forum, where some nutter called sion roams. | 0.37130504609119 |

+----+----------------------------------+----------------------------------------------------------+------------------+

As you can see id 1 has the higher score this is because “sion” is found both in the title and the body text.

The “relevance score” is calculated by hard code formulae within mySQL.

Full details on this formulae can be found here : http://dev.mysql.com/doc/internals/en/full-text-search.html

This covers the mySQL side of the system.
PHP

First off we have to make some assumptions for this method to work.

We have to assume that the highest score is equivalent to 100% relevant to the search.

And for this “basic” stage we have to assume that the default mySQL setup is sufficient for our needs, as there is a whole host of things to configure such as minimum word length, and mySQL’s “stop list” to consider.

This will be covered in the “fine tuning” section of this tutorial.

I am also assuming you have read the above section on mySQL and not skipped strait to the PHP code.

First of all as I’m sure you know we need to create a connection to the mySQL server.

Code:

$usr = "mysqlusr";

$pass = "mysqlpass";

$host = "localhost";

$db = "sion_ft";

$connection = mysql_connect($host,$usr,$pass);

mysql_select_db($db,$connection);

?>

Ok so lets now get some data to start playing with.

Code:

$query = "SELECT *, MATCH(title,body) AGAINST('sion') AS score FROM sion_ft_tutorial WHERE MATCH(title,body) AGAINST('sion') ORDER BY SCORE DESC";

$result = mysql_query($query);

$row = mysql_fetch_assoc($result);

??

Now we have the data as mentioned above in the MYSQL section.

Remember I said we have to “assume” the highest score is 100% relevant. well lets do that and start creating relevance percentages.

Code:

$max_score = 0;

$data = array();

do {

if($row['score'] > $max_score){ $max_score = $row['score']; } //because we are ordering by score we can assume on the first run this wil be the max score.

echo $row['title'].” “.@number_format(($row['score']/$max_score)*100,0).”%<br>n”;

}while($row = mysql_fetch_assoc($result));

Now you should get a list that looks something like the following.

Sion Fulltext tutorial at 3dbuzz 100%

PHP Problems? 70%

Right so lets go over what we have done so far, we have used mySQL’s inbuilt “relevance” calculation and assume the highest “score” to bee 100% as such we have used that score as the “denominator” for the result of the results to calculate their percentage relevance.

Comments No Comments »