InnoDB tablosunun değişip değişmediğini kontrol etmenin en hızlı yolu


22

Başvurum çok veritabanı yoğun. Şu anda, MySQL 5.5.19 kullanıyorum ve MyISAM kullanıyorum, ancak InnoDB'ye geçme sürecindeyim. Kalan tek sorun sağlama toplamı performansı.

Başvurum CHECKSUM TABLEyoğun zamanlarda saniyede yaklaşık 500-1000 ifade yapıyor , çünkü müşteriler GUI değişiklikler için veritabanını sürekli olarak oyluyor (bu bir izleme sistemidir, bu nedenle çok hızlı yanıt vermeli ve çok hızlı olmalıdır).

MyISAM ile, tablo modifikasyonunda önceden hesaplanmış ve ÇOK hızlı olan canlı sağlama toplamları vardır. Ancak, InnoDB'de böyle bir şey yoktur. Yani, CHECKSUM TABLEçok yavaş.

Tablonun son güncelleme zamanını kontrol edebilmeyi umuyorum, Ne yazık ki, bu InnoDB'de de mevcut değil. Artık sıkıştım, çünkü testler uygulamanın performansının ciddi şekilde düştüğünü göstermiştir.

Tabloları güncellemek için çok fazla kod satırı vardır, bu nedenle uygulamada tablo değişikliklerini günlüğe kaydetmek için mantık uygulamak söz konusu değildir.

InnoDB tablolarındaki değişiklikleri tespit etmek için hızlı bir yöntem var mı?

Yanıtlar:


15

Mydb.mytable tablosu için bu sorguyu çalıştırın:

SELECT update_time
FROM information_schema.tables
WHERE table_schema='mydb'
AND table_name='mytable';

Son 5 dakikada hangi tabloların değiştiğini bilmek istiyorsanız, şunu çalıştırın:

SELECT table_schema,table_name,update_time
FROM information_schema.tables
WHERE update_time > (NOW() - INTERVAL 5 MINUTE);

Bir şans ver !!!

GÜNCELLEME 2011-12-21 20:04 EDT

İşverenim (DB / Wweb hosting comany) 112.000 InnoDB tabloya sahip bir müşterim var. Yoğun saatlerde INFORMATION_SCHEMA.TABLES okumak çok zordur. Alternatif bir önerim var:

İnnodb_file_per_table etkinse ve tüm InnoDB tabloları .ibddosyalarda depolanırsa , son güncellemenin zamanını tespit etmenin bir yolu vardır (dakikaya kadar).

Mydb.mytable tablosu için işletim sisteminde aşağıdakileri yapın:

$ cd /var/lib/mysql/mydb
$ ls -l mytable.ibd | awk '{print $4,$5}'

Bu zaman damgası işletim sisteminden geliyor. Bu konuda yanlış gidemezsin.

GÜNCELLEME 2011-12-21 22:04 EDT [mysqld] innodb_max_dirty_pages_pct = 0;

Bunu my.cnf dosyasına ekleyin, mysql'yi yeniden başlatın ve tüm InnoDB tabloları tampon havuzundan hızlı bir şekilde basar.

Yeniden başlatmayı önlemek için, sadece çalıştırın

mysql> SET GLOBAL innodb_max_dirty_pages_pct=0;

GÜNCELLEME 2013-06-27 07:15 EDT

Bir dosyanın tarihini ve saatini almaya gelince, ls --time-styleseçeneğine sahiptir:

$ cd /var/lib/mysql/mydb
$ ls -l --time-style="+%s" mytable.ibd | awk '{print $6}'

Dosyanın zaman damgasını UNIX_TIMESTAMP (NOW ()) ile karşılaştırabilirsiniz .


İdb moddate ile yanlış gidemeyeceğinize emin misiniz? Bir değişiklik sadece tampon havuzunda bellekte yaşıyor olabilir ve henüz diske atılmamış olabilir.
atxdba

6
Cevabınız için teşekkürler, ama dediğim gibi, information_schema.tables'daki update_time InnoDB tabloları için NULL. Ayrıca innodb_max_dirty_pages_pct = 0'ın iyi bir fikir olduğundan emin değilim, çünkü performansı feda edecek ... İzlenen tabloların her biri için bir referans tablosuna rastgele bir değer eklemek için tetikleyicilerle bir çözüm hakkında düşünüyordum ama sonra sadece bunun için masa başına 3 tetikleyiciye ihtiyacım olacak ...
Ceket

