เก็บขยะชั่วคราวหรือไม่


61

คำถามนี้ทำให้ฉันคิดว่าฟีด RSS ชั่วคราวใน wp_options ไม่ถูกลบโดยอัตโนมัติ

Transients ควรจะหมดอายุและถูกลบ อย่างไรก็ตามวิธีเดียวที่ฉันเห็นการจัดการนี้คือเมื่อหมดอายุชั่วคราวและขอแล้วมันจะถูกลบในระหว่างการร้องขอ

จะเกิดอะไรขึ้นถ้าหมดอายุชั่วคราว แต่ไม่ได้ขอหลังจากนั้น จากคำอธิบายใน Codex ฉันคิดว่าการรวบรวมขยะบางประเภทนั้นบอกเป็นนัย ตอนนี้ฉันไม่แน่ใจและไม่สามารถหารหัสที่มีประสิทธิภาพ

ดังนั้นมันจะติดอยู่ในฐานข้อมูลตลอดไปหรือไม่


ในทางทฤษฎีพวกเขาควรจะถูกลบออกเมื่อ cron ถูกเรียกใช้ (หากหมดอายุ)
onetrickpony

1
@ Amoeba ทะเยอทะยานใช่ฉันพูดถึงในคำถาม ประเด็นของฉันคือ - การสร้างชั่วคราวไม่ได้สมมติหรือรับประกันว่ามันจะถูกร้องขอ เน้นหนักคำถามเดิม - เมื่อหมดอายุแล้วและหากได้รับการลบชั่วคราวถ้าฉันไม่เคยได้รับมันได้หรือไม่
Rarst

1
มันจะถือว่าคุณล้างข้อมูลที่หมดอายุ แต่ใช่คุณพูดถูกมีสถานการณ์ที่มันจะไม่ถูกลบ ชอบลบเครื่องมือที่ใช้ชั่วคราว คุณควรส่งตั๋วใน Trac สำหรับนี้ :)
onetrickpony

1
@Rarst - ดูเหมือนว่าเป็นสิ่งที่สมบูรณ์แบบในการเขียนโปรแกรมแก้ไขและส่งไปยัง trac?
MikeSchinkel

1
ตั๋ว trac ที่เกี่ยวข้อง: core.trac.wordpress.org/ticket/20316
Stephen Harris

คำตอบ:


45

ตอนนี้พวกเขาเป็น

เริ่มต้นด้วย WordPress 3.7 ที่หมดอายุชั่วคราวจะถูกลบในการอัปเกรดฐานข้อมูลดู# 20316


คำตอบเก่า

หากใครบางคนไม่สามารถแสดงให้ฉันเห็นเป็นอย่างอื่นดูเหมือนว่าคนชั่วจะไม่เก็บขยะ สิ่งที่ทำให้แย่ลงคือไม่เหมือนกับตัวเลือกที่ไม่รับประกันว่าจะถูกเก็บไว้ในฐานข้อมูล ดังนั้นจึงไม่มีวิธีที่เชื่อถือได้ในการดึงรายชื่อของผู้ที่อยู่ชั่วคราวทั้งหมดเพื่อตรวจสอบพวกเขาสำหรับการหมดอายุ

รหัสชั่วคราวเพื่อทำการรวบรวมขยะหากใช้ฐานข้อมูลสำหรับจัดเก็บ:

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);
    }
}

$ time = $ _SERVER ['REQUEST_TIME']; แล้วใช้ $ time ในแบบสอบถาม SQL - อย่าทำอย่างนั้น จัดการอย่างระมัดระวังยิ่งขึ้นด้วยตัวแปร / ค่า $ _SERVER เพื่อป้องกันการแทรก SQL
hakre

@ hakre hm ... ฉันเลือกสิ่งนั้นจากการนำเสนอเกี่ยวกับประสิทธิภาพของ PHP ที่แนะนำให้ใช้มากกว่าtime()ซึ่งอาจทำให้เกิดข้อบกพร่อง (การดำเนินการไม่ได้เกิดขึ้นทันทีตามธรรมชาติ) PHP ตั้งเวลาร้องขอไว้โดยไม่ได้มาจากข้อมูลที่ผู้ใช้จัดหา เหตุใดจึงเป็นช่องโหว่นี้
Rarst

