Anda akan menemukan bahwa ini terjadi hanya ketika @status
adalah NULL
atau string.
Masalahnya ada dua:
-
Tidak seperti variabel lokal , MySQL variabel pengguna mendukung kumpulan tipe data yang sangat terbatas:
Dokumentasi gagal menyebutkan bahwa tipe data aktual yang digunakan masing-masing adalah
BIGINT
,DECIMAL(65,30)
,DOUBLE
,LONGBLOB
,LONGTEXT
danLONGBLOB
. Mengenai yang terakhir, manual setidaknya menjelaskan:Penyimpanan dari tiga tipe data pertama (yaitu untuk nilai integer, desimal dan floating-point) masing-masing membutuhkan 8, 30 dan 8 byte. Tipe data lainnya (yaitu untuk string dan
NULL
nilai) memerlukan (hingga) 4 gigabyte penyimpanan. -
Karena Anda menggunakan versi PHP sebelum v5.4.0, driver MySQL default adalah libmysql , dengan hanya metadata tipe kolom yang tersedia dari server pada pengikatan data—jadi MySQLi mencoba mengalokasikan memori yang cukup untuk menampung setiap nilai yang mungkin (bahkan jika buffer penuh pada akhirnya tidak diperlukan); jadi
NULL
- dan variabel pengguna bernilai string, yang memiliki kemungkinan ukuran maksimum 4GiB, menyebabkan PHP melebihi batas memori default (dari 128MiB sejak PHP v5.2.0).
Pilihan Anda meliputi:
-
Mengganti tipe data kolom dalam definisi tabel:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table ( status VARCHAR(2) ) SELECT @status AS status;
-
casting secara eksplisit variabel pengguna ke tipe data yang lebih spesifik:
DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT CAST(@status AS CHAR(2)) AS status;
-
Menggunakan variabel lokal, yang dideklarasikan dengan tipe data eksplisit:
DECLARE status VARCHAR(2) DEFAULT @status; DROP TEMPORARY TABLE IF EXISTS tmp_table; CREATE TEMPORARY TABLE tmp_table SELECT status;
-
Mengatasi masalah dengan memanggil
mysqli_stmt::store_result()
sebelummysqli_stmt::bind_result()
, yang menyebabkan hasil untuk disimpan di libmysql (di luar batas memori PHP) dan kemudian PHP hanya akan mengalokasikan memori aktual yang diperlukan untuk menyimpan catatan saat mengambilnya:$stmt->execute(); $stmt->store_result(); $stmt->bind_result( $status ); $stmt->fetch();
-
Meningkatkan batas memori PHP sehingga dapat mengakomodasi alokasi buffer 4GiB (walaupun kita harus menyadari implikasi pada sumber daya perangkat keras dari melakukannya)—misalnya, untuk menghapus batasan memori sepenuhnya (walaupun waspadai potensi efek samping negatif dari melakukan hal ini, misalnya dari kebocoran memori asli):
ini_set('memory_limit', '-1');
-
Mengkompilasi ulang PHP, dikonfigurasi untuk menggunakan driver mysqlnd asli (disertakan dengan PHP sejak v5.3.0, tetapi tidak dikonfigurasi sebagai default hingga PHP v5.4.0) alih-alih libmysql:
./configure --with-mysqli=mysqlnd
-
Upgrade ke PHP v5.4.0 atau yang lebih baru sehingga mysqlnd digunakan secara default.