Berurusan dengan bug yang tidak dapat direproduksi

73

Misalkan tim Anda menulis sistem perangkat lunak yang (sangat mengejutkan!) Berfungsi dengan baik.

Suatu hari salah satu insinyur keliru menjalankan beberapa query SQL yang mengubah beberapa data DB, kemudian melupakannya.

Setelah beberapa waktu Anda menemukan data yang rusak / salah dan semua orang menggaruk kepala bagian mana dari kode yang menyebabkan ini dan mengapa, tidak berhasil. Sementara itu manajer proyek bersikeras bahwa kami menemukan bagian dari kode yang menyebabkannya.

Bagaimana Anda menangani ini?

Nik Kyriakides
sumber
32
Jika insinyur lupa tentang itu, bagaimana Anda tahu itu yang terjadi? Bagaimana Anda rusak oleh seseorang yang menjalankan skrip, dan bukan oleh bug?
DaveG
18
Dia memiliki pencerahan setelah satu atau dua hari. Ini adalah hipotesis kalau-kalau dia tidak pernah ingat yang bisa dengan mudah terjadi.
Nik Kyriakides
12
Ini adalah hipotesis. Saya yakin PM akan meminta kita mengejar ini sebanyak yang kita bisa jika dia tidak pernah ingat. Saya tahu saya akan melakukannya.
Nik Kyriakides
59
xkcd.com/583 ;) [Bahasa NSFW]
Baldrickk
100
"Misalkan timmu menulis sistem perangkat lunak yang berjalan dengan baik." Berhenti menggodaku dengan fantasi mustahil!
Paul D. Waite

Jawaban:

134

Jelas tidak ada manajer proyek yang akan menginvestasikan waktu yang tidak terbatas ke dalam masalah seperti itu. Mereka ingin mencegah situasi yang sama terulang kembali.

Untuk mencapai tujuan ini, bahkan jika seseorang tidak dapat menemukan akar penyebab kegagalan seperti itu, seringkali mungkin untuk mengambil beberapa tindakan

  • Deteksi kegagalan seperti itu sebelumnya jika terjadi lagi
  • Jadikan kecil kemungkinan kegagalan yang sama akan terjadi lagi
  • Jadikan sistem lebih kuat dari jenis inkonsistensi tertentu

Misalnya, pencatatan yang lebih terperinci, penanganan kesalahan yang lebih rumit, atau pensinyalan kesalahan segera dapat membantu mencegah kesalahan yang sama menyerang lagi, atau untuk menemukan akar permasalahan. Jika sistem Anda mengizinkan penambahan pemicu basis data, mungkin dimungkinkan untuk menambahkan pemicu yang melarang inkonsistensi yang diperkenalkan.

Pikirkan apa jenis tindakan yang sesuai dalam situasi Anda, dan sarankan ini kepada tim; Saya yakin manajer proyek Anda akan senang.

Suatu hari salah satu insinyur keliru menjalankan beberapa query SQL yang mengubah beberapa data DB, kemudian melupakannya.

Seperti yang disebutkan oleh orang lain, itu juga merupakan ide yang baik untuk melarang prosedur semacam itu (jika Anda memiliki pengaruh pada bagaimana sistem dioperasikan). Tidak seorang pun boleh diizinkan menjalankan kueri ad-hoc tidak berdokumen yang mengubah konten basis data. Jika ada kebutuhan untuk permintaan seperti itu, pastikan ada kebijakan untuk menyimpan permintaan bersama dengan tanggal pelaksanaannya, nama orang yang mengeksekusinya, dan alasan mengapa itu digunakan, di tempat yang terdokumentasi.

