Apakah sampah sementara dikumpulkan?

61

Pertanyaan ini membuat saya berpikir umpan RSS sementara di wp_options tidak dihapus secara otomatis?

Transien seharusnya kedaluwarsa dan dihapus. Namun satu-satunya cara saya melihat ini ditangani adalah ketika transient kedaluwarsa dan diminta, maka itu dihapus selama permintaan.

Bagaimana jika transien kedaluwarsa tetapi tidak pernah diminta setelah itu? Dari uraian di Codex saya berpikir bahwa semacam pengumpulan sampah tersirat. Sekarang saya tidak begitu yakin dan tidak dapat menemukan kode yang melakukan itu.

Jadi apakah itu hanya akan terjebak dalam database selamanya?

Jarang
sumber
secara teoritis mereka harus dihapus ketika cron dijalankan (jika mereka kedaluwarsa)
onetrickpony
1
@ Amoeba Ambulans ya, saya agak menyebutkan hal itu. Maksud saya adalah - sementara diciptakan tidak menganggap atau menjamin bahwa itu akan pernah diminta. Menekankan pertanyaan awal - kapan dan jika transien yang kedaluwarsa dihapus jika saya tidak pernah mendapatkannya ?
Rarst
1
itu mengasumsikan Anda membersihkan data yang kadaluwarsa, tetapi ya, Anda benar, ada situasi di mana itu tidak akan pernah dihapus. Seperti menghapus widget yang menggunakan transien. Anda harus mengirimkan tiket di trac untuk ini :)
onetrickpony
1
@ Pertama - Kedengarannya seperti hal yang sempurna untuk menulis tambalan dan tunduk pada trac?
MikeSchinkel
1
Tiket trac terkait: core.trac.wordpress.org/ticket/20316
Stephen Harris

Jawaban:

45

Mereka sekarang

Dimulai dengan WordPress 3.7 transien kedaluwarsa dihapus pada peningkatan basis data, lihat # 20316


Jawaban lama

Jika seseorang tidak dapat menunjukkan kepada saya sebaliknya, transien tampaknya bukan sampah yang dikumpulkan. Yang membuatnya lebih buruk adalah bahwa tidak seperti opsi mereka tidak dijamin untuk disimpan dalam database. Jadi tidak ada cara yang dapat diandalkan untuk mengambil daftar semua transien untuk memeriksa mereka untuk kedaluwarsa.

Beberapa kode darurat untuk melakukan pengumpulan sampah jika database digunakan untuk penyimpanan:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}
Jarang
sumber
$ time = $ _SERVER ['REQUEST_TIME']; dan kemudian menggunakan $ time dalam query SQL - jangan lakukan itu. Berurusan lebih hati-hati dengan $ _SERVER variabel / nilai untuk mencegah injeksi SQL.
hakre
@ hakre hm ... Saya memilih itu dari presentasi tentang kinerja PHP yang merekomendasikannya menggunakan time()yang dapat menyebabkan bug (eksekusi tidak instan secara alami). Waktu permintaan diatur oleh PHP itu sendiri, tidak berasal dari jenis data apa pun yang disediakan pengguna. Mengapa kerentanan ini?
Paling lambat
@ Pertama: Saya tidak mengatakan bahwa Anda tidak boleh menggunakannya, Anda hanya harus memastikan bahwa itu dikodekan dengan aman untuk digunakan di dalam query SQL. Anda harus melakukan ini dengan setiap variabel dari sumber eksternal. Variabel $ _SERVER mungkin tidak disetel seperti yang diharapkan, dan sebagai gantinya, bahkan ditetapkan oleh pengguna yang meminta. Saya hanya ingin menyebarkan beberapa praktik pengkodean yang baik. Seperti biasa, untuk mengetahui kondisi ketersediaan sebenarnya, lihat dokumen. Misalnya untuk PHP 4, variabel seperti itu tidak ada dan mungkin ditimpa oleh header khusus atau variabel lingkungan - php.net/manual/en/reserved.variables.server.php
hakre
@hakre tetap (saya pikir), terima kasih untuk pengingat PHP4 btw (Saya tidak sabar menunggu WordPress untuk menjatuhkan dukungannya)
Rarst
Itu terlihat jauh lebih baik di mataku;). Mari kita berharap bahwa tidak ada masalah dengan waktu () dan bilangan bulat negatif yang mungkin menghapus semua atau tidak ada transien selain karena kecelakaan. Jangan pernah mempercayai sistem yang sedang berjalan: P
hakre
20