@Rarst: ฉันไม่ได้บอกว่าคุณไม่ควรใช้มันคุณควรตรวจสอบให้แน่ใจว่ามันถูกเข้ารหัสอย่างปลอดภัยเพื่อใช้ภายในแบบสอบถาม SQL คุณควรทำสิ่งนี้กับทุกตัวแปรจากแหล่งภายนอก ตัวแปร $ _SERVER อาจไม่ได้รับการตั้งค่าตามที่คาดไว้และตั้งค่าโดยผู้ใช้ที่ขอแทน ฉันแค่ต้องการเผยแพร่วิธีการเข้ารหัสที่ดี เช่นเคยเพื่อเรียนรู้เกี่ยวกับสถานะของความพร้อมใช้งานจริงให้ดูเอกสาร สำหรับ PHP 4 ตัวอย่างเช่นไม่มีตัวแปรดังกล่าวและอาจถูกเขียนทับโดยส่วนหัวที่กำหนดเองหรือตัวแปรสภาพแวดล้อม - php.net/manual/en/reserved.variables.server.php
hakre

แก้ไข @hakre (ฉันคิดว่า) ขอบคุณสำหรับการเตือน PHP4 btw (ฉันไม่สามารถรอให้ WordPress ปล่อยการสนับสนุน)
Rarst

มันดูดีขึ้นมากในสายตาของฉัน;) หวังว่าจะไม่มีปัญหากับเวลา () และจำนวนเต็มลบที่อาจลบทั้งหมดหรือไม่ชั่วคราวกว่าโดยไม่ได้ตั้งใจ อย่าไว้ใจระบบที่ใช้งานอยู่: P
hakre

20

การย้ายความคิดเห็นบางส่วนจากการอภิปรายไปยังคำตอบพร้อมการใช้ถ้อยคำซ้ำและการจัดรูปแบบอีกครั้ง ..

โดยพื้นฐานแล้วสิ่งที่เกิดขึ้นคือถ้าคุณไม่มีกรณีสุดขั้วพวกเขาไม่จำเป็นต้องเป็น "ขยะที่เก็บรวบรวม" หากคุณไม่เคยได้รับพวกเขาก็ไม่สำคัญว่าพวกเขาจะอยู่ที่นั่นหรือไม่

ดูที่การชั่วคราวจะถูกเก็บไว้ในตารางตัวเลือกโดยค่าเริ่มต้น ในการติดตั้งพื้นฐานตารางตัวเลือกอาจมี 100 รายการในนั้น แต่ละรายการชั่วคราวเพิ่มอีกสองรายการ แต่แม้ว่าคุณจะมีหลายพันรายการพวกเขาจะไม่ส่งผลกระทบต่อความเร็วของไซต์เนื่องจากไม่มีการโหลดอัตโนมัติ

เมื่อเริ่มต้น WordPress โหลดตัวเลือกลงในหน่วยความจำ แต่จะโหลดเฉพาะตัวเลือกที่เปิดใช้งานการตั้งค่าสถานะอัตโนมัติ Transients ไม่ได้รับสิ่งนี้ดังนั้นอย่าโหลดลงในหน่วยความจำ เฉพาะผู้ที่ได้ใช้จริงในภายหลังเท่านั้นที่จะต้องเสียค่าใช้จ่าย

จากมุมมองของฐานข้อมูลตารางตัวเลือกจะมีดัชนีทั้งตัวเลือกรหัสและชื่อตัวเลือก Transients จะถูกโหลดตามชื่อ (คีย์) เสมอและการค้นหาสำหรับพวกเขานั้นจะง่ายต่อการเลือกโดยใช้ค่าคีย์ที่ไม่ซ้ำกัน ดังนั้นการค้นหาคือ O (log (n)) และเร็วมาก ด้วย Big-O log (n) คุณจะต้องเข้าแถวเป็นล้าน ๆ แถวก่อนที่จะสังเกตเห็นได้ ตรงไปตรงมาค่าใช้จ่ายในการตั้งค่าและการลดลงของแบบสอบถามรวมถึงการถ่ายโอนข้อมูลจริงนั้นมีความยาวกว่า แบบสอบถามเองทำงานเป็นศูนย์เวลาโดยเปรียบเทียบ ดังนั้นการมีแถวที่ไม่ได้ใช้เพิ่มนั้นไม่มีผลอะไรเลยนอกจากการใช้พื้นที่ดิสก์เพิ่มเติม

การจัดทำดัชนีในฐานข้อมูลเป็นหนึ่งในแนวคิดแบบอ่านลึกที่ไม่สมเหตุสมผลกับผู้ที่ไม่เข้าใจจริง ๆ ว่าเกิดอะไรขึ้นเบื้องหลัง ฐานข้อมูลได้รับการออกแบบมาเพื่อการดึงข้อมูลที่รวดเร็วจากพื้นฐานและสามารถจัดการกับสิ่งต่าง ๆ ได้โดยไม่มีปัญหา นี่เป็นอ่านที่ค่อนข้างดี: http://en.wikipedia.org/wiki/Index_(database )

