Arxiv

Posts Tagged ‘point in time recovery’

Point-in-time recovery with MySQL row based binary log

İyun 28, 2013 2 şərh

/* Replication setup edənlər mütləq şəkildə binlog_format=row qeyd etməyi unutmasınlar */

Binary log-un nə olduğunu və hansı zamanlarda istifadə olunduğuna qısa olaraq toxunsaq əsasları:
1. Point-in-time recovery
2. Replication

Biz indi point-in-time recovery-yə baxacıq. Statement binary log formatında(default format)
hər şey çox sadədir yəni cədvələ edilən dəyişikliklər elə məhz statement şəklində bin log-a qeyd olunur. Statement bin log formatı üçün artıq bir yazım var : Statemen Binary log format

İndi isə row based binary log-la işləyək biraz.
Mövcud binary log-larımız tapaq:

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000031 |       120 |
+------------------+-----------+
1 row in set (0.13 sec)

Hansı hal hazırda istifadədir ona baxaq:

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000031
         Position: 120
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

mysql-bin.000031 hal hazırda istifadədir. Position-u 120.

Cədvəl yaradaq və məlumat daxil edək:

mysql> create schema backup_test character set=utf8;
Query OK, 1 row affected (0.26 sec)

mysql> use backup_test;
Database changed

mysql> create table test_table(
    -> id int not null auto_increment,
    -> name varchar(15),
    -> surname varchar(20),
    -> primary key(id)
    -> );
Query OK, 0 rows affected (0.74 sec)

mysql> insert into test_table(name,surname) values('Shahriyar','Rzayev'),('Khatai','Rzayev'),('Elvin','Binyatov');
Query OK, 3 rows affected (0.16 sec)
Records: 3  Duplicates: 0  Warnings: 0

Və hər hansı dəyişikliklərin qeyd olunduğuna baxaq:

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000031
         Position: 725
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

Position 120-dən 725-ə dəyişdiyi üçün deyə bilərik ki binary log-a qeyd olunub. Binary log-a nəzər yetirək. Binary log-larla işləmək üçün mysqlbinlog utility default olaraq installation zamanı gəlir. Məndə installation path fərqli olduğu üçün məcburi full path verəcəm:

root@sh-ubuntu:~# /opt/mysql/server-5.6/bin/mysqlbinlog /var/lib/mysql/data/mysql-bin.000031
.
.
/*!*/;
# at 252
#130628 11:21:59 server id 1  end_log_pos 453 CRC32 0x5de3dc2f 	Query	thread_id=1	exec_time=0	error_code=0
use `backup_test`/*!*/;
SET TIMESTAMP=1372400519/*!*/;
create table test_table(
id int not null auto_increment,
name varchar(15),
surname varchar(20),
primary key(id)
)
/*!*/;
# at 453
#130628 11:23:06 server id 1  end_log_pos 532 CRC32 0x1e299628 	Query	thread_id=1	exec_time=0	error_code=0
SET TIMESTAMP=1372400586/*!*/;
BEGIN
/*!*/;
# at 532
#130628 11:23:06 server id 1  end_log_pos 598 CRC32 0x02542031 	Table_map: `backup_test`.`test_table` mapped to number 70
# at 598
#130628 11:23:06 server id 1  end_log_pos 694 CRC32 0xb71ce174 	Write_rows: table id 70 flags: STMT_END_F

BINLOG '
yivNURMBAAAAQgAAAFYCAAAAAEYAAAAAAAEAC2JhY2t1cF90ZXN0AAp0ZXN0X3RhYmxlAAMDDw8E
LQA8AAYxIFQC
yivNUR4BAAAAYAAAALYCAAAAAEYAAAAAAAEAAgAD//gBAAAACVNoYWhyaXlhcgZSemF5ZXb4AgAA
AAZLaGF0YWkGUnpheWV2+AMAAAAFRWx2aW4IQmlueWF0b3Z04Ry3
'/*!*/;
# at 694
#130628 11:23:06 server id 1  end_log_pos 725 CRC32 0x5509e700 	Xid = 23
COMMIT/*!*/;
DELIMITER ;
# End of logfile

Burda diqqət yetirək:

BINLOG '
yivNURMBAAAAQgAAAFYCAAAAAEYAAAAAAAEAC2JhY2t1cF90ZXN0AAp0ZXN0X3RhYmxlAAMDDw8E
LQA8AAYxIFQC
yivNUR4BAAAAYAAAALYCAAAAAEYAAAAAAAEAAgAD//gBAAAACVNoYWhyaXlhcgZSemF5ZXb4AgAA
AAZLaGF0YWkGUnpheWV2+AMAAAAFRWx2aW4IQmlueWF0b3Z04Ry3

Bunun izahı:
By default, mysqlbinlog displays row events encoded as base-64 strings using BINLOG statements

Dolayısı ilə bas64 encoded string olduğu üçün biz görə bilmirik ki, konkret olaraq nə baş verib və nə düşüb bin log-a(bir daha qeyd edirəm ki bu row based binary log format-a aiddir).
Bizim anlaya biləcəyimiz bir dildə göstərilməsi üçün aşağıdakı qaydada decode edirik:

root@sh-ubuntu:~# /opt/mysql/server-5.6/bin/mysqlbinlog -vv --base64-output=DECODE-ROWS /var/lib/mysql/data/mysql-bin.000031
.
.
/*!*/;
# at 252
#130628 11:21:59 server id 1  end_log_pos 453 CRC32 0x5de3dc2f 	Query	thread_id=1	exec_time=0	error_code=0
use `backup_test`/*!*/;
SET TIMESTAMP=1372400519/*!*/;
create table test_table(
id int not null auto_increment,
name varchar(15),
surname varchar(20),
primary key(id)
)
/*!*/;
# at 453
#130628 11:23:06 server id 1  end_log_pos 532 CRC32 0x1e299628 	Query	thread_id=1	exec_time=0	error_code=0
SET TIMESTAMP=1372400586/*!*/;
BEGIN
/*!*/;
# at 532
#130628 11:23:06 server id 1  end_log_pos 598 CRC32 0x02542031 	Table_map: `backup_test`.`test_table` mapped to number 70
# at 598
#130628 11:23:06 server id 1  end_log_pos 694 CRC32 0xb71ce174 	Write_rows: table id 70 flags: STMT_END_F
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Shahriyar' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Rzayev' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Khatai' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Rzayev' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Elvin' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Binyatov' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
# at 694
#130628 11:23:06 server id 1  end_log_pos 725 CRC32 0x5509e700 	Xid = 23
COMMIT/*!*/;
DELIMITER ;
# End of log file

İndi isə fərqə diqqət edirik:

### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Shahriyar' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Rzayev' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Khatai' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Rzayev' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2='Elvin' /* VARSTRING(45) meta=45 nullable=1 is_null=0 */
###   @3='Binyatov' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

İnsert bizə aydın şəkildə göstərildi. İndi isə yuxarıdakıların nə anlama gəldiyini izah edək:
@1, @2, @3 column sırasıni göstərir. @N olaraq dava edir, harda ki N sütün sayıdır.

/* INT meta=0 nullable=0 is_null=0 */ İNT data tipini göstərir.
/* VARSTRING(45) meta=45 nullable=1 is_null=0 */ varstring=varchar.

İndi isə binary log-un nə dərəcədə əhəmiyyətli olduğunu nümayiş etdirək. Deyək ki, cədvəlimizi səhvən drop etmişik:

mysql> drop table test_table;
Query OK, 0 rows affected (0.24 sec)

mysql> select * from test_table;
ERROR 1146 (42S02): Table 'backup_test.test_table' doesn't exist

Və əlimizdə backup yoxdur. Lakin vaxtında binary log-umuzu aktiv etdiyimiz üçün bəxtimiz gətirib. Biz drop-a qədər olan bütün dəyişiklikləri replay edə bilərik. Bunun üçün binlog position-ları öyrənməliyik. Bir daha binary log-a nəzər yetirək:

/*!*/;
# at 252
#130628 11:21:59 server id 1  end_log_pos 453 CRC32 0x5de3dc2f 	Query	thread_id=1	exec_time=0	error_code=0
use `backup_test`/*!*/;
SET TIMESTAMP=1372400519/*!*/;
create table test_table(
id int not null auto_increment,
name varchar(15),
surname varchar(20),
primary key(id)
)
/*!*/;
# at 453
#130628 11:23:06 server id 1  end_log_pos 532 CRC32 0x1e299628 	Query	thread_id=1	exec_time=0	error_code=0
SET TIMESTAMP=1372400586/*!*/;
BEGIN
/*!*/;
# at 532
#130628 11:23:06 server id 1  end_log_pos 598 CRC32 0x02542031 	Table_map: `backup_test`.`test_table` mapped to number 70
# at 598
#130628 11:23:06 server id 1  end_log_pos 694 CRC32 0xb71ce174 	Write_rows: table id 70 flags: STMT_END_F
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=1
###   @2='Shahriyar'
###   @3='Rzayev'
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=2
###   @2='Khatai'
###   @3='Rzayev'
### INSERT INTO `backup_test`.`test_table`
### SET
###   @1=3
###   @2='Elvin'
###   @3='Binyatov'
# at 694
#130628 11:23:06 server id 1  end_log_pos 725 CRC32 0x5509e700 	Xid = 23
COMMIT/*!*/;
# at 725
#130628 11:48:11 server id 1  end_log_pos 862 CRC32 0xb911519a 	Query	thread_id=2	exec_time=1	error_code=0
SET TIMESTAMP=1372402091/*!*/;
DROP TABLE `test_table` /* generated by server */
/*!*/;

# at 252 -də başlayacıq # at 725-ə qədər replay edəcik. Yəni drop-a qədər:

root@sh-ubuntu:~# /opt/mysql/server-5.6/bin/mysqlbinlog --start-position=252 --stop-position=725 /var/lib/mysql/data/mysql-bin.000031 | mysql -u root -p
Enter password:

Möcüzəli şəkildə cədvəlimiz və içindəki məlumatlar geri qayıtdı:

mysql> select * from test_table;
+----+-----------+----------+
| id | name      | surname  |
+----+-----------+----------+
|  1 | Shahriyar | Rzayev   |
|  2 | Khatai    | Rzayev   |
|  3 | Elvin     | Binyatov |
+----+-----------+----------+
3 rows in set (0.00 sec)

Bizim işlərimizi asanlaşdırmaq üçün və öz məlumat təhlükəsizliyinizi təmin etmək üçün mütləq binary log-u aktiv edin!
Təşəkkürlər 😉

Making logical backup-binary log,mysqldump (part 2)

Yazının 1ci hissəsi
Bəli 2ci yazıda mysqldump-la full logical backup alacıq, restore edəcik.
Və ən sonda da binary log ilə çox sadə point-in-time recovery edəcik.
Ilk öncə nümunə schema və cədvəlimizi yaradaq:

mysql> create schema backup_test character set=utf8;
Query OK, 1 row affected (0.12 sec)

mysql> use backup_test;
Database changed
mysql> create table test_table(
    -> id int not null auto_increment,
    -> name varchar(15),
    -> surname varchar(20),
    -> primary key(id)
    -> );
Query OK, 0 rows affected (0.20 sec

3 İnsert-imizi edək:

mysql> insert into test_table(name,surname) values('Shahriyar','Rzayev'),('Khatai','Rzayev'),('Elvin','Binyatov');
Query OK, 3 rows affected (0.18 sec)
Records: 3  Duplicates: 0  Warnings: 0

Cədvəlimizin halı:

mysql> select * from test_table;
+----+-----------+----------+
| id | name      | surname  |
+----+-----------+----------+
|  1 | Shahriyar | Rzayev   |
|  2 | Khatai    | Rzayev   |
|  3 | Elvin     | Binyatov |
+----+-----------+----------+
3 rows in set (0.00 sec)

Və deyək ki cədvəlimizin bu halında biz full backup etmək qərarına gəldik…(yalnızca bu cədvəl yox bütün cədvəlləri)
Full logical backup mysqldump vasitəsilə yerinə yetirilir…Amma ilk öncə binary log-larımızı araşdıraq:

mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000002 |       126 |
| mysql-bin.000003 |       126 |
| mysql-bin.000004 |      6969 |
| mysql-bin.000005 |       150 |
| mysql-bin.000006 |       710 |
+------------------+-----------+
5 rows in set (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000006 |      710 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

Bu outputlardan aydın olur ki,bizim 6 ədəd binary log var. Və hal-hazırda istifadə olunanı da mysql-bin.000006-dır.

indi isə full logical backup:

[root@sh ~]# mysqldump -uroot -p --all-databases --single-transaction --flush-logs --master-data=2 > /home/shahriyar/dumps/full_logical_backup.sql
Enter password: 

1. –all-databases — bütün schema-ları çıxardır.
2. –single-transaction — bir transaction başladır və hər şeyi bir transaction-lar birdəfəlik yerinə yetirir.
–flush-logs — çox faydalı bir opsiya. backup-dan sonra yeni binary log yaradır. bu o deməkdir ki full backup-dan sonrakı bütün əməliyyatlar həmin bu yeni yaranan binary log-da qeyd olunur.
–master-data=2 — yeni yaranmış binary log kordinatlarını comment şəklində .sql faylına qeyd edəcək. indiki halda full_logical_backup.sql-a.
Və həqiqətən də faylı açdıqda ən başda bunu görəcik:

Yoxladıqda görürük ki həqiqətən də yeni binary log-umuz yaranıb:

Və davam edirik…bizim test_table-a gəlin əlavə 3 ədəd də insert verək:

mysql> insert into test_table(name,surname) values('Senan','Quliyev'),('Faxri','Xalidov'),('Elvin','Dursunov');
Query OK, 3 rows affected (0.23 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from test_table;
+----+-----------+----------+
| id | name      | surname  |
+----+-----------+----------+
|  1 | Shahriyar | Rzayev   |
|  2 | Khatai    | Rzayev   |
|  3 | Elvin     | Binyatov |
|  4 | Senan     | Quliyev  |
|  5 | Faxri     | Xalidov  |
|  6 | Elvin     | Dursunov |
+----+-----------+----------+
6 rows in set (0.00 sec)

Deməli belə, biz full backup aldıqdan sonra test_table cədvəlimizə əlavə 3 insert gedib. və son nəticədə bizdə 6 row olub. Burdan belə nəticə çıxarmaq olar ki, əgər faciə nəticəsində test_table drop olsa və sonra biz yaratdığımız .sql fayldan test_table-ı restore etsək bizim əlimizdə backup-dan əvvəlki 3 row olacaq elə deyil mi?
backup-dan sonrakı 3 row-nu isə birdəfəlik itirəcik? Qəşəng sualdı. itiriləcək row sayı 1000 olsa bəs onda necə?

Bir kənaraçıxma olsun bu: full logical backup almaq çox sadə görünsə də server-i yükləyə bilir.Mənim backup həcmim 517 mb oldu. Təbii ki production database-də bu 10 gb-lərlə ola bilər. İtiriləcək vaxtı nəzərə alın.
Bundan əlavə böyük .sql faylla işləmək olduqca çətindi və hər text editor bunu başarmır. Ən azından linux-da default olan gedit ümumiyyətlə donur. Mənim faylımı 20 dəqiqədən çox bir vaxtda aça bilmədi.
Bu əsasən o zaman problem olur ki, bizə bəlkə də full restore lazım olmadı bir cədvəli o boyda faylın içindən tapıb edit-ləmək təbii ki, əziyyətdir. Nə isə ki bunun üçün də bir çıxış yolu mövcuddur: GREP
SED

Və davam edirik. test_table-ı drop edirik:

mysql> drop table test_table;
Query OK, 0 rows affected (0.23 sec)

Indi isə full_logical_backup.sql fayl-ından yalnız test_table-ı restore edək.
ilk öncə sed vasitəsilə test_table-ın create-ni tapaq:

[root@sh dumps]# sed -e '/./{H;$!d;}' -e 'x;/CREATE TABLE `test_table`/!d;q' full_logical_backup.sql
DROP TABLE IF EXISTS `test_table`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `test_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(15) DEFAULT NULL,
  `surname` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

Və copy edib run edirik:

CREATE TABLE `test_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(15) DEFAULT NULL,
  `surname` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.19 sec)

grep vasitəsilə bizə lazım olan insertləri-i tapırıq və elə yerindəcə insert edirik:

[root@sh dumps]# grep 'INSERT INTO `test_table`' full_logical_backup.sql | mysql backup_test -u root -p
Enter password:

Və select:

mysql> select * from test_table;
+----+-----------+----------+
| id | name      | surname  |
+----+-----------+----------+
|  1 | Shahriyar | Rzayev   |
|  2 | Khatai    | Rzayev   |
|  3 | Elvin     | Binyatov |
+----+-----------+----------+
3 rows in set (0.00 sec)

Bəli ilk 3 row var amma digər son 3 row-nu itirmək istəmirəm deyirsinizsə. Çarəsi binary log
binary log-un aktiv edilməsi haqqında artıq yazım var:MySQL binary log-un aktiv edilməsi

Digər 3 row-nu da aşağıdakı qaydada bərpa edə bilərik. İlk öncə bizə lazım olan binary log-un içinə baxaq.bunun mysqlbinlog-dan istifadə olunur. və əgər nəzər alsaq ki bizə backup-dan sonrakı 3 insert lazımdır onu axtarıb tapmaq elə da çətin deyil:

[root@sh data]# mysqlbinlog mysql-bin.000008
.
.
# at 210
#121227 18:55:14 server id 1  end_log_pos 383 	Query	thread_id=2	exec_time=0	error_code=0
use backup_test/*!*/;
SET TIMESTAMP=1356620114/*!*/;
insert into test_table(name,surname) values('Senan','Quliyev'),('Faxri','Xalidov'),('Elvin','Dursunov')
/*!*/;
# at 383
#121227 18:55:14 server id 1  end_log_pos 410 	Xid = 9284
COMMIT/*!*/;
.
.

Burda əsas yadda saxlamalı olduğumuz at 210 və at 383…Yəni bizim restore-umuz başlıyacaq 210-dan bitəcək 383-də!

[root@sh data]# mysqlbinlog --start-position=210 --stop-position=383 /var/lib/mysql/data/mysql-bin.000008 | mysql -u root -p
Enter password: 

İnanmağınız üçün yoxlayaq:

mysql> select * from test_table;
+----+-----------+----------+
| id | name      | surname  |
+----+-----------+----------+
|  1 | Shahriyar | Rzayev   |
|  2 | Khatai    | Rzayev   |
|  3 | Elvin     | Binyatov |
|  4 | Senan     | Quliyev  |
|  5 | Faxri     | Xalidov  |
|  6 | Elvin     | Dursunov |
+----+-----------+----------+
6 rows in set (0.01 sec)

Sizi canı-könüldən təbrik edirəm itirilmiş 3 row bərpa olunmuşdur 🙂

Təbii ki bu binary log-un istifadəsinin sadə misalı idi. Amma elə burdan da görünür ki bu necə vacib bir məsələdir.
Binary log, Physical (Raw) backup, incremental backup, XtraBackup tool haqqında daha ətraflı yazılar olacaq. inşallah…
Hələlik isə beynəlxalq məsləhət. Production database-də yalnızca logical backup-la kifayətlənirsinzə,(Bizdə çox zaman bunu php script-lər vasitəsilə yerinə yetirirlər) O zaman heç olmasa mysqldump-dan istifadə edin.
Amma qətiyyən məsləhət görülməyən bir şeydir bu! Yalnızca logical backup yuxarıdakı sadə misalda göstərildiyi kimi məlumatların itirilməsinə gətirib çıxarır!
Mütləq şəkildə binary log-dan istifadə edin…məsələn həftədə 1 dəfə logical backup alın hər gün isə binary log ilə incremental backup alın. Yəni deyək ki, bazar günü full logical backup aldınız. Bazar ertəsi binary log1, bazar ertəsi binary log2, çərşənbə axşamı binary log3 və.s şəklində increment edin.
Ya da ki, hər 3 gündən bir full logical backup alın daha sonra binary log ilə increment edin və.s
Bu və digər metodlar haqqında yazılar olacaq.

Təşəkkürlər 🙂

Making logical backup-mysqldump (part 1)

Bu yazı 2 hissədən ibarət olub full logical backup almaq haqqındadır. Bu məqsədlə mysqldump-dan istifadə edəcik.
Ümumiyyətlə gələcək üçün biz belə qəbul edəcik ki, database-imizdə yalnız və yalnız İnnoDB table-lar yerləşir.
İrəliki vaxtlarda Physical (Raw) backup,incremental backup,point-in-time recovery və.s kimi mövzular üçün bu əsas şərtlərdən biridir. Və ümumiyyətlə öz məlumat təhlükəsizliyimiz məqsədilə MyİSAM-dan bir dəfəlik əl çəkməyiniz məsləhət görülür.

Mən yoxladım və gördüm ki, özümdə çoxlu MyİSAM table-lar mövcuddur. Biz bu table-ları alter edib İnnoDB-yə çevirmək fikrindəyik.
İlk öncə hansı cədvəllər-in engine-ı MyİSAM-dı ona baxaq. Sözsüz ki bizim bir-bir cədvəllərin engine-na baxası halımız yoxdu. Əgər belə ürəkdən bunu istəyirsinzə show create table sizin_table_ad -la baxa bilərsiz.

Lakin daha professional yanaşma üçün biz istifadə edəcik information_schema-dan.
MySQL installation-la birlikdə 3 schema gəlir: performance_schema, mysql, information_schema.
Beləliklə MyİSAM table-ları tapaq:

mysql> use information_schema;
Database changed

mysql> select table_name from tables where engine='MyISAM';
+---------------------------+
| table_name                |
+---------------------------+
| COLUMNS                   |
| EVENTS                    |
| PARAMETERS                |
| PARTITIONS                |
| PLUGINS                   |
.
.
| max_sales_by_customer     |
| product_codes             |
| timestamp_check           |
| film_text                 |
+---------------------------+
51 rows in set (1.36 sec)

51 cədvəlimiz var imiş lakin output-dan da hiss elədiyimiz kimi bəzi cədvəllər yuxarıda qeyd olunan 3 schema-ya aiddi!
Onları ataq:

mysql> select table_name from tables where engine='MyISAM' and table_schema not in('mysql','information_schema','performance_schema');
+-----------------------+
| table_name            |
+-----------------------+
| aircraft              |
| aircrafttype          |
| class                 |
| flight                |
| flightclass           |
| flightdep             |
| p                     |
| pax                   |
| route                 |
| stats                 |
| test_85               |
| Product_Codes         |
| books                 |
| creditcards           |
| enum_test             |
| limit_test            |
| max_sales_by_customer |
| product_codes         |
| timestamp_check       |
| film_text             |
+-----------------------+
20 rows in set (0.01 sec)

20 cədvəlimiz var ki, onlar MyİSAM cədvəllərdir.
Təbii ki 20 ədəd alter table yazmaq da biraz çətin və əziyyətli işdir.bu say 100 olsaydı onda necə?
Bu məqsədlə procedure yazmışam, müəllif hüquqları mənə aiddi 😛
Procedure bütün MyİSAM cədvəlləri tapır və onları 1-1 alter edir. Procedure kodu:

delimiter $$

create procedure multiple_alter()
begin 
	declare v_table_schema varchar(30);
	declare v_table_name varchar(30);
	declare v_last_row_fetched int default 0;
	
	declare cursor1 cursor for
	select 
        a.table_schema, a.table_name from
        information_schema.tables as a
        where a.engine = 'MyISAM'
	and a.table_schema not in ('mysql' , 'information_schema','performance_schema');

	declare continue handler for not found set v_last_row_fetched=1;

	set v_last_row_fetched=0;
	open cursor1;
	cursor_loop: loop
	fetch cursor1 into v_table_schema,v_table_name;
			if v_last_row_fetched=1 then
					leave cursor_loop;
			end if;
			
			set @sql_v=concat('alter table ',v_table_schema,'.',v_table_name,' engine=innodb');
			prepare stmt from @sql_v;
			EXECUTE stmt;
			deallocate prepare stmt;
	end loop cursor_loop;
	close cursor1;
	set v_last_row_fetched=0;
	
end$$

Proseduru işlətdiyim anda bir dənə error çıxdı:

mysql> call multiple_alter();
ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes

Hansı table-lların alter olunmadığına baxmaq üçün yuxarıdakı query-ni bir də verək:

mysql> select      a.table_schema, a.table_name from     information_schema.tables as a     where a.engine = 'MyISAM' and a.table_schema not in ('mysql' , 'information_schema','performance_schema');
+--------------+------------+
| table_schema | table_name |
+--------------+------------+
| sakila       | film_text  |
+--------------+------------+
1 row in set (0.01 sec)

Burdan belə nəticə çıxır ki film_text cədvəlində FULLTEXT index istifadə olunub. Lakin MySQL 5.5 İnnoDB-də FULLTEXT dəstəyi olmadığı üçün yuxarıdakı ERROR çıxır(MySQL 5.6-da bu dəstək var).
Ona görə də geriyə qalan 1 cədvəlimizi özümüz alter edəcik:

mysql> alter table sakila.film_text drop index idx_title_description;
Query OK, 1000 rows affected (0.23 sec)
Records: 1000  Duplicates: 0  Warnings: 0

mysql> alter table sakila.film_text engine=innodb;
Query OK, 1000 rows affected (0.27 sec)
Records: 1000  Duplicates: 0  Warnings: 0

Və yenidən MyİSAM cədvəl axtarırıq:

mysql> select      a.table_schema, a.table_name from     information_schema.tables as a     where a.engine = 'MyISAM' and a.table_schema not in ('mysql' , 'information_schema','performance_schema');
Empty set (0.00 sec)

Daha yoxdur.
Bütün cədvəllərimiz İnnoDB-dir.
Və bu Yazının 2ci hissəsi mysqldump-la full logical backup-ın alınması, restore olunması və point-time-recovery haqqında olacaq.
Təşəkkürlər 🙂