這是歷史版本頁面 — 看 PostgreSQL 最新版本

資料庫卡卡或鎖死?PostgreSQL 能解決什麼

PostgreSQL 軟體圖示 PostgreSQL 14.1 資料更新 2021-11-12 閱讀約 6 分鐘

你正在開發一個網站或應用程式,資料量從幾千筆成長到幾十萬筆,原本順暢的查詢開始變慢,甚至偶爾出現「資料庫被鎖住」的錯誤。你想找一個能撐住這種成長、又不會讓你在資料正確性上提心吊膽的資料庫,但市面上選項太多,不知道從哪裡下手。

一般人習慣先用 Excel 或輕量型資料庫(例如 SQLite)撐著,但資料一多、同時讀寫的人一多,這些方案就會開始出現效能瓶頸或鎖定問題。這類工具真正的切入點,是提供一套完整的「關聯式資料庫管理系統」:用結構化的表格存放資料、用 SQL 查詢、支援交易(Transaction)確保資料不會寫到一半出錯,並透過索引、分割區等機制讓查詢在資料量變大時仍然有辦法維持效能。

PostgreSQL 操作介面
PostgreSQL 的操作介面

01PostgreSQL 這套軟體到底能做什麼?

它是一套開放原始碼的關聯式資料庫管理系統,主要用途是存放、查詢、管理結構化資料。你可以用它建立多張有關聯的表格,用 SQL 語法做新增、讀取、更新、刪除,並設定主鍵、外鍵、唯一性限制等規則來確保資料正確。它也支援交易、並行控制、備份還原,適合當作網站、應用程式或內部系統的資料後端。

02它支援哪些資料型態?我只存文字和數字夠用嗎?

除了常見的整數、數值、字串、布林值,它還支援日期時間、陣列、範圍、UUID、JSON/JSONB、XML、鍵值對(Hstore),以及點、線、多邊形等幾何資料。如果你需要存圖片、聲音或影片這類大型二進位物件,它也有支援。所以不只是文字數字,半結構化資料或地理位置資料都可以放進來。

PostgreSQL 介面畫面 2
PostgreSQL 介面畫面

03資料量很大的時候,查詢會不會越來越慢?

它提供多種索引類型,包括 B-tree、多欄位索引、部分索引、GiST、GIN、BRIN 等,也支援表示式索引和覆蓋索引。查詢規劃器會嘗試找出有效率的執行計畫,並支援平行查詢、資料表分割區、JIT 編譯。不過索引要自己設計,不是裝好就自動變快,需要依照實際查詢模式來建立。

04多人同時讀寫,會不會互相卡住或鎖死?

它採用多版本並行控制(MVCC),讓讀取和寫入不會互相阻擋,也支援 SQL 標準定義的所有交易隔離等級,包括 Serializable。你可以設定明確鎖定或建議性鎖定(Advisory Locks)來控制特定情況的並行行為。但要注意,交易隔離等級和鎖定的設定會影響實際行為,需要依照應用情境調整。

PostgreSQL 介面畫面 3
PostgreSQL 介面畫面

05資料安全方面,它有沒有提供什麼保護機制?

它支援多種身分驗證方式,包括 GSSAPI、SSPI、LDAP、SCRAM-SHA-256、憑證驗證等,也有細緻的存取控制系統,可以做到欄位層級和列層級的安全設定。另外有 Write-ahead Logging(WAL)來確保資料寫入的可靠性,並支援非同步、同步、邏輯複製,以及時間點復原(PITR)和主動備援。

06這套軟體適合什麼樣的人或團隊?

適合需要處理大量結構化資料、重視資料完整性和交易正確性的開發者或團隊。如果你在建置網站後端、內部管理系統、需要跑複雜查詢或報表,而且希望資料庫本身是開放原始碼、不用付授權費,那它會是一個可以考慮的選項。它也適合需要自訂資料型態或函式的人,因為擴充性很強。

PostgreSQL 介面畫面 4
PostgreSQL 介面畫面

07我只會用圖形介面操作,不會寫指令,這樣能用嗎?

它安裝時會附帶 pgAdmin 圖形介面工具,可以用視覺化方式建立資料庫、執行 SQL 查詢、設定使用者權限、備份還原。但要注意,官方資料提到它「內建的 GUI 管理工具有限」,如果習慣用圖形介面做所有事情,可能會覺得某些進階操作還是得回到指令列。另外介面是英文的,沒有官方中文介面。