Memindahkan beberapa komentar dari diskusi menjadi jawaban, dengan kata-kata ulang dan format ulang ..

Pada dasarnya, apa yang terjadi adalah bahwa kecuali Anda memiliki kasus yang sangat ekstrem, mereka tidak benar-benar perlu "pengumpulan sampah". Jika Anda tidak pernah mengambilnya, maka tidak masalah apakah mereka ada di sana atau tidak.

Lihat, transien disimpan dalam tabel opsi secara default. Dalam instalasi dasar, tabel opsi mungkin memiliki 100 entri di dalamnya. Setiap transien menambahkan dua entri lagi, tetapi bahkan jika Anda memiliki ribuan, mereka tidak mempengaruhi kecepatan situs, karena mereka tidak dimuat secara otomatis.

Saat startup, WordPress memuat opsi ke dalam memori, tetapi hanya memuat opsi yang bendera autoload-nya dihidupkan. Transien tidak mendapatkan ini, jadi jangan dimuat ke dalam memori. Hanya transien yang benar-benar digunakan kemudian akan dikenakan biaya.

Dari perspektif basis data, tabel opsi memiliki indeks pada Id opsi dan nama opsi. Transien selalu dimuat berdasarkan nama (kunci), sehingga pencarian untuk mereka selalu dipilih secara sederhana pada satu nilai kunci unik. Jadi pencariannya adalah O (log (n)) dan sangat cepat. Dengan Big-O log (n), Anda harus masuk ke jutaan dan jutaan baris sebelum menjadi penting. Terus terang, overhead dalam pengaturan dan teardown dari query, bersama dengan transfer data aktual, jauh lebih lama. Permintaan itu sendiri berjalan pada dasarnya nol-waktu dengan perbandingan. Jadi hanya memiliki baris tambahan yang tidak digunakan tidak mempengaruhi apa pun selain menggunakan ruang disk tambahan.

Mengindeks dalam basis data adalah salah satu dari ide-ide yang banyak dibaca yang tidak masuk akal bagi orang-orang yang belum benar-benar memahami apa yang terjadi di balik layar. Database dirancang untuk pengambilan data cepat, dari bawah ke atas, dan dapat menangani hal semacam ini tanpa masalah. Ini adalah bacaan yang sangat bagus: http://en.wikipedia.org/wiki/Index_(database )

Sekarang, pembersihan dengan cara yang paling jelas (memanggil SQL DELETE pada mereka) tidak benar-benar menghapusnya dari database. Itu hanya menghapus mereka dari indeks dan menandai baris sebagai "dihapus". Sekali lagi, ini adalah cara kerja database. Untuk benar-benar membersihkan ruang disk, Anda harus melanjutkan dan melakukan TABEL OPTIMASI setelahnya, dan ini bukan operasi cepat. Ini membutuhkan waktu. Mungkin lebih banyak waktu daripada nilainya. Ini mungkin tidak cukup untuk memberi Anda penghematan waktu CPU, secara total.

Jika Anda memiliki beberapa kasus yang menyebabkan penyisipan transien baru yang terus-menerus tidak digunakan, maka Anda perlu mencari masalah yang mendasarinya. Apa yang memasukkan transien ini? Apakah mereka menggunakan kunci yang berubah atau bermutasi? Jika demikian, maka plugin atau kode yang menyebabkan ini harus diperbaiki, pada dasarnya, jangan lakukan itu. Itu akan lebih membantu, karena kemungkinan kode yang tidak membuatnya dengan benar juga tidak mengambil mereka, dan dengan demikian melakukan lebih banyak pekerjaan daripada yang harus dilakukan.

Di sisi lain, mungkin ada kasus di mana transien sedang dibuat untuk sesuatu seperti setiap pos. Ini mungkin memang bisa diterima. Saya melakukan ini sendiri di SFC, untuk menyimpan komentar yang masuk dari Facebook. Setiap posting memiliki potensi sementara yang terkait dengannya, yang berarti dua baris tambahan per posting. Jika Anda memiliki 10k posting, Anda akan memiliki 20k baris pada tabel opsi (akhirnya). Ini tidak buruk atau lambat, karena sekali lagi, ada sangat sedikit perbedaan antara 100 baris dan 20.000 baris sejauh database sangat peduli. Semuanya diindeks. Ini secepat sih. Sub-sub-milidetik.