Doc Brown
sumber
8
@NicholasKyriakides Mungkin keduanya. Semua ini adalah tindakan yang masuk akal untuk membuat debugging "ditangguhkan" lebih sederhana. Mereka mungkin telah ditulis dalam prosedur yang tak terhitung jumlahnya.
Nic Hartley
29
Itu memang terjadi dari waktu ke waktu bahwa Anda memiliki semacam masalah serius dalam sistem produksi dan gagal untuk menentukan penyebabnya meskipun upaya yang signifikan. Pada akhirnya, Anda mengaitkannya dengan sinar kosmik dan mencoba meningkatkan pelaporan (jadi jika itu terjadi lagi, Anda akan memiliki kesempatan lebih baik untuk menemukan penyebabnya) dan mitigasi (jadi jika itu terjadi lagi, kerusakan akan minimal) dan lihat apakah itu mengulangi.
David Schwartz
2
@Nicholas Kyriakides: pengalaman pribadi selama beberapa dekade.
Doc Brown
4
Perlu juga dicatat bahwa sangat mungkin bahwa, bahkan jika ada bug, itu mungkin tidak ada lagi. Yang terbaik yang kadang-kadang dapat Anda lakukan adalah memperbaiki data, dan meningkatkan pengujian / prosedur untuk memastikan masalah yang sama tidak terjadi lagi.
kutschkem
2
Menemukan masalah yang terputus-putus adalah tentang penebangan dan menemukan titik tersedak yang dapat mendeteksi mereka ketika terjadi, kemudian berjalan mundur dari sana untuk menentukan sumbernya. Kadang-kadang diperlukan hal-hal yang tidak menyenangkan seperti pemicu, atau menyebarkan kode dengan logging kesalahan berisik, hanya untuk mengetahui kapan / di mana kesalahan itu terjadi.
AaronLS
51

Ini bukan bug

Setidaknya tidak pada kode Anda. Ini adalah bug dalam proses Anda . Manajer proyek Anda harus lebih khawatir tentang proses Anda daripada kode Anda.

Bagaimana Anda menangani ini?

Sederhananya, dengan tidak membiarkan para insinyur mengubah produksi atau pengembangan bersama database .


Dengan asumsi ini adalah database pengembangan bersama:

Idealnya, jika memungkinkan, hindari memiliki database bersama di tempat pertama . Sebaliknya, miliki basis data per-pengembang yang berumur pendek. Ini harus diotomatisasi dengan skrip, jika tidak biaya untuk pengujian menjadi terlalu besar, dan ada insentif untuk tidak menguji sesuatu. Anda dapat memiliki database ini di workstation pengembang, atau di server pusat.

Jika, karena suatu alasan, Anda benar-benar HARUS memiliki database bersama, Anda harus menggunakan fixture - pada dasarnya, sesuatu yang mengatur database ke kondisi yang dikenal baik setiap kali Anda perlu menggunakannya. Ini menghindari pengembang digigit oleh perubahan orang lain.

Jika Anda perlu menerapkan perubahan permanen ke database, Anda harus mengkomitnya ke kontrol sumber Anda . Setup database Anda sedemikian sehingga devs tidak memiliki izin untuk menulisnya secara langsung, dan memiliki program yang menarik perubahan dari kontrol sumber dan menerapkannya.

Akhirnya, dari deskripsi Anda tentang cara Anda men-debug sesuatu, sepertinya Anda tidak menggunakan CI . Gunakan CI . Agak sulit untuk setup, tetapi akan menghemat banyak waktu dalam jangka panjang, belum lagi menghentikan Anda dari khawatir tentang bug basis data yang tidak dapat diproduksi kembali. Anda hanya perlu khawatir tentang Heisenbugs sekarang!


Dengan asumsi ini adalah basis data produksi:

Jika pengembang Anda mengubah basis data produksi, banyak hal yang salah, bahkan jika perubahannya benar.

Pengembang tidak boleh mengakses basis data produksi . Sama sekali tidak ada alasan untuk itu, dan begitu banyak hal yang bisa menjadi sangat salah.

Jika Anda perlu memperbaiki sesuatu dalam database produksi, pertama-tama Anda membuat cadangan, mengembalikan cadangan itu pada contoh (pengembangan) yang berbeda , dan kemudian bermain-main dengan database pengembangan itu. Setelah Anda berpikir Anda memiliki perbaikan siap (pada kontrol sumber!), Anda melakukan kembali pemulihan, menerapkan perbaikan, dan melihat hasilnya. Kemudian, setelah mencadangkan semuanya lagi (dan idealnya mencegah pembaruan bersamaan), Anda memperbaiki instance produksi, idealnya melalui tambalan perangkat lunak.