ตอนนี้การล้างข้อมูลในวิธีที่ชัดเจนที่สุด (การเรียกใช้ SQL DELETE บนพวกเขา) ไม่ได้ลบออกจากฐานข้อมูล มันเพิ่งลบออกจากดัชนีและทำเครื่องหมายแถวว่า "ลบ" นี่เป็นเพียงการทำงานของฐานข้อมูล หากต้องการล้างพื้นที่ดิสก์จริงคุณต้องดำเนินการต่อและทำตาราง OPTIMIZE ในภายหลังและนี่ไม่ใช่การดำเนินการที่รวดเร็ว มันต้องใช้เวลา อาจมากกว่าเวลาที่คุ้มค่า อาจไม่เพียงพอที่จะให้คุณประหยัดเวลาโดยรวมของ CPU

หากคุณมีบางกรณีที่ทำให้เกิดการแทรกอย่างต่อเนื่องของทรานแซกชั่นใหม่ที่ไม่ได้ใช้งานคุณจำเป็นต้องค้นหาปัญหาพื้นฐานแทน การแทรกสภาวะชั่วคราวเหล่านี้คืออะไร พวกเขากำลังใช้รหัสการเปลี่ยนแปลงหรือการกลายพันธุ์หรือไม่? ถ้าเป็นเช่นนั้นปลั๊กอินหรือโค้ดที่ทำให้เกิดสิ่งนี้ควรได้รับการแก้ไขโดยทั่วไปไม่ทำเช่นนั้น สิ่งนี้จะเป็นประโยชน์มากขึ้นเนื่องจากเป็นไปได้ว่ารหัสที่ไม่ได้สร้างอย่างถูกต้องนั้นยังไม่สามารถเรียกคืนได้และทำให้ทำงานได้มากกว่าที่ต้องทำ

ในทางกลับกันอาจมีกรณีที่มีการสร้างทรานแซคชันสำหรับบางอย่างเช่นทุกโพสต์ นี่อาจเป็นที่ยอมรับอย่างสมบูรณ์ ฉันทำสิ่งนี้ด้วยตัวเองใน SFC เพื่อเก็บความคิดเห็นที่เข้ามาจาก Facebook แต่ละโพสต์มีศักยภาพที่เกี่ยวข้องชั่วคราวซึ่งหมายถึงสองแถวพิเศษต่อโพสต์ หากคุณมีโพสต์ 10k คุณจะมี 20k แถวในตารางตัวเลือก (ในที่สุด) สิ่งนี้ไม่เลวหรือช้าเพราะมีความแตกต่างกันเล็กน้อยระหว่าง 100 แถวกับ 20,000 แถวเท่าที่ฐานข้อมูลสนใจจริงๆ มันคือดัชนีทั้งหมด รวดเร็วเหมือนห่า อนุกรรมการย่อยมิลลิวินาที

เมื่อคุณเริ่มเข้าไปในล้านแถวแล้วฉันจะเป็นห่วง เมื่อขนาดของตารางตัวเลือกเพิ่มขึ้นเหนือหลายร้อยเมกะไบต์แล้วฉันจะต้องกังวลพอที่จะดูอย่างใกล้ชิด แต่โดยทั่วไปแล้วการพูดนี้ไม่ได้เป็นปัญหายกเว้นในกรณีที่รุนแรง แน่นอนว่ามันไม่ใช่ปัญหาสำหรับอะไรที่เล็กกว่าอะไรอย่างเว็บไซต์ข่าวใหญ่ที่มีการโพสต์นับแสน และสำหรับเว็บไซต์ใด ๆ ที่มีขนาดใหญ่พอสำหรับมันจะมีปัญหาคุณควรจะใช้แคชวัตถุภายนอกของการจัดเรียงบางและในที่กรณีชั่วคราวได้รับการจัดเก็บไว้โดยอัตโนมัติมีแทนในฐานข้อมูล


1
หมายเหตุ: ผู้ที่ไม่มีการหมดอายุจะได้รับการโหลดโดยอัตโนมัติและไม่มีการหมดอายุเป็นค่าเริ่มต้นดังนั้นเมื่อแอปพลิเคชัน / ปลั๊กอินกำลังสร้างการถ่ายโอนจำนวนมากและไม่ได้ตั้งค่าการหมดอายุพวกเขาจะใช้หน่วยความจำในทุกหน้า / โหลด
webaware

ไม่มีเหตุผลที่จะใช้ "ชั่วคราวโดยไม่มีการหมดอายุ" เพราะโดยทั่วไปจะเหมือนกับตัวเลือก "ปกติ"
อ็อตโต