Ketika Anda mulai masuk ke jutaan baris, maka saya akan khawatir. Ketika ukuran tabel opsi meningkat di atas ratusan megabyte, maka saya akan cukup peduli untuk melihat lebih dekat. Tetapi secara umum, ini bukan masalah kecuali untuk kasus-kasus ekstrim. Ini tentu bukan masalah untuk hal yang lebih kecil dari sesuatu seperti situs berita besar, dengan ratusan ribu posting. Dan untuk setiap situs yang cukup besar untuk itu menjadi masalah, Anda harus menggunakan objek cache eksternal dari beberapa macam, dan dalam bahwa kasus, transien mendapatkan otomatis disimpan di sana bukan di database.

Otto
sumber
1
NB: transien tanpa kedaluwarsa jangan mendapatkan autloaded, dan tidak ada kadaluarsa adalah standar , jadi di mana aplikasi / plugin adalah menciptakan banyak transien dan tidak menetapkan kedaluwarsa mereka akan menggunakan potongan memori pada setiap buka halaman / posting.
webaware
Tidak ada alasan untuk menggunakan "sementara tanpa kedaluwarsa", karena itu pada dasarnya identik dengan "opsi" normal.
Otto
1
Tentu, tapi ini default . Karena itu, banyak penulis plugin menambahkan transien yang tidak kedaluwarsa.
webaware
1
Nah, solusinya di sini sederhana: Jangan gunakan plugin itu. Mereka salah melakukannya. Transien tidak boleh digunakan sebagai sesi, Anda tidak boleh menggunakannya tanpa kedaluwarsa yang berarti, dan mereka tidak boleh memiliki mutasi atau perubahan kunci.
Otto
2
Katakan, 7 hari. Jika pembuat plugin / tema menginginkan sesuatu yang lebih besar atau lebih kecil, mereka akan menentukannya. Jika mereka ingin memuat otomatis, mereka tidak harus menentukan 0 untuk kedaluwarsa (= tak terbatas), tetapi itulah yang mereka dapatkan saat ini dengan parameter kedaluwarsa melakukan tugas ganda sebagai parameter pengisian otomatis ya / tidak. Either way, kedaluwarsa default juga tidak boleh menyebabkan autoload = ya sebagai default; itu hanya meminta masalah.
webaware
18

Otto - Saya sangat tidak setuju dengan Anda. Masalahnya adalah bahwa pada akhirnya dengan semua transien itu, ukuran meja menjadi konyol. Tidak perlu jutaan baris untuk rawa. Saat ini saya sedang berurusan dengan tabel opsi yang memiliki lebih dari 130 ribu baris, dan hang secara teratur. Karena bidang nilai adalah tipe teks besar, bahkan mencari hanya baris "autoload" menjadi mimpi buruk kinerja. Bidang nilai tersebut disimpan secara terpisah dari sisa data baris. Meskipun secara logis bagian dari tabel yang sama, bergabung harus terjadi untuk menarik baris yang Anda inginkan. Bergabung dengan yang sekarang mengambil selamanya karena data yang Anda butuhkan tersebar di semua tempat pada disk. Pembuatan profil (menggunakan jet profiler untuk mysql) telah membuktikan ini.

Menambahkan auto-load ke kunci yang dikelompokkan mungkin membantu menyelesaikan masalah ini. Pengelompokan pada Autoload Desc, ID ASC misalnya, akan memungkinkan semua baris autoload untuk bergabung bersama terlebih dahulu pada disk. Bahkan masih saya pikir Anda sedang melihat ketegangan besar dari perspektif DB.

Secara pribadi saya pikir desain sistem ini aneh. Tabel opsi tampaknya telah berubah menjadi tangkapan umum untuk semua hal. Tidak masalah jika bidang nilai cukup kecil untuk dimasukkan pada halaman yang sama dengan data baris lainnya, dan dapat diindeks secara efektif. Sayangnya bukan itu masalahnya. Siapa pun yang merancang ini harus kembali ke kelas DB101.

myke
sumber
5
benar, tetapi pertimbangkan bahwa ketika pengembangan WordPress dimulai, tidak ada yang berpikir bahwa itu akan mencapai memiliki ribuan plugin menggunakan tabel opsi sebagai penyimpanan data mereka :)
onetrickpony
@onetrickpony itu sebabnya penting untuk selalu meluangkan waktu Anda dan melakukan hal-hal dengan benar, apakah Anda mengharapkannya menjadi besar suatu hari nanti atau tidak :)
Mahmoud Al-Qudsi