Jika Anda perlu menguji sesuatu di basis data produksi ... tidak, Anda tidak perlu. Apa pun tes yang perlu Anda lakukan, Anda harus lakukan dalam contoh pengembangan. Jika Anda memerlukan beberapa data untuk melakukan tes, Anda mendapatkan data itu di sana.

goncalopp
sumber
12
Jadi, solusi yang Anda sarankan adalah perjalanan waktu?
Benubird
7
Meskipun ini adalah solusi yang layak untuk contoh yang diberikan, pertanyaannya memiliki konteks yang jauh lebih umum dalam menangani bug yang tidak dapat direproduksi dan manajer yang ingin mereka membujuknya. Itu bisa berlaku untuk lebih dari sekadar masalah basis data dan manajemen izin. Saya merasa jawaban ini sebenarnya tidak menjawab pertanyaan yang dimaksud, hanya contoh yang diberikan.
Kyle Wardle
@KyleWardle Setuju. Saya pikir jawaban Doc Brown mencakup kasus umum dengan cukup baik (detail logging dan penanganan kesalahan, kondisi penjaga). Saya kebanyakan menambahkan milik saya karena saya melihat tidak ada yang menyebutkan kegagalan proses yang menyebabkan masalah di tempat pertama
goncalopp
2
@ Benubird Saya pikir jawabannya bermuara pada "cara Anda menangani ini mencegah hal itu terjadi lagi". Saya tidak berpikir Anda dapat "memecahkan" database produksi yang rusak dari perspektif rekayasa perangkat lunak.
goncalopp
1
Anda tidak akan mengubah kode untuk memasukkan data ke dalam database dev. Di mana pun saya bekerja, termasuk perusahaan besar, pengembang bebas untuk memasukkan data uji, dan menggunakan kredensial yang sama seperti yang digunakan aplikasi.
David Conrad
13

Database produksi harus memiliki akses penuh logging dan kontrol akses berbasis peran. Dengan demikian, Anda harus memiliki bukti kuat tentang WHO melakukan APA SAJA ke database sehingga memindahkan perhatian dari kode ke keamanan operasional yang buruk.

Don Gilman
sumber
2
Sepertinya mereka mungkin tidak tahu persis kapan korupsi data terjadi, yang bisa menyulitkan untuk mencari tahu log apa yang perlu mereka selidiki.
Nathanael
3
Sayangnya pada penelusuran salah satu dari ini kami menemukan itu juga menghancurkan log. (Ya, Itu. Bug itu nyata.)
Joshua
Berpasangan dengan pekerjaan terjadwal memeriksa integritas data, bahkan jika hanya dalam semalam, berarti masalah dapat ditandai lebih awal dan diselesaikan. Jika Anda ingin benar-benar berhati-hati, perlu peer review untuk perubahan.
Keith
Di mana-mana saya telah bekerja para devs terhubung ke database dengan kredensial yang sama dengan yang digunakan aplikasi, jadi akses logging hanya akan menunjukkan kapan id telah melakukan perubahan, bukan bahwa itu dilakukan oleh manusia daripada program. Saya kira Anda dapat membandingkan timestamp dengan log aplikasi untuk melihat apakah aplikasi itu melakukan apa pun yang akan menulis ke db pada waktu itu.
David Conrad
@DavidConrad: Mengapa dev memiliki akses ke kredensial yang digunakan aplikasi dalam produksi? Anda harus menggunakan semacam manajemen rahasia sehingga kredensial itu bahkan tidak dapat dibaca kecuali oleh akun layanan aplikasi Anda, dari server aplikasi produksi.
Daniel Pryden
6

Dalam hal ini, Anda akhirnya mengetahui penyebabnya, tetapi mengambil hipotesis Anda bahwa Anda tidak ...

Pertama, analisis apa yang berubah. Jika sistem berjalan dengan baik sebelumnya, melihat dengan seksama semua yang telah dilakukan baru-baru ini dapat mengungkapkan perubahan yang menyebabkan bug. Tinjau secara sistematis kontrol versi Anda, CI / sistem penyebaran, dan kontrol konfigurasi untuk melihat apakah ada yang berubah. Jalankan git bisect atau mekanisme yang setara untuk melakukan pencarian biner. Periksa log. Cari-cari log yang tidak Anda ketahui. Bicaralah dengan semua orang dengan akses ke sistem untuk melihat apakah mereka telah melakukan sesuatu baru-baru ini. Untuk masalah Anda, jika Anda cukup teliti dalam proses ini, semoga ini akan mengungkapkan pertanyaan SQL yang terlupakan.