08我目前只是做個小專案,資料量不大,用它會不會太重?

它功能完整,但相對的也需要花時間學習和設定。如果只是幾百筆資料、單人使用、不需要複雜查詢,用 SQLite 這類輕量資料庫可能更簡單,不需要安裝伺服器、不需要管理使用者權限。不過如果你預期資料會持續成長,或之後要多人同時連線,提早用它可以省下日後搬移資料的麻煩。

09它的介面只有英文,我英文不好,會不會很難上手?

官方介面和文件都是英文,沒有內建中文語系。如果你英文閱讀有困難,操作上會比較吃力。不過它的文件寫得相當完整,社群也很大,網路上可以找到大量中文教學文章和討論。如果你完全無法閱讀英文,可能需要先評估自己能不能接受看英文文件,或考慮其他有中文介面的資料庫工具。

10我聽說它更新很頻繁,這樣會不會一直要升級、很麻煩?

它的版本更新確實算頻繁,近一年內有多次更新。升級時可能需要手動調整,官方資料也提到「升級可能需要手動調整」。如果你不習慣定期維護資料庫,或沒有專門的人負責這塊,頻繁的版本更新可能會造成額外負擔。但如果不更新,安全性漏洞和 bug 修復就無法取得。

11它跟 MySQL Workbench 或 SQLite 比起來,我該怎麼選?

這取決於你的需求。SQLite 是嵌入式資料庫,適合單機、小規模、不需要伺服器管理的場景;MySQL Workbench 是 MySQL 的圖形介面工具,本身不是資料庫。PostgreSQL 則是一套完整的資料庫伺服器,功能更全面,支援更多進階功能(如自訂型態、多種索引、豐富的資料型態)。如果你需要複雜查詢、高並行、資料完整性要求高,它會是比較完整的方案;如果只是簡單存取,SQLite 可能更輕量。

下載與官方連結

前往官方網站 下載 PostgreSQL

postgresql-14.1-1-windows-x64.exe · 連結指向軟體原廠

版本紀錄

再看 5 筆

看完整版本清單

這一版改了什麼

What's new in this version:

