MySQL içine PHP ikili veri eklerken neden bin2hex kullanabilir?

4 Cevap php

Ben MySQL içine ikili veri (dosyalar ve gibi) eklerken, sen bin2hex() işlevini kullanın ve bir HEX kodlu değer olarak göndermek, sadece kullanmak yerine, mysql_real_escape_string gerektiğini bir söylenti duydum ikili dize ve kullanabilirsiniz.

// That you should do
$hex = bin2hex($raw_bin);
$sql = "INSERT INTO `table`(`file`) VALUES (X'{$hex}')";

// Rather than
$bin = mysql_real_escape_string($raw_bin);
$sql = "INSERT INTO `table`(`file`) VALUES ('{$bin}')";

Bu performans nedenleriyle sözde. MySQL bu HEX-kodlu değerlerini nasıl işleyeceğini vs büyük dizeleri nasıl işleyeceğini ile ilgili bir şey

However, I am having a hard time confirming this. All my tests indicate the exact oposite; that the bin2hex method is ~85% slower and uses ~24% more memory.
(I am testing this on PHP 5.3, MySQL 5.1, Win7 x64 - Using a farily simple insert loop.)

Örneğin, bu grafik test kodu çalışırken mysqld işleminin özel bellek kullanımını gösterir:

mysqld process"> tarafından kullanılan Private Byte</p>

<p>Herkes bu açıklık herhangi explainations veya reasources var mı?</p>

<p>Teşekkürler.</p></div>
										</div>
									</div>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>

	</div>
	<div class=

4 Cevap

Bu benim için bir şehir efsanesi gibi geliyor.

bin2hex(), her byte two çıkış bayt için giriş harita ('a' -> '61') bir önemli fark gerekir, bu yüzden Sorguyu gerçekleştiren script artış bellek - daha eklenecek ikili veri bayt uzunluğu olarak en az kadar bellek kullanmak gerekir.

Ayrıca, bu uzun bir dize bin2hex() koşma daha much uzun sürer ima mysql_real_escape string(), hangi - in MySQL's documentation açıklandığı gibi - sadece NULL, \r, \n, \, , ve "Control-Z ': 6 karakter kaçar.

Sunucu doğru verileri depolamak için ters işlem yapmak gerekiyor: o şimdi MySQL için, PHP parçası oldu. Fonksiyonların iki Ters neredeyse sürece orijinal işlem olarak alır - ters fonksiyonu mysql_real_escape_string() (\\) çıkmamış olanlarla (\ kaçan değerleri değiştirmek için ihtiyaç ), tersinde ise bin2hex(), yeni bir bayt ile each and every byte tuple değiştirmek gerekir.

Ikili veri mysql_real_escape_string() çağrı (MySQL ait ve PHP's documentation ya da bile sadece operasyon yukarıda listelenen olanlardan daha başka bir dönüşüm yapmaz düşünüyor göre) güvenli olduğu, bunu yapmak istiyorum kesinlikle böyle bir pahalı işlemi gerçekleştirmek için hiçbir anlamı.

Ben kendimi bu test ettik, ve ben oldukça tutarlı sonuçlar ile geldim. (Even though my tests are a tad crude.)

Ben üç bilgisayarları test ettik

  1. Windows 7 (x64), PHP 5.3, MySQL 5.1
  2. Ubuntu 9.10 (x64) PHP 5.2, MySQL 5.1
  3. Ubuntu 10.04 (x32) PHP 5.3, MySQL 5.1

Şimdiye kadar üç platformlarda testler aynı tıları belirttiler:

  • Bir BLOB takmadan InnoDb ziyade MyISAM daha hızlı 8x 2x. Fark HEX-kodlu dizeleri daha ikili dizeleri daha yüksek gibi görünüyor. (See the data below)
  • ) Ham veri üzerinde bir X'...') uses more memory, on average, than using an escaped binary string (mysql_real_escape_string içine bir HEX kodlanmış dizesi (bin2hex . - Bu MyISAM ve InnoDB hem de doğru görünüyor.
  • Ikili dize hızlı MyISAM üzerinde, ancak HEX kodlu veri hızlı InnoDb üzerinde.

Test temelde (a 2.4 MiB image retrieved once at the top of the script), sorgu dizesi inşa, ve mysql_query veya mysqli::query yoluyla idam ham verileri kaçan veya onaltılık kodlu sadece basit bir döngü oldu fonksiyonları. - Ben iki uzantıları ile test. Herhangi bir fark görünmüyordu.

I put the results from the Ubuntu 10.04 (#3) up in spreadsheets. The results from the Ubuntu 9.10 (#2) machine were pretty much the same, so I didn't bother set them up:
(Finally an excuse to test the Google Docs thing properly! xD)

Bu grafikler Win7 (# 1) makinede mysqld işlem tarafından özel bellek kullanımını gösterir.

Onaltılık dize gelen ikili dize önemli ölçüde daha uzun olduğunu. Transfer süresi ve PHP içeride kopyalama etrafında ve MySQL'in bellek sadece hile yapabilirsiniz.

Tüm dürüstlük içinde yatan uygulanması konusunda uzman değilim, ama tüm SQL içindeki veri geçmek değil iyi olmaz, ama örneğin kullanarak PDOStatement 's parametresi bağlayıcı? Belki burada daha bilgili birisi PDO sadece başlık altında kaçışa ve sorgu dize manipülasyon yapar mı bu gerçekten veriler hiç bir SQL deyimi dışında, ikili bir dize olarak gönderilmesine neden olur olmadığını teyit, ya da olabilir.

Her iki şekilde de, sen orada yarar bir güvenlik (ve sadelik) olsun.

Örneğin, benzer sorunla karşılaşırsanız eğer burada açıklandığı gibi: http://www.php.net/manual/en/function.mysql-real-escape-string.php#82015

örneğin mysql_real_escape_string "ikili-güvenli" olarak görünse bile olsa igbinary_serialize ile birlikte (örnek olarak) bunu kullanamaz - unserializing sadece başarısız olur.

bu durumda size mysql içine önce takma verileri bin2hex gerekir.

Ayrıca, genellikle :) ekleme daha mysql den daha sık veri okumak