Kedua, instrumentasi. Jika Anda tidak dapat menemukan penyebab bug secara langsung, tambahkan instrumen di sekitarnya untuk mengumpulkan data tentang masalah tersebut. Tanyakan pada diri Anda "jika saya bisa mereproduksi bug ini pada perintah, apa yang ingin saya lihat di debugger," dan kemudian login. Ulangi sesuai kebutuhan sampai Anda memiliki pemahaman yang lebih baik tentang masalah tersebut. Seperti yang disarankan Doc Brown, tambahkan logging untuk status yang relevan dengan bug. Tambahkan pernyataan yang mendeteksi data yang rusak. Misalnya, jika bug Anda adalah aplikasi crash, tambahkan mekanisme crash logging. Jika Anda sudah memilikinya, hebat, tambahkan anotasi ke log kerusakan untuk mencatat keadaan yang berpotensi relevan dengan crash. Pertimbangkan apakah masalah konkurensi mungkin terlibat dan uji coba untuk menggunakan utas keselamatan .

Ketiga, ketahanan. Bug tidak dapat dihindari, jadi tanyakan pada diri Anda bagaimana Anda dapat meningkatkan sistem Anda menjadi lebih tangguh sehingga pemulihan dari bug lebih mudah. Bisakah cadangan Anda ditingkatkan (atau ada)? Pemantauan, kegagalan, dan peringatan yang lebih baik? Lebih banyak redundansi? Penanganan kesalahan yang lebih baik? Layanan saling bergantung satu sama lain? Bisakah Anda meningkatkan proses Anda di sekitar akses database dan permintaan manual? Paling-paling, hal-hal ini akan membuat konsekuensi bug Anda tidak terlalu parah, dan paling buruk, mereka mungkin melakukan hal-hal baik.

Zach Lipton
sumber
5
  1. Jelaskan kepada manajer proyek Anda bahwa menurut Anda penyebab yang paling mungkin adalah akses basis data manual.
  2. Jika mereka masih ingin Anda mencari kode yang menyebabkan ini, buka dan lihat lagi kode tersebut.
  3. Kembalilah dalam beberapa jam (atau waktu lain yang sesuai) dan katakan Anda tidak dapat menemukan kode apa pun yang menyebabkan hal ini, karena itu Anda masih yakin penyebab yang paling mungkin adalah akses basis data manual.
  4. Jika mereka masih ingin Anda mencari kodenya, tanyakan berapa banyak waktu yang mereka ingin Anda habiskan untuk ini. Secara halus mengingatkan mereka bahwa Anda tidak akan mengerjakan fitur X, bug Y atau peningkatan Z saat Anda melakukan ini.
  5. Habiskan waktu sebanyak yang mereka minta. Jika Anda masih berpikir kemungkinan penyebabnya adalah akses basis data manual, beri tahu mereka ini.
  6. Jika mereka masih ingin Anda mencari kodenya, tingkatkan masalahnya karena hal ini jelas menjadi penggunaan waktu tim Anda yang tidak produktif.

Anda mungkin juga ingin mempertimbangkan apakah Anda harus menambahkan proses tambahan untuk mengurangi kemungkinan akses basis data manual yang menyebabkan masalah seperti ini di masa mendatang.

Philip Kendall
sumber
1
Saya tidak tahu salah satu insinyur melakukan pembaruan manual + insinyur hampir tidak pernah menjalankan query langsung pada database. Yang ini baru saja melakukannya, sebagai hal yang sekali saja dan melupakannya. Kami menghabiskan + hari mempersiapkan untuk menghabiskan seminggu penuh untuk mencari tahu apa yang salah. Pertanyaan saya adalah apa yang terjadi jika Anda tidak dapat menemukan penyebabnya dan tidak dapat menyarankan kemungkinan penyebabnya.
Nik Kyriakides
5
"Pertanyaan saya adalah apa yang terjadi jika Anda tidak dapat menemukan penyebabnya dan tidak dapat menyarankan kemungkinan penyebabnya" Ini adalah alasan yang tepat mengapa bendera 'tidak akan diperbaiki - tidak dapat diduplikasi' diciptakan.
esoterik
4