- Make the server reject extraneous data after an SSL or GSS encryption handshake
- A man-in-the-middle with the ability to inject data into the TCP connection could stuff some cleartext data into the start of a supposedly encryption-protected database session. This could be abused to send faked SQL commands to the server, although that would only work if the server did not demand any authentication data. (However, a server relying on SSL certificate authentication might well not do so.)
- The PostgreSQL Project thanks Jacob Champion for reporting this problem.
- Make libpq reject extraneous data after an SSL or GSS encryption handshake
- A man-in-the-middle with the ability to inject data into the TCP connection could stuff some cleartext data into the start of a supposedly encryption-protected database session. This could probably be abused to inject faked responses to the client's first few queries, although other details of libpq's behavior make that harder than it sounds. A different line of attack is to exfiltrate the client's password, or other sensitive data that might be sent early in the session. That has been shown to be possible with a server vulnerable to CVE-2021-23214.
- The PostgreSQL Project thanks Jacob Champion for reporting this problem.
- Fix physical replication for cases where the primary crashes after shipping a WAL segment that ends with a partial WAL record
- If the primary did not survive long enough to finish writing the rest of the incomplete WAL record, then the previous crash-recovery logic had it back up and overwrite WAL starting from the beginning of the incomplete WAL record. This is problematic since standby servers may already have copies of that WAL segment. They will then see an inconsistent next segment, and will not be able to recover without manual intervention. To fix, do not back up over a WAL segment boundary when restarting after a crash. Instead write a new type of WAL record at the start of the next WAL segment, informing readers that the incomplete WAL record will never be finished and must be disregarded.
- When applying this update, it's best to update standby servers before the primary, so that they will be ready to handle this new WAL record type if the primary happens to crash.
- Ensure that parallel VACUUM doesn't miss any indexes (Peter Geoghegan, Masahiko Sawada)
- A parallel VACUUM would fail to process indexes that are below the min_parallel_index_scan_size cutoff, if the table also has at least two indexes that are above that size. This could result in those indexes becoming corrupt, since they'd still contain references to any heap entries removed by the VACUUM; subsequent queries using such indexes would be likely to return rows they shouldn't. This problem does not affect autovacuum, since it doesn't use parallel vacuuming. However, it is advisable to reindex any manually-vacuumed tables that have the right mix of index sizes.
- Fix CREATE INDEX CONCURRENTLY to wait for the latest prepared transactions (Andrey Borodin)
- Rows inserted by just-prepared transactions might be omitted from the new index, causing queries relying on the index to miss such rows. The previous fix for this type of problem failed to account for PREPARE TRANSACTION commands that were still in progress when CREATE INDEX CONCURRENTLY checked for them. As before, in installations that have enabled prepared transactions (max_prepared_transactions > 0), it's recommended to reindex any concurrently-built indexes in case this problem occurred when they were built.
- Avoid race condition that can cause backends to fail to add entries for new rows to an index being built concurrently
- While it's apparently rare in the field, this case could potentially affect any index built or reindexed with the CONCURRENTLY option. It is recommended to reindex any such indexes to make sure they are correct.
- Fix REINDEX CONCURRENTLY to preserve operator class parameters that were attached to the target index (Michael Paquier)
- Fix incorrect creation of shared dependencies when cloning a database that contains non-builtin objects
- The effects of this error are probably limited in practice. In principle, it could allow a role to be dropped while it still owns objects; but most installations would never want to drop a role that had been used for objects they'd added to template1.
- Ensure that the relation cache is invalidated for a table being attached to or detached from a partitioned table
- This oversight could allow misbehavior of subsequent inserts/updates addressed directly to the partition, but only in currently-existing sessions.
- Fix corruption of parse tree while creating a range type
- CREATE TYPE incorrectly freed an element of the parse tree, which could cause problems for a later event trigger, or if the CREATE TYPE command was stored in the plan cache and used again later.
- Fix updates of element fields in arrays of domain over composite
- A command such as UPDATE tab SET fld[1].subfld = val failed if the array's elements were domains rather than plain composites.
- Disallow the combination of FETCH FIRST WITH TIES and FOR UPDATE SKIP LOCKED
- FETCH FIRST WITH TIES necessarily fetches one more row than requested, since it cannot stop until it finds a row that is not a tie. In our current implementation, if FOR UPDATE is used then that row will also get locked even though it is not returned. That results in undesirable behavior if the SKIP LOCKED option is specified. It's difficult to change this without introducing a different set of undesirable behaviors, so for now, forbid the combination.
- Disallow ALTER INDEX index ALTER COLUMN col SET (options)
- While the parser accepted this, it's undocumented and doesn't actually work.
- Fix corner-case loss of precision in numeric power()
- The result could be inaccurate when the first argument is very close to 1.
- Avoid choosing the wrong hash equality operator for Memoize plans
- This error could result in crashes or incorrect query results.
- Fix planner error with pulling up subquery expressions into function rangetable entries
- If a function in FROM laterally references the output of some sub-SELECT earlier in the FROM clause, and we are able to flatten that sub-SELECT into the outer query, the expression(s) copied into the function expression were not fully processed. This could lead to crashes at execution.
- Avoid using MCV-only statistics to estimate the range of a column
- There are corner cases in which ANALYZE will build a most-common-values (MCV) list but not a histogram, even though the MCV list does not account for all the observed values. In such cases, keep the planner from using the MCV list alone to estimate the range of column values.
- Fix restoration of a Portal's snapshot inside a subtransaction
- If a procedure commits or rolls back a transaction, and then its next significant action is inside a new subtransaction, snapshot management went wrong, leading to a dangling pointer and probable crash. A typical example in PL/pgSQL is a COMMIT immediately followed by a BEGIN ... EXCEPTION block that performs a query.
- Clean up correctly if a transaction fails after exporting its snapshot
- This oversight would only cause a problem if the same session attempted to export a snapshot again. The most likely scenario for that is creation of a replication slot (followed by rollback) and then creation of another replication slot.
- Prevent wraparound of overflowed-subtransaction tracking on standby servers
- This oversight could cause significant performance degradation (manifesting as excessive SubtransSLRU traffic) on standby servers.
- Ensure that prepared transactions are properly accounted for during promotion of a standby server (Michael Paquier, Andres Freund)
- There was a narrow window where a prepared transaction could be omitted from a snapshot taken by a concurrently-running session. If that session then used the snapshot to perform data updates, erroneous results or data corruption could occur.
- Fix “could not find RecursiveUnion” error when EXPLAIN tries to print a filter condition attached to a WorkTableScan node
- Ensure that the correct lock level is used when renaming a table
- For historical reasons, ALTER INDEX ... RENAME can be applied to any sort of relation. The lock level required to rename an index is lower than that required to rename a table or other kind of relation, but the code got this wrong and would use the weaker lock level whenever the command is spelled ALTER INDEX.
- Avoid null-pointer-dereference crash when dropping a role that owns objects being dropped concurrently
- Prevent “snapshot reference leak” warning when lo_export() or a related function fails
- Fix inefficient code generation for CoerceToDomain expression nodes
- Avoid O(N^2) behavior in some list-manipulation operations
- These changes fix slow processing in several scenarios, including: when a standby replays a transaction that held many exclusive locks on the primary; when many files are due to be unlinked after a checkpoint; when hash aggregation involves many batches; and when pg_trgm extracts indexable conditions from a complex regular expression. Only the first of these scenarios has actually been reported from the field, but they all seem like plausible consequences of inefficient list deletions.
- Add more defensive checks around B-tree posting list splits
- This change should help detect index corruption involving duplicate table TIDs
- Avoid assertion failure when inserting NaN into a BRIN float8 or float4 minmax_multi_ops index
- In production builds, such cases would result in a somewhat inefficient, but not actually incorrect, index.
- Allow the autovacuum launcher process to respond to pg_log_backend_memory_contexts() requests more quickly
- Fix memory leak in HMAC hash calculations
- Disallow setting huge_pages to on when shared_memory_type is sysv
- Previously, this setting was accepted, but it did nothing for lack of any implementation
- Fix checking of query type in PL/pgSQL's RETURN QUERY statement
- RETURN QUERY should accept any query that can return tuples, e.g. UPDATE RETURNING. v14 accidentally disallowed anything but SELECT; moreover, the RETURN QUERY EXECUTE variant failed to apply any query-type check at all.
- Fix pg_dump to dump non-global default privileges correctly
- If a global (unrestricted) ALTER DEFAULT PRIVILEGES command revoked some present-by-default privilege, for example EXECUTE for functions, and then a restricted ALTER DEFAULT PRIVILEGES command granted that privilege again for a selected role or schema, pg_dump failed to dump the restricted privilege grant correctly.
- Make pg_dump acquire shared lock on partitioned tables that are to be dumped
- This oversight was usually pretty harmless, since once pg_dump has locked any of the leaf partitions, that would suffice to prevent significant DDL on the partitioned table itself. However problems could ensue when dumping a childless partitioned table, since no relevant lock would be held.
- Fix crash in pg_dump when attempting to dump trigger definitions from a pre-8.3 server
- Fix incorrect filename in pg_restore's error message about an invalid large object TOC file
- Ensure that pgbench exits with non-zero status after a socket-level failure
- The desired behavior is to finish out the run but then exit with status 2. Also, fix the reporting of such errors.
- Prevent pg_amcheck from checking temporary relations, as well as indexes that are invalid or not ready
- This avoids unhelpful checks of relations that will almost certainly appear inconsistent
- Make contrib/amcheck skip unlogged tables when running on a standby server
- It's appropriate to do this since such tables will be empty, and unlogged indexes were already handled similarly
- Change contrib/pg_stat_statements to read its “query texts” file in units of at most 1GB
- Such large query text files are very unusual, but if they do occur, the previous coding would fail on Windows 64 (which rejects individual read requests of more than 2GB).
- Fix null-pointer crash when contrib/postgres_fdw tries to report a data conversion error
- Ensure that GetSharedSecurityLabel() can be used in a newly-started session that has not yet built its critical relation cache entries
- When running a TAP test, include the module's own directory in PATH
- This allows tests to find built programs that are not installed, such as custom test drivers.
- Use the CLDR project's data to map Windows time zone names to IANA time zones
- When running on Windows, initdb attempts to set the new cluster's timezone parameter to the IANA time zone matching the system's prevailing time zone. We were using a mapping table that we'd generated years ago and updated only fitfully; unsurprisingly, it contained a number of errors as well as omissions of recently-added zones. It turns out that CLDR has been tracking the most appropriate mappings, so start using their data. This change will not affect any existing installation, only newly-initialized clusters.
- Update time zone data files to tzdata release 2021e for DST law changes in Fiji, Jordan, Palestine, and Samoa, plus historical corrections for Barbados, Cook Islands, Guyana, Niue, Portugal, and Tonga.