Ayrıca information_schema.tables arasından seçim yapmak da oldukça yavaştır ... bir tabloyu kontrol etmek yaklaşık 300ms sürer. MyISAM masasında "CHECKSUM TABLE" yaparak, Canlı Sağlama Toplamı etkin olan milyonlarca satırın karşılaştırılması milisaniyeden daha az sürüyor.
Ceket

2
Dosya sistemi kontrolü için +1, arabellek temizleme işlemi yeterince düzenli olduğu sürece (kabaca saniyede bir kez varsayılandır), o zaman bu zaman damgası oldukça doğru ve muhtemelen çoğu durumda yeterince iyi olur ...
Dave Rix

1
Belki 's yerel veritabanı için Tamam, ama ben, birden çok uzak köle var ... çalışmıyor bu yüzden
Ceket

3

Sanırım çözümü buldum. Bir süredir MySQL sunucularımı değiştirmek için Percona Sunucusuna bakıyordum ve şimdi bunun iyi bir nedeni olduğunu düşünüyorum.

Percona sunucusu, standart MySQL sunucusunda bulunmayan INNODB_TABLE_STATS gibi birçok yeni INFORMATION_SCHEMA tablosu sunar. Ne zaman yaparsın:

SELECT rows, modified FROM information_schema.innodb_table_stats WHERE table_schema='db' AND table_name='table'

Gerçek satır sayısı ve bir sayaç olsun. Resmi belgeler bu alan hakkında şunları söylüyor:

Eğer değiştirilen sütunun değeri “satır / 16” veya 2000000000 değerini geçerse, istatistik yeniden hesaplama işlemi innodb_stats_auto_update == 1. olduğunda, istatistiklerin eskiliğini bu değerle tahmin edebiliriz.

Böylece bu sayaç her seferinde bir sarar, ancak satır sayısını ve sayıcıyı sağlama toplamı yapabilir ve ardından tablonun her değiştirilmesinde benzersiz bir sağlama toplamı elde edersiniz. Örneğin:

SELECT MD5(CONCAT(rows,'_',modified)) AS checksum FROM information_schema.innodb_table_stats WHERE table_schema='db' AND table_name='table';

Zaten sunucularımı Percona sunucusuna yükseltecektim, bu yüzden bu sınırlama benim için bir sorun değil. Yüzlerce tetikleyiciyi yönetmek ve tablolara alan eklemek, bu uygulama için büyük bir acıdır, çünkü geliştirme aşamasında çok geç kalmıştır.

Bu, hangi motor ve sunucu kullanılırsa kullanılsın, tabloların kontrol edilememesini sağlamak için elde ettiğim PHP işlevidir:

function checksum_table($input_tables){
    if(!$input_tables) return false; // Sanity check
    $tables = (is_array($input_tables)) ? $input_tables : array($input_tables); // Make $tables always an array
    $where = "";
    $checksum = "";
    $found_tables = array();
    $tables_indexed = array();
    foreach($tables as $table_name){
        $tables_indexed[$table_name] = true; // Indexed array for faster searching
        if(strstr($table_name,".")){ // If we are passing db.table_name
            $table_name_split = explode(".",$table_name);
            $where .= "(table_schema='".$table_name_split[0]."' AND table_name='".$table_name_split[1]."') OR ";
        }else{
            $where .= "(table_schema=DATABASE() AND table_name='".$table_name."') OR ";
        }
    }
    if($where != ""){ // Sanity check
        $where = substr($where,0,-4); // Remove the last "OR"
        $get_chksum = mysql_query("SELECT table_schema, table_name, rows, modified FROM information_schema.innodb_table_stats WHERE ".$where);
        while($row = mysql_fetch_assoc($get_chksum)){
            if($tables_indexed[$row[table_name]]){ // Not entirely foolproof, but saves some queries like "SELECT DATABASE()" to find out the current database
                $found_tables[$row[table_name]] = true;
            }elseif($tables_indexed[$row[table_schema].".".$row[table_name]]){
                $found_tables[$row[table_schema].".".$row[table_name]] = true;
            }
            $checksum .= "_".$row[rows]."_".$row[modified]."_";
        }
    }

    foreach($tables as $table_name){
        if(!$found_tables[$table_name]){ // Table is not found in information_schema.innodb_table_stats (Probably not InnoDB table or not using Percona Server)
            $get_chksum = mysql_query("CHECKSUM TABLE ".$table_name); // Checksuming the old-fashioned way
            $chksum = mysql_fetch_assoc($get_chksum);
            $checksum .= "_".$chksum[Checksum]."_";
        }
    }

    $checksum = sprintf("%s",crc32($checksum)); // Using crc32 because it's faster than md5(). Must be returned as string to prevent PHPs signed integer problems.

    return $checksum;
}