Saya sedang bekerja pada tim pengembangan untuk produk basis data mainframe ketika seorang pelanggan melaporkan bahwa mereka memiliki basis data yang korup. Korupsi dalam arti bahwa keadaan internal bit pada disk berarti database tidak dapat dibaca melalui perangkat lunak database. Di dunia mainframe, pelanggan membayar Anda $ juta dan Anda harus menganggap ini serius. Inilah yang kami lakukan:

Langkah 0: bantu pelanggan untuk bangkit dan berjalan kembali dengan memperbaiki basis data.

Langkah 1: dengan memeriksa file pada disk di tingkat heks kami menentukan bahwa korupsi itu sistematis: ada banyak contoh korupsi yang sama. Jadi itu pasti disebabkan pada tingkat perangkat lunak basis data. Memang, itu cukup sistematis sehingga kami merasa kami bisa mengesampingkan masalah multi-threading.

Setelah menghilangkan banyak teori lain, kami menggunakan utilitas yang dapat digunakan untuk reorganisasi fisik database. Tampaknya itu satu-satunya kode yang memiliki akses ke data di tingkat yang tepat. Kami kemudian menemukan cara menjalankan utilitas ini, dengan opsi yang dipilih dengan cermat, yang mereproduksi masalah. Pelanggan tidak dapat mengkonfirmasi atau menyangkal bahwa ini adalah apa yang telah mereka lakukan, tetapi karena itu adalah satu-satunya penjelasan yang dapat kami buat, kami memutuskan bahwa itu kemungkinan penyebabnya, dan mereka tidak punya banyak pilihan selain menerima diagnosis kami. .

Langkah 2: Kami kemudian membuat dua perubahan pada perangkat lunak: (a) membuatnya lebih sulit untuk menyebabkan efek ini secara tidak sengaja melalui antarmuka pengguna "ya saya tahu apa yang saya lakukan", dan (b) memperkenalkan file log baru sehingga jika pernah terjadi lagi, kita akan memiliki catatan tindakan pengguna.

Jadi pada dasarnya (a) perbaiki kerusakan dan kembalikan berjalan hidup, (b) temukan akar masalahnya, (c) lakukan apa saja yang diperlukan untuk mencegahnya terjadi lagi, atau untuk memudahkan diagnosa jika itu terjadi lagi.

Michael Kay
sumber
3

Dari pengalaman saya apa yang bos Anda inginkan adalah jaminan tingkat bahwa ini tidak akan terulang kembali. Jika tidak ada kode yang menjadi penyebabnya, karena itu dijamin oleh pengujian kesatuan, jadi anggap Anda sudah memiliki cakupan pengujian pada basis kode Anda, solusinya harus menambahkan "pengujian" ke database Anda. Saya akan mengutip Don Gilman, karena dia memaku di sana:

Database produksi harus memiliki akses penuh logging dan kontrol akses berbasis peran. Dengan demikian, Anda harus memiliki bukti kuat tentang WHO melakukan APA SAJA ke database sehingga memindahkan perhatian dari kode ke keamanan operasional yang buruk.

Tetapi juga, Anda harus memiliki Prosedur Operasi Standar untuk mengubah data dalam produksi. Misalnya, tidak ada DBA yang harus mengubah data, tidak ada pengembang yang harus melaksanakan perubahan itu sendiri dan mereka, sebagaimana didefinisikan dalam SOP, harus saling meminta secara resmi perubahan melalui surat atau tiket.

Pasti ada kutipan seperti ini di suatu tempat, jika tidak Anda bisa mengutipnya:

Ada alasan yang sangat bagus untuk koki yang tidak bertanggung jawab untuk membersihkan toilet.

CesarScur
sumber
1

Ada beberapa hal yang harus dilakukan dengan bug yang tidak dapat direproduksi.

  1. Buat tiket untuk itu

Buat tiket, dan catat semua yang dapat Anda pikirkan di tiket. Periksa juga apakah "bug" ini telah dicatat sebelumnya, dan tautkan tiketnya. Akhirnya, Anda mungkin mendapatkan tiket yang cukup untuk membentuk pola bagaimana mereproduksi bug. Ini termasuk bekerja di sekitar yang digunakan untuk mencoba menghindarinya. Bahkan jika ini adalah satu-satunya contoh, jika ada yang pertama kali, pada akhirnya akan ada yang kedua kalinya. Ketika Anda menemukan penyebabnya, tutup tiketnya dengan penjelasan tentang apa penyebabnya sehingga Anda memiliki gagasan kuat tentang apa yang terjadi jika itu terjadi lagi (memperbaiki hilang dalam penggabungan yang buruk)

  1. Lakukan analisis pengerasan

Lihatlah sistem, apa yang gagal, dan bagaimana itu gagal. Cobalah untuk menemukan area kode yang dapat diperbarui untuk mengurangi kemungkinan kegagalan. Beberapa contoh...

  • Ganti kode ad-hoc dengan panggilan khusus (seperti execute(<query>)denganexecuteMyStoredProcedure(<params>)
  • Jalankan skrip verifikasi malam hari untuk memverifikasi integritas data (sehingga ini dapat dideteksi dalam 24 jam berikutnya)
  • Tambahkan / tingkatkan pencatatan dan pengarsipan (pencadangan).
  • Mengubah batas keamanan yang tidak tepat (misalnya, orang / program yang hanya membaca data tidak memiliki izin menulis; Tidak membiarkan pengembang yang tidak bertanggung jawab atas produksi tidak dapat masuk ke server produksi)
  • Tambahkan verifikasi data / sanitasi jika tidak ada

Ini mungkin tidak memperbaiki bug, tetapi bahkan jika tidak, sistem sekarang lebih stabil / aman sehingga masih terbayar.

  1. Tambahkan peringatan sistem

Agak bagian dari 2, tetapi sesuatu terjadi, dan Anda perlu tahu kapan itu terjadi lagi. Anda harus membuat beberapa skrip / program pemeriksaan kesehatan untuk memantau sistem, sehingga admin dapat diperingatkan dalam waktu 24 jam sejak pelapisan ulang bug (semakin sedikit penundaan, semakin baik, semakin masuk akal). Ini akan membuat pembersihan lebih mudah. (Perhatikan bahwa selain log basis data, OS juga harus mencatat siapa yang log in, dan setiap tindakan yang tidak dibaca yang mereka lakukan. Paling tidak, harus ada log jaringan lalu lintas ke mesin itu)

Tezra
sumber
0

Masalah Anda bukan disebabkan oleh kesalahan pada perangkat lunak Anda, tetapi oleh seseorang yang mengutak-atik database. Jika Anda menyebut hal-hal yang salah sebagai "bug", maka bug Anda mudah direproduksi: Hal-hal akan selalu salah ketika seseorang melakukan hal-hal bodoh ke database. Dan ada beberapa cara untuk menghindari "bug" ini, dengan tidak mengizinkan database untuk dimodifikasi secara manual atau menggunakan perangkat lunak yang tidak diuji, dan dengan secara ketat mengontrol siapa yang dapat memodifikasi database.

Jika Anda hanya menyebut kesalahan dalam database Anda sebagai "bug", maka Anda tidak memiliki bug yang tidak dapat diproduksi kembali, Anda tidak memiliki bug sama sekali. Anda mungkin memiliki laporan bug, tetapi Anda juga memiliki bukti bahwa masalahnya bukan disebabkan oleh bug. Jadi Anda dapat menutup laporan bug, bukan sebagai "tidak dapat diproduksi ulang", tetapi sesuatu yang lain seperti "database rusak". Tidak jarang ada laporan bug di mana investigasi menunjukkan tidak ada bug, tetapi pengguna menggunakan perangkat lunak yang salah, harapan pengguna salah, dll.

Jika demikian, Anda masih tahu ada masalah yang tidak ingin diulang, jadi Anda mengambil tindakan yang sama seperti pada kasus pertama.

gnasher729
sumber