Инсталиране и използване на dhs_mysql_profile_debuger

Не мисля, че има какво толкова да се обяснява затова направо по същество.

В. Първо какво е dhs_mysql_profile_debuger?
О. Това е проста php функция (не е вградена както става ясно по- долу), чрез която може да се следи процесорното време, паметта и времето за изпълнение на всяка заявка.

В. Как работи dhs_mysql_profile_debuger?
О. Цялостно е базирана на профилинга в MySQL

В. Може ли да работи постоянно в сайта ми?
О. Може(зависи от посещаемостта и натовареността), но определено не е желателно. Най- правилно е да се ползва за определено време с цел да се придобие информация какво натоварване правят заявките X. Един вид да ни се покажат пробойните в лодката които да запушем.

Инсталиране на dhs_mysql_profile_debuger

1. Създване на таблица в която да се съхраняват данните

drop table dhs_mysql_profile_debuger;
CREATE TABLE `dhs_mysql_profile_debuger` (
`qid` int(7) NOT NULL auto_increment,
`ddate` datetime NOT NULL,
`query` varchar(200) not null,
`query_duration` varchar(10) NOT NULL,
`cpu_duration` varchar(10) NOT NULL,
`cpu_user` varchar(10) NOT NULL,
`cpu_system` varchar(10) NOT NULL,
`mem_duration` varchar(10) NOT NULL,
PRIMARY KEY  (`qid`)
) ENGINE=MyISAM;

2. При свързване към базата данни да се сетне profiling=1

Пример: mysql_query('SET profiling = 1;', $db);

3. Include на функцията dhs_mysql_profile_debuger

#dhstudio mysql profile debuger written by amri

function dhs_mysql_profile_debuger()
{
$ddate=date('Y-m-d H:i:s');

$query="SHOW PROFILES";
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
$query_ID="{$row[0]}";
$Duration="{$row[1]}";
$Query=addslashes("{$row[2]}");

$query2="SHOW PROFILE CPU FOR QUERY $query_ID;";
$result2 = mysql_query($query2);
unset($cpu_duration);unset($cpu_user);unset($cpu_system);unset($mem_duration);
while($row2 = mysql_fetch_array($result2))
{
$cpu_duration+=number_format("{$row2[1]}", 6, '.', ' ');
$cpu_user+=number_format("{$row2[2]}", 6, '.', ' ');
$cpu_system+=number_format("{$row2[3]}", 6, '.', ' ');
};

$query2="SHOW PROFILE MEMORY FOR QUERY $query_ID;";
$result2 = mysql_query($query2);
while($row2 = mysql_fetch_array($result2))
{
$mem_duration=number_format($mem_duration+"{$row2[1]}", 6, '.', ' ');
};

$mass_insert="$mass_insert,('$ddate','$Query','$Duration','$cpu_duration','$cpu_user','$cpu_system','$mem_duration')";
if($mass_insert{0} == ",")$mass_insert=substr($mass_insert,1);
};

$query_insert="insert into dhs_mysql_profile_debuger (ddate,query,query_duration,cpu_duration,cpu_user,cpu_system,mem_duration) VALUES $mass_insert;";
$result_insert = mysql_query($query_insert);
};

4. Извикване на функцията dhs_mysql_profile_debugerв в края на всеки php файл които ще се следи

dhs_mysql_profile_debuger();#DH Studio mysql profile debuger

Извеждане на статистика за заявките

1. Извеждане на най- натоварващите CPU заявки

mysql> select * from dhs_mysql_profile_debuger order by cpu_duration desc;

2. Извеждане на най- натоварващите MEM заявки

mysql> select * from dhs_mysql_profile_debuger order by mem_duration desc;

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Какво е профил в MySQL и с какво може да ни помогне

Профил е един вид възможност да записвате вашите заявки от конкретен момент и след това да ги изследвате по- подробно. Благодарение на този метод може да видите резултата от оптимизацията(+ explain). С профил може да проследите по- подробно една заявка какво процесорно време ползва, памет и дооооста други неща :)

Ето един пример как работи. Изполваме базата "test" където създаваме таблица "t1" и процедура "dh_profile" с която да я напълним.

use test;