1
แน่นอน แต่มันเป็นค่าเริ่มต้น ดังนั้นผู้เขียนปลั๊กอินจำนวนมากกำลังเพิ่มทรานแซคชันที่ไม่หมดอายุ
webaware

1
วิธีแก้ปัญหาที่นี่ก็ง่าย: อย่าใช้ปลั๊กอินเหล่านั้น พวกเขาทำผิด ไม่ควรใช้ Transients เป็นเซสชันคุณไม่ควรใช้โดยไม่มีการหมดอายุที่มีความหมายและไม่ควรมีการกลายพันธุ์หรือเปลี่ยนคีย์
อ็อตโต

2
พูด 7 วัน หากผู้เขียนปลั๊กอิน / ธีมต้องการบางสิ่งที่ใหญ่กว่าหรือเล็กกว่านั้นพวกเขาจะระบุ หากพวกเขาต้องการ autoload พวกเขาไม่ควรระบุ 0 สำหรับการหมดอายุ (= อนันต์) แต่นั่นคือสิ่งที่พวกเขาได้รับในขณะนี้ด้วยพารามิเตอร์การหมดอายุที่ทำหน้าที่สองเท่าเป็นพารามิเตอร์ yes / no autoload ไม่ว่าจะด้วยวิธีใดการหมดอายุที่เป็นค่าเริ่มต้นไม่ควรนำไปสู่ ​​autoload = ใช่เป็นค่าเริ่มต้น นั่นเป็นเพียงการถามหาปัญหา
webaware

18

อ็อตโต - ฉันไม่เห็นด้วยกับคุณมากกว่านี้ ปัญหาก็คือในที่สุดเมื่อมีการเปลี่ยนแปลงชั่วคราวขนาดของโต๊ะกลายเป็นเรื่องไร้สาระ มันไม่ใช้เวลานับล้านแถวในการชะงักงัน ฉันกำลังจัดการกับตารางตัวเลือกที่มีมากกว่า 130k แถวและค้างเป็นประจำ เนื่องจากฟิลด์ค่าเป็นประเภทข้อความขนาดใหญ่แม้แต่การค้นหาเฉพาะแถว "autoload" ก็กลายเป็นฝันร้ายของประสิทธิภาพ เขตข้อมูลค่าเหล่านั้นจะถูกจัดเก็บแยกต่างหากจากข้อมูลแถวที่เหลือ แม้ว่ามันจะเป็นส่วนหนึ่งของตารางอย่างมีเหตุผล แต่การรวมจะต้องเกิดขึ้นเพื่อดึงแถวที่คุณต้องการ เข้าร่วมที่ตอนนี้ใช้ตลอดไปเพราะข้อมูลที่คุณต้องการจะกระจายไปทั่วสถานที่บนดิสก์ การสร้างโปรไฟล์ (โดยใช้ jet profiler สำหรับ mysql) ได้พิสูจน์เรื่องนี้แล้ว

การเพิ่มการโหลดอัตโนมัติไปยังคีย์คลัสเตอร์อาจช่วยแก้ปัญหานี้ได้ ยกตัวอย่างเช่นการทำคลัสเตอร์บน Descoload Desc, ID ASC จะทำให้แถว autoload ทั้งหมดรวมเข้าด้วยกันเป็นอันดับแรกบนดิสก์ แม้ว่าฉันจะยังคิดว่าคุณกำลังมองดูความเครียดจากมุมมองของ DB

โดยส่วนตัวแล้วฉันคิดว่าการออกแบบของระบบนี้ไม่เพียงพอ ตารางตัวเลือกดูเหมือนจะกลายเป็น catch-all ทั่วไปสำหรับหลายสิ่งหลายอย่าง ไม่เป็นไรถ้าเขตข้อมูลค่าเล็กพอที่จะรวมไว้ในหน้าเดียวกับส่วนที่เหลือของแถวข้อมูลและสามารถทำดัชนีได้อย่างมีประสิทธิภาพ น่าเสียดายที่ไม่ใช่อย่างนั้น ใครก็ตามที่ออกแบบสิ่งนี้จะต้องกลับไปที่คลาส DB101


5
จริง แต่พิจารณาว่าเมื่อการพัฒนา WordPress เริ่มต้นไม่มีใครคิดว่ามันจะมีปลั๊กอินนับพันที่ใช้ตารางตัวเลือกเป็นที่เก็บข้อมูล :)
onetrickpony

@onetrickpony นั่นเป็นเหตุผลว่าทำไมจึงสำคัญที่จะต้องสละเวลาและทำสิ่งที่ถูกต้องเสมอไม่ว่าคุณจะคาดหวังว่ามันจะมีขนาดใหญ่สักวันหรือไม่ :)
Mahmoud Al-Qudsi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.