編程中的典型錯誤操作(第一部分)

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"摘要"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"軟件開發是一項越來越普遍的工作,但是在開發的過程中,有一些錯誤是我們經常遇到,或者是一犯再犯的,所以George在本文中整理了在服務器和操作系統級別以及數據庫級別常見的錯誤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文是該系列的第一篇。第二篇已發佈"},{"type":"link","attrs":{"href":"https:\/\/www.infoq.cn\/article\/A4C1vGKDOlcI69MqBvlL","title":"xxx","type":null},"content":[{"type":"text","text":"編程中的典型錯誤操作(第二部分)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"本文最初發表於"},{"type":"link","attrs":{"href":"https:\/\/primalskill.blog\/mistakes-were-made-part-1","title":null,"type":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"Primal Skill Programming網站"}],"marks":[{"type":"italic"}]},{"type":"text","marks":[{"type":"italic"}],"text":",經原作者George授權,由InfoQ中文站翻譯分享。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"編程中的錯誤是有害的,這一點大家都沒有異議吧?不管怎樣,我們都應該竭力避免它們,否則的話,就會導致我們花費額外的金錢、錯失最後期限,並且會引發焦慮,不僅對你來講會這樣,對你的客戶同樣如此。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在我17年的編程生涯中,我依然記得我犯過的最大錯誤是不小心刪除了客戶的生產數據庫。真要命!當時估計的損失會有幾十萬美元,但是後來幸運的是,我“找到了”幾天前的手動備份,所以最終沒有想象中的那麼糟糕。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開發人員可能會犯無數的錯誤,開發人員的生活便是如此,但是有些類型的錯誤你應該盡力避免。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我通過兩篇系列文章的方式將這些錯誤分門別類地列出來,因爲畢竟千禧一代的年輕人都喜歡列表(每"},{"type":"text","marks":[{"type":"italic"}],"text":"個都在快速掃視,沒有人再去詳細閱讀任何東西,好了,吐槽結束"},{"type":"text","text":")。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"服務器和操作系統級別的錯誤"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這可能不完全是開發人員的權限,而是DevOps或系統管理員團隊的權限,不過,我經常看到在小型的開發公司中,開發人員具有訪問服務器的權限,這其實也沒什麼,不是每個公司都有成立專門部門的預算,但是需要確保你不要犯下面的錯誤。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"自己託管一切"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然在世界某個地方的數據中心中託管自己的專用服務器是一件很好的事情,而且這種方式也更能節省成本,但是前提是你要知道要做哪些事情。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大多數的專用服務器都是非託管的,這意味着你可以租用數據中心的物理服務器,但配置相關的事情都要自己來做。數據中心提供了最低限度的安全性,這裏的安全性只涉及到數據中心的其他服務器,但在操作系統層面卻沒有做太多的事情。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了實現這種安全性和最佳配置,你需要一個受管理的專用服務器,在這裏還需要僱傭一個專門的系統管理團隊,但是這些服務器要花很多的錢。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"問一下自己,你是否真的需要一個專門的服務器?如果你只想要託管一個簡單的網站,可能是一個WordPress博客,那麼我們有大量的可選方案:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/wpengine.com\/","title":null,"type":null},"content":[{"type":"text","text":"WPEngine"}]},{"type":"text","text":"用來託管WordPress"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http:\/\/dreamhost.com\/","title":null,"type":null},"content":[{"type":"text","text":"DreamHost"}]},{"type":"text","text":"用來實現簡單的網站託管"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"或者從數以百萬計的供應商中選擇VPS服務器託管"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"沒有備份"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你能夠從本文或者一般的編程經驗中學到什麼的話,那就是:"},{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"創建那些該死的備份"},{"type":"text","text":",不僅僅是項目的備份,還有個人數據的備份。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很多的初學者甚至資深的程序員都會犯這樣錯誤,那就是不創建備份,不使用版本控制,不備份數據庫。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以使用不同的備份策略,但需要知道一件重要的事情,那就是在同一臺服務器上進行備份是不行的。如果服務器被黑客攻擊了或者以某種方式遭到了破壞該怎麼辦?你所有的備份也將付諸東流。備份始終應該被轉移到另外一臺單獨的服務器上。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你應該知道有兩種備份類型,即"},{"type":"text","marks":[{"type":"strong"}],"text":"邏輯備份和物理備份"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"邏輯備份是從數據庫中提取實際的數據,並將它們以文本或二進制的形式存儲到文件中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"物理備份將整個的數據庫信息提取到一個文件中,包括數據庫和表元數據、寫前日誌(write-ahead log,WAL),以及完整恢復數據庫所需的所有必要信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以,哪種方式更重要呢?邏輯備份更容易實現,對於小型的數據庫來說,這確實是我們所需的方式,而物理備份的方式實現起來更爲複雜,如果你的項目規模正在變大的話,那麼你可能在某個時間點會用到這種方式。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"不正確的日誌設置"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以日誌的方式記錄服務器、數據庫和應用的數據,"},{"type":"text","marks":[{"type":"strong"}],"text":"並確保對它們進行分析"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很多的開發人員要麼在服務器上實現日誌(通過在操作系統上預先定義),要麼在應用層面實現日誌。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"好的日誌策略可以爲你省去大量的麻煩和開發時間,更不用說它還能幫助我們預防可能的黑客攻擊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"只有當你不斷監控應用、數據庫和服務器上發生了什麼的情況下,日誌纔有意義。從最基本的層面來講,你所需要的只是錯誤日誌,隨後你可以實現進程日誌,以及可選的調試日誌。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以實現各種各樣的策略,從簡單的文件日誌開始,到去中心化的日誌管理器和聚合器,比如"},{"type":"link","attrs":{"href":"https:\/\/www.elastic.co\/logstash","title":null,"type":null},"content":[{"type":"text","text":"Logstash"}]},{"type":"text","text":"或"},{"type":"link","attrs":{"href":"https:\/\/kafka.apache.org\/","title":null,"type":null},"content":[{"type":"text","text":"Kafka"}]},{"type":"text","text":"。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"沒有緩存"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們都知道這樣一個說法,"},{"type":"link","attrs":{"href":"https:\/\/martinfowler.com\/bliki\/TwoHardThings.html","title":null,"type":null},"content":[{"type":"text","text":"計算機科學領域有兩個難題"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在現代Web應用開發中,緩存是非常重要的。不是每個人都有千兆的互聯網連接,實際上,世界上很多人都在使用3G的連接速度瀏覽互聯網。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"緩存可以爲你的項目提供極大的幫助,而實施一個成功的緩存策略則取決於你的實際背景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你可以瞭解的技術包括:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"如果你使用WordPress的話,可以瞭解"},{"type":"link","attrs":{"href":"https:\/\/wordpress.org\/plugins\/w3-total-cache\/","title":null,"type":null},"content":[{"type":"text","text":"W3 Total Cache"}]},{"type":"text","text":"。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"對於通用的PHP來說,OpCode cache可以提供幫助。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"更細粒度的緩存解決方案是"},{"type":"link","attrs":{"href":"https:\/\/varnish-cache.org\/intro\/index.html#intro","title":null,"type":null},"content":[{"type":"text","text":"Varnish Cache"}]},{"type":"text","text":"。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"對於數據庫緩存來講,"},{"type":"link","attrs":{"href":"https:\/\/redis.io\/","title":null,"type":null},"content":[{"type":"text","text":"Redis"}]},{"type":"text","text":"或"},{"type":"link","attrs":{"href":"https:\/\/memcached.org\/","title":null,"type":null},"content":[{"type":"text","text":"Memcached"}]},{"type":"text","text":"是不錯的解決方案(注意,這兩項技術並不僅僅侷限於數據庫緩存)。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/www.cloudflare.com\/learning\/cdn\/what-is-a-cdn\/","title":null,"type":null},"content":[{"type":"text","text":"內容交付網絡(CDN)"}]},{"type":"text","text":"也能爲我們提供幫助。"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"缺少維護"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你應該實施的一個良好策略就是定期的維護週期,在每個週期裏,你需要更新服務器、數據庫、應用依賴等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼會不斷變得陳舊,會出現缺陷,就像其他的產品一樣,代碼也有一個生命週期,在週期結束後它會重構、更新或刪除。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在舊的代碼上運行項目會帶來很多的麻煩,這樣你的代碼、服務器和數據庫都更易於受到攻擊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以我來看,如果是中小型的項目,應該每週對服務器和數據實施一次維護週期,並且要對你的實際代碼及其依賴實施兩週一次的維護週期。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"數據庫級別的錯誤"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"爲所有的開發環境使用同一個數據庫"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於任何項目來說,混合使用數據都不是一個好的長期解決方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個經過“實戰檢驗”的解決方案就是爲每個開發環境使用不同的數據庫,主要包括:開發、staging和生產。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着像Docker這樣的容器化軟件的誕生,在開發環境中啓用一個新的隔離容器,複製生產服務器和數據庫的配置是一件非常容易的事情。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"不進行性能審計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當一個網站運行緩慢的時候,如果不是網絡問題的話,那大多數就是數據庫的問題。數據庫是Web應用的第一個瓶頸。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不對數據庫進行定期的性能審計是很多開發人員所犯的一個錯誤,這是因爲他們在本地開發環境中沒有看到性能的下降。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以做的第一個性能方面的修復就是檢查在要進行查詢的表的列中,是否添加了恰當的索引(比如,當你使用SQL的時候,出現在WHERE語句中的列)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關於數據庫性能的文章可以單獨寫一整個系列,所以我不會在這裏展開論述,但你應該查看"},{"type":"link","attrs":{"href":"https:\/\/use-the-index-luke.com\/","title":null,"type":null},"content":[{"type":"text","text":"Use the index, Luke!"}]},{"type":"text","text":"網站以瞭解更多細節,而且可以購買作者編寫的“"},{"type":"link","attrs":{"href":"https:\/\/amzn.to\/3rJotf5","title":null,"type":null},"content":[{"type":"text","text":"SQL Performance Explained: Everything developers need to know about SQL performance"}]},{"type":"text","text":"”,這是一本對數據庫和性能進行深入研究的書。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"不進行安全審計"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最常見的數據庫黑客攻擊類型是SQL查詢注入攻擊。每個開發者都應該知道並關心在他們的Web應用程序上可能被攻擊的手段。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當你在你的項目中加入越來越多的工具和技術時,這不僅增加了複雜性,而且增加了黑客可能進行的攻擊類型,從而能使你的Web應用面臨一系列的潛在攻擊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"幸運的是,有大量關於這個主題的教程,請閱讀以下資源:"}]},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/owasp.org\/www-community\/attacks\/SQL_Injection","title":null,"type":null},"content":[{"type":"text","text":"OWASP的SQL注入文檔"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/SQL_Injection_Prevention_Cheat_Sheet.html","title":null,"type":null},"content":[{"type":"text","text":"SQL注入預防手冊"}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"http:\/\/sqlmap.org\/","title":null,"type":null},"content":[{"type":"text","text":"SQLMap滲透測試工具"}]}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"忽視數據完整性"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在數據庫中操縱數據時,如果操作不當,很容易對數據造成破壞。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是我多年來看到的,開發人員在操作數據時犯的最大錯誤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你要插入、更新或刪除相關數據的話,要始終使用事務來實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如,我們有一個葡萄酒目錄的數據庫,將葡萄酒本身的數據保存在一個表中,將針對該葡萄酒的訂單保存在另一個表中。如果由於某種原因,有種酒停產了並且從數據庫中刪除了,但訂單卻沒有被刪除,當我們試圖查看訂單或者對其進行分析時,將導致數據被破壞,因爲所有的訂單將指向數據庫中已經不存在的葡萄酒條目。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有人認爲,當刪除某種葡萄酒的時候,也可以執行刪除相關訂單的操作,但如果分開進行的話(例如,兩個單獨的DELETE查詢,一個接着一個去執行),倘若出現數據庫連接丟失或其他原因,仍然可能導致數據損壞。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種情況下,最好使用事務,這樣可以保證"},{"type":"text","marks":[{"type":"italic"}],"text":"在事務內"},{"type":"text","text":"執行的查詢總是一起執行的,如果其中一個查詢失敗,事務也會失敗,並且變更會回滾到原來的狀態。"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"不關心敏感數據"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“純文本”?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我感到驚訝的是,即使是在今天,將敏感數據存儲在純文本中仍然是一個問題,這樣的錯誤開發人員還在犯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"即使是大的開發公司也會犯這樣的錯誤,用純文本存儲密碼、用純文本泄露敏感信息的日誌等等,這樣的例子數不勝數。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"密碼應該始終"},{"type":"text","marks":[{"type":"strong"}],"text":"以散列形式存儲"},{"type":"text","text":"。好的散列算法是"},{"type":"link","attrs":{"href":"https:\/\/en.wikipedia.org\/wiki\/Blowfish_(cipher","title":null,"type":null},"content":[{"type":"text","text":"Blowfish"}]},{"type":"text","text":"或"},{"type":"link","attrs":{"href":"https:\/\/en.wikipedia.org\/wiki\/Twofish","title":null,"type":null},"content":[{"type":"text","text":"Twofish"}]},{"type":"text","text":",大多數數據庫引擎都原生支持它們。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開發者犯的另一個大錯是他們沒有使用經過實戰檢驗的加密算法,相反,他們試圖採用自己的加密算法。"},{"type":"text","marks":[{"type":"strong"}],"text":"不要試圖重新發明輪子"},{"type":"text","text":"。我有個壞消息要告訴你,這麼做將會失敗,非常糟糕。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"加密算法是由數學家而不是Web開發人員創造的。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"結論"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"軟件開發非常有趣,並且是令人興奮的,但要把它作對卻是很難的。80\/20法則告訴我們,最後的20%決定了一個Web應用的成敗,並佔用了80%的開發時間。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我希望你喜歡這篇文章,請繼續關注第二部分,我將會討論在應用層面可能發生的錯誤。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"歡迎評論並分享這篇文章,如果你有任何問題,可以在"},{"type":"link","attrs":{"href":"https:\/\/twitter.com\/feketegy","title":null,"type":null},"content":[{"type":"text","text":"Twitter"}]},{"type":"text","text":"上聯繫我。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章