drop table t1;
CREATE TABLE `t1` (
`id` int(11) NOT NULL auto_increment,
`weight` int(11) NOT NULL,
`query` varchar(3072) NOT NULL,
`ddate` date NOT NULL,
PRIMARY KEY  (`id`),
KEY `query` (`query`)
) ENGINE=MyISAM;

delimiter $$
CREATE PROCEDURE dh_profile()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE (i<=100000) DO
insert into t1 (weight,query,ddate) VALUES ("1","Mysql rulz +{:>>",CURDATE());
SET i=i+1;
END WHILE;
END$$
delimiter ;

Пълним таблицата t1

mysql> call dh_profile();
Query OK, 1 row affected (37.06 sec)

Проверяваме дали профилирането е пуснато

mysql> SELECT @@profiling;
+-------------+
| @@profiling |
+-------------+
|           0 |
+-------------+
1 row in set (0.00 sec)

Пускаме профилиране

mysql> SET profiling = 1;
Query OK, 0 rows affected (0.00 sec)

Изпълняваме малка натоварваща заявка която по -- долу ще разгледам по- обстойно

mysql> select query from t1 order by rand() limit 10;
+------------------+
| query            |
+------------------+
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
| Mysql rulz +{:>> |
+------------------+
10 rows in set (5.10 sec)

Извеждаме какво е записано в профила ни

mysql> SHOW PROFILES;
+----------+------------+-----------------------------------------------+
| Query_ID | Duration   | Query                                         |
+----------+------------+-----------------------------------------------+
|        1 | 6.50790900 | select query from t1 order by rand() limit 10 |
+----------+------------+-----------------------------------------------+
1 row in set (0.00 sec)

Информация по стъпки за заявка 1

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| (initialization)               | 0.000003 |
| checking query cache for query | 0.000021 |
| Opening tables                 | 0.000005 |
| System lock                    | 0.000003 |
| Table lock                     | 0.000004 |
| init                           | 0.000008 |
| optimizing                     | 0.000002 |
| statistics                     | 0.000007 |
| preparing                      | 0.000007 |
| Creating tmp table             | 0.000027 |
| executing                      | 0.000003 |
| Copying to tmp table           | 0.017907 |
| converting HEAP to MyISAM      | 0.049151 |
| Copying to tmp table on disk   | 4.75879  |
| Sorting result                 | 0.268406 |
| Sending data                   | 0.000364 |
| end                            | 0.000004 |
| removing tmp table             | 1.413161 |
| end                            | 0.000014 |
| query end                      | 0.000005 |
| freeing items                  | 0.000009 |
| closing tables                 | 0.000006 |
| logging slow query             | 0.000002 |
+--------------------------------+----------+
23 rows in set (0.01 sec)

Извеждане на всички стъпки при заявка 1 + тяхното CPU натоварване

mysql> SHOW PROFILE CPU FOR QUERY 1;
+--------------------------------+----------+----------+------------+
| Status                         | Duration | CPU_user | CPU_system |
+--------------------------------+----------+----------+------------+
| (initialization)               | 0.000003 | 0        | 0          |
| checking query cache for query | 0.000021 | 0        | 0          |
| Opening tables                 | 0.000005 | 0        | 0          |
| System lock                    | 0.000003 | 0        | 0          |
| Table lock                     | 0.000004 | 0        | 0          |
| init                           | 0.000008 | 0        | 0          |
| optimizing                     | 0.000002 | 0        | 0          |
| statistics                     | 0.000007 | 0        | 0          |
| preparing                      | 0.000007 | 0        | 0          |
| Creating tmp table             | 0.000027 | 0        | 0          |
| executing                      | 0.000003 | 0        | 0          |
| Copying to tmp table           | 0.017907 | 0.016001 | 0          |
| converting HEAP to MyISAM      | 0.049151 | 0.024001 | 0.028001   |
| Copying to tmp table on disk   | 4.75879  | 0.260017 | 0.644041   |
| Sorting result                 | 0.268406 | 0.17201  | 0.0960059  |
| Sending data                   | 0.000364 | 0        | 0.004      |
| end                            | 0.000004 | 0        | 0          |
| removing tmp table             | 1.413161 | 0        | 0.088005   |
| end                            | 0.000014 | 0        | 0          |
| query end                      | 0.000005 | 0        | 0          |
| freeing items                  | 0.000009 | 0        | 0          |
| closing tables                 | 0.000006 | 0        | 0          |
| logging slow query             | 0.000002 | 0        | 0          |
+--------------------------------+----------+----------+------------+
23 rows in set (0.00 sec)

Извеждане на всички стъпки при заявка 1 + натоварването в паметта

mysql> SHOW PROFILE MEMORY FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| (initialization)               | 0.000003 |
| checking query cache for query | 0.000021 |
| Opening tables                 | 0.000005 |
| System lock                    | 0.000003 |
| Table lock                     | 0.000004 |
| init                           | 0.000008 |
| optimizing                     | 0.000002 |
| statistics                     | 0.000007 |
| preparing                      | 0.000007 |
| Creating tmp table             | 0.000027 |
| executing                      | 0.000003 |
| Copying to tmp table           | 0.017907 |
| converting HEAP to MyISAM      | 0.049151 |
| Copying to tmp table on disk   | 4.75879  |
| Sorting result                 | 0.268406 |
| Sending data                   | 0.000364 |
| end                            | 0.000004 |
| removing tmp table             | 1.413161 |
| end                            | 0.000014 |
| query end                      | 0.000005 |
| freeing items                  | 0.000009 |
| closing tables                 | 0.000006 |
| logging slow query             | 0.000002 |
+--------------------------------+----------+
23 rows in set (0.00 sec)

PS: Надявам се публикацията бъде полезни на всеки MySQL оптимизатор. Успех!

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Поправяне на цяла база в MySQL(repair table)

Тук идеята е, че ПРИМЕРНО имате повредени 100 таблици база X, но базата съдържа  200 таблици. Едвали на някои ще му допадне да правя: repair table t1;repair table t2; или да пише скриптче което да ги обхожда една по една като има съвсем лесно решение на това с един ред(предоставен ни от MySQL пакета).

mysqlcheck -r databaseX -uroot -p

По този начин "repair table Xn" ще бъде изпълнено за всички таблици от базата "databaseX".

PS: Подобна публикация, но за оптимизиране на всички таблици от конкретна база: Жокер- optimize на mysql база

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

MySQL- Извеждане на неоптимизираните таблици- fragmented tables

Идеята е да оптимизираме тези таблици само които са оптимизирани и MyISAM разбира се :)
С една заявка можем да изведем тези  таблици:

mysql> SELECT TABLES.TABLE_SCHEMA,TABLES.TABLE_NAME,TABLES.DATA_FREE,TABLES.ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLES.DATA_FREE!=0;
+-----------------+----------------+-----------+--------+
| TABLE_SCHEMA    | TABLE_NAME     | DATA_FREE | ENGINE |
+-----------------+----------------+-----------+--------+
| database1    | table_confirm  |       196 | MyISAM |
| database1    | table_sessions |     29460 | MyISAM |
| database1    | table_users    |        24 | MyISAM |
| database2 | table2       |        56 | MyISAM |
+-----------------+----------------+-----------+--------+
4 rows in set (0.04 sec)

В моя случай имам 4(понеже ги оптимизирам доста често)

Ето и как се оптимизира конкретна таблица:

mysql> optimize table database1.table_confirm;
+----------------------------+----------+----------+----------+
| Table                      | Op       | Msg_type | Msg_text |
+----------------------------+----------+----------+----------+
| database1.table_confirm | optimize | status   | OK       |
+----------------------------+----------+----------+----------+

PS: Всичко това може да си го автоматизирате с perl,bash,php или там каквото ви е на сърце :). Успех

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

MySQL- Спиране на duplicate key erros при insert на доста стойности

Идеята е да се спести ресурс като се направи един INSERT с доста стойности в место нормалния метод с INSERT за всяка стойност. Тук обаче има подробност, че при INSERT на5 стойности(на пример) и едната е дублирана излиза грешка което пречи на останалите 4 да бъдат записани.

Решенията които се сещам са следните:

1. Проверява се които са налични и така се прави INSERT само на новите
2. Прави се insert но със INSERT IGNORE.

Пример за решение 2:

Без употреба на INSERT IGNORE:

mysql> insert into tags_basic (date_add,time_add,tag) VALUES ('2010-09-27','16:09:43','tag1'),('2010-09-27','16:09:43','tag2'),('2010-09-27','16:09:43','tag3'),('2010-09-27','16:09:43','tag5');
ERROR 1062 (23000): Duplicate entry 'tag1' for key 2

С употреба на INSERT IGNORE:

mysql> insert ignore into mtable (date_add,time_add,tag) VALUES ('2010-09-27','16:09:43','tag1'),('2010-09-27','16:09:43','tag2'),('2010-09-27','16:09:43','tag3'),('2010-09-27','16:09:43','tag5');
Query OK, 1 row affected (0.01 sec)
Records: 4  Duplicates: 3  Warnings: 0

На мен лично ми допада метод 2 понеже не се изискват допълнителни select заявки и калкулации в php/perl или каквото е там.

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Един форум на SMF се счупи

Един forum на SMF се счупи и какво да гледам:

mysqld[14988]: 100923 10:59:07 [ERROR] /usr/sbin/mysqld: Incorrect key file for table './database/smf_log_online.MYI'; try to repair it


Решение на проблема:

mysql> repair table smf_log_online;
+-------------------------------+--------+----------+------------------------------------+
| Table                         | Op     | Msg_type | Msg_text                           |
+-------------------------------+--------+----------+------------------------------------+
| ciscodchjoomla.smf_log_online | repair | warning  | Number of rows changed from 7 to 8 |
| ciscodchjoomla.smf_log_online | repair | status   | OK                                 |
+-------------------------------+--------+----------+------------------------------------+

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Изтриване на файл започващ с тире

Проблем при триенето на файлове или директории започващи с тире или dash

cd /tmp
touch ./'--dash-file'

Пробваме да изтрием файла започващ със dash:

machine:/tmp# rm -fr --dash-file
rm: unrecognized option `--dash-file'
Опитайте „rm ./--dash-file“, за да изтриете файла „--dash-file“.
Използвайте „rm --help“ за повече информация.

Виждаме, че дава грешка.

Решението е много просто, ето го и него:

rm -fr ./--dash-file

Готово :)

PS: Последно време пиша сравнително простички и често срещани проблеми понеже доста хора се сблъскват с тях които незнаят как да ги разрешат. Дано тези съвети им помогнат :)

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Как да архивираме с tar без някои директории

Идеята е да архивираме цялата директория X без нейната под директория XY.
Реален случай: Имаме сайт които използва кеширане и съхранява всички статични файлове в директория cache. Решаваме да архивираме сайта, но без директорията cache и за целта изпълняваме:

tar zcvvf website.tar.gz website/ --exclude=cache

По този начин архивираме целия сайт без директорията cache

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Жокер- optimize на mysql база

Сетих се да споделя как може да се изпълни "optimize table" на всички таблици в една база с една команда. Идеята е, че ако имате база с 300 таблици няма как една по една да изпълнявате "optimize table" както и не е необходимо да се пише скрипче което да ги обикаля и изпълнява. Решението е супер просто :

mysqlcheck -o DB -p

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Триене на MySQL bin логове

На доста хора сигурно се е случвало на по- стара машина с малък диск да има пусната сравнително големичка база и сайт. След време bin логовете пълнят целия хард и MySQL спира да работи. Какво решението ?!

1. Да се спре създаването на bin логове(които не препоръчвам)
2. Да се трият периодично(под периодично не разбирам всеки ден или през ден)

Решение:
След като сме се логнали в MySQL може да видим bin логовете по следния начин:

SHOW BINARY LOGS;

+------------------+------------+
| Log_name         | File_size  |
+------------------+------------+
| mysql-bin.001522 |     908287 |
| mysql-bin.001523 |   17500544 |
| mysql-bin.001524 |   11443409 |

Може да се трият един по един:

PURGE BINARY LOGS TO 'mysql-bin.001524';

или да се изтрият преди конкретна дата(може да се ползва и час)

PURGE BINARY LOGS BEFORE '2010-10-10 10:10:10';

VN:F [1.9.22_1171]
Rating: 5.0/5 (1 vote cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Личен Блог на Мартин Петров