Bu şekilde kullanabilirsiniz:

// checksum a signle table in the current db
$checksum = checksum_table("test_table");

// checksum a signle table in db other than the current
$checksum = checksum_table("other_db.test_table");

// checksum multiple tables at once. It's faster when using Percona server, because all tables are checksummed via one select.
$checksum = checksum_table(array("test_table, "other_db.test_table")); 

Umarım bu aynı problemi yaşayan diğer insanlara biraz bela kazandırır.


İlgilenenler için daha fazla hikaye geliştirme: forum.percona.com/…
Ceket

1

Bu sürümde Mysql v5.6 + sürümüne güncellemeniz gerekir. http://dev.mysql.com/doc/refman/5.6/en/checksum-table.html

bunun dışında, ideal çözüm, müşterinizin sürekli olarak sonuçlanmasını istememesiydi, bunun yerine, kullanılabilir olduğunda ve mevcut olduğunda yeni ve değiştirilmiş verileri zorladığınız yer olur. Daha hızlı olurdu ve sunucuya daha az yük yüklenecekti. Web tabanlı GUI kullanıyorsanız, APE http://ape-project.org/ veya diğer benzer projelere bakmalısınız .


Ne yazık ki, bu bir performans katilidir. Checksum, tüm satırları tek tek birleştirerek yapılır . Belgelerden: "Bu satır-satır hesaplama, EXTENDED deyimiyle, InnoDB ve MyISAM dışındaki diğer tüm depolama motorlarıyla ve CHECKSUM = 1 deyimi ile oluşturulmamış MyISAM tablolarıyla elde
ettiğiniz şeydir

1

Çoğunlukla bir tabloya ekliyorsanız, AUTO_INCREMENT ürününü güncelliğin bir ölçüsü olarak bağlayabilirsiniz.

SELECT `AUTO_INCREMENT` FROM `information_schema`.`tables` 
WHERE `table_schema` = DATABASE() AND `table_name` = 'YOUR_TABLE';

Ancak, Memcached'deki bir sayaç gibi bir otside kaynağa başvurmayı tercih ederim, veritabanında bir şeyi her değiştirişinizde artar.


0

Aşağıdakileri yapmayı deneyebilirsiniz:

SELECT rows_changed
FROM information_schema.table_statistics
WHERE table_schema = 'mydb' AND table_name='mytable';

Bu, her tablo güncellemesinde artış gösteren bir sayı döndürür ve değişimin tespit edilmesine izin verir.

Önemli not: değer, bir GÜNCELLEŞTİRME işleminden hemen sonra, KOMİTE'den sonra değiştirilir. Dolayısıyla, değişiklikler bitmemiş başka bir işlemin içinde yapıldıysa değişiklikleri göremeyebilirsiniz.


0

Bu cevap mysql veritabanı sürümleri veya türleri ile ilgisi yoktur, güncelleme ifadelerinin değişiklik yapıp yapmadığını bilmek istiyorum ve bunu php kodumda yapmak istiyorum ..

  1. Mysql'nin current_timestamp değerini bulmak için sorgulayacağım bir kayıt ve bir alan içeren bir kukla masa yarattı.

  2. Güncellenen veri tablosuna zaman damgası alanı eklendi ve "ON UPDATE CURRENT_TIMESTAMP" adlı mysql seçeneğini kullandı.

  3. Karşılaştırılmış # 1 ve # 2

Bu, zamanın% 100'ünde işe yaramayacak, ancak başvurum için basit ve harika bir çözümdü. Umarım bu birine yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.