TRUNCATE in postgresql
在我們的印象裡,truncate 命令是 ddl 是沒有事務的。
在mysql 跟oracle 裡是這樣的。
在pg 裡truncate 是事務安全的,也就是是說是可以回滾的。
[code]
cyp_app=> begin;
BEGIN
Time: 0.130 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.358 ms
cyp_app=> truncate table tmp_lsl ;
TRUNCATE TABLE
Time: 0.371 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
0
(1 row)
Time: 0.274 ms
cyp_app=> rollback;
ROLLBACK
Time: 91.841 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.401 ms
[/code]
這個功能得益於PG的mvcc 的實現。
但是truncate 操作不是MVCC-safe的。
什麼意思呢?
我們看看先:
session A :
[code]
cyp_app=> begin;
BEGIN
Time: 0.122 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.282 ms
[/code]
session B :
[code]
BEGIN
cyp_app=> select count(*) from tmp_lsl ;
count
-------
140
(1 row)
[/code]
session A : 繼續執行:
[code]
cyp_app=> truncate table tmp_lsl;
這個時候操作已經被掛起了,
[/code]
session B:
[code]
繼續下一步操作
cyp_app=> select count(*) from tmp_lsl ;
count
-------
140
(1 row)
cyp_app=> delete from tmp_lsl;
DELETE 140
cyp_app=>
cyp_app=> rollback;
ROLLBACK
session B 可以執行刪除。
[/code]
session A
[code]
這個是sessiona 的truncate 返回了
cyp_app=> truncate table tmp_lsl;
TRUNCATE TABLE
Time: 4953153.416 ms
cyp_app=>
cyp_app=> rollback;
ROLLBACK
Time: 92.143 ms
cyp_app=>
[/code]
在看另一個
sessionA:
[code]
cyp_app=> begin;
BEGIN
Time: 0.123 ms
cyp_app=> select count(*) from tmp_Lsl;
count
-------
140
(1 row)
Time: 0.377 ms
cyp_app=> truncate table tmp_lsl;
TRUNCATE TABLE
Time: 0.331 ms
cyp_app=>
表已經被truncate 了但是沒有提交。
[/code]
開啟session B
[code]
cyp_app=> begin;
BEGIN
cyp_app=> select count(*) from tmp_lsl;
sessionB 被掛起了,無法查詢到結果:
[/code]
session A 繼續:
[code]
cyp_app=> commit;
COMMIT
Time: 92.136 ms
cyp_app=>
session A 提交資料庫修改:
[/code]
sessionB :
[code]
cyp_app=> select count(*) from tmp_lsl;
count
-------
0
(1 row)
cyp_app=> commit;
COMMIT
cyp_app=>
sesssion B 返回了0行,session b 看到的是session A 執行完成後的資料快照。
[/code]
什麼意思呢? 根據我們設定的readcommited 的事務隔離級別,sessionB 看到sessionA 提交的結果是對的。
主要的問題是truncate 不是mvcc-safe 的,就是truncate 的操作發生後,對所有的事務都返回一個空的結果集,不論這個事務是否在truncate 操作發生前還是發生後。
對於前面的那個,session b 不提交,則session a 的truncate 被掛起,則是因為session b 只有的access share 共享鎖,阻止了truncate clusive 鎖的獲得。
truncate 不會帶來任何資料一致性的問題。
因為這個原因,我們在在pg 同步oracle 的表的時候,本想直接在一個事務裡truncate table 然後再insert 的做法,似乎就會有些行不通。
這回導致與阻止其他事務,或者被其他事務阻止,而insert 是全表資料,如果資料量比較大,阻塞其他事務的機會應該更大一些。
比較靠譜的操作是用 a b 表輪換的方式。
在mysql 跟oracle 裡是這樣的。
在pg 裡truncate 是事務安全的,也就是是說是可以回滾的。
[code]
cyp_app=> begin;
BEGIN
Time: 0.130 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.358 ms
cyp_app=> truncate table tmp_lsl ;
TRUNCATE TABLE
Time: 0.371 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
0
(1 row)
Time: 0.274 ms
cyp_app=> rollback;
ROLLBACK
Time: 91.841 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.401 ms
[/code]
這個功能得益於PG的mvcc 的實現。
但是truncate 操作不是MVCC-safe的。
什麼意思呢?
我們看看先:
session A :
[code]
cyp_app=> begin;
BEGIN
Time: 0.122 ms
cyp_app=> select count(*) from tmp_lsl;
count
-------
140
(1 row)
Time: 0.282 ms
[/code]
session B :
[code]
BEGIN
cyp_app=> select count(*) from tmp_lsl ;
count
-------
140
(1 row)
[/code]
session A : 繼續執行:
[code]
cyp_app=> truncate table tmp_lsl;
這個時候操作已經被掛起了,
[/code]
session B:
[code]
繼續下一步操作
cyp_app=> select count(*) from tmp_lsl ;
count
-------
140
(1 row)
cyp_app=> delete from tmp_lsl;
DELETE 140
cyp_app=>
cyp_app=> rollback;
ROLLBACK
session B 可以執行刪除。
[/code]
session A
[code]
這個是sessiona 的truncate 返回了
cyp_app=> truncate table tmp_lsl;
TRUNCATE TABLE
Time: 4953153.416 ms
cyp_app=>
cyp_app=> rollback;
ROLLBACK
Time: 92.143 ms
cyp_app=>
[/code]
在看另一個
sessionA:
[code]
cyp_app=> begin;
BEGIN
Time: 0.123 ms
cyp_app=> select count(*) from tmp_Lsl;
count
-------
140
(1 row)
Time: 0.377 ms
cyp_app=> truncate table tmp_lsl;
TRUNCATE TABLE
Time: 0.331 ms
cyp_app=>
表已經被truncate 了但是沒有提交。
[/code]
開啟session B
[code]
cyp_app=> begin;
BEGIN
cyp_app=> select count(*) from tmp_lsl;
sessionB 被掛起了,無法查詢到結果:
[/code]
session A 繼續:
[code]
cyp_app=> commit;
COMMIT
Time: 92.136 ms
cyp_app=>
session A 提交資料庫修改:
[/code]
sessionB :
[code]
cyp_app=> select count(*) from tmp_lsl;
count
-------
0
(1 row)
cyp_app=> commit;
COMMIT
cyp_app=>
sesssion B 返回了0行,session b 看到的是session A 執行完成後的資料快照。
[/code]
什麼意思呢? 根據我們設定的readcommited 的事務隔離級別,sessionB 看到sessionA 提交的結果是對的。
主要的問題是truncate 不是mvcc-safe 的,就是truncate 的操作發生後,對所有的事務都返回一個空的結果集,不論這個事務是否在truncate 操作發生前還是發生後。
對於前面的那個,session b 不提交,則session a 的truncate 被掛起,則是因為session b 只有的access share 共享鎖,阻止了truncate clusive 鎖的獲得。
truncate 不會帶來任何資料一致性的問題。
因為這個原因,我們在在pg 同步oracle 的表的時候,本想直接在一個事務裡truncate table 然後再insert 的做法,似乎就會有些行不通。
這回導致與阻止其他事務,或者被其他事務阻止,而insert 是全表資料,如果資料量比較大,阻塞其他事務的機會應該更大一些。
比較靠譜的操作是用 a b 表輪換的方式。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/133735/viewspace-732292/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL truncate原理MySql
- truncate 命令使用
- oracle truncate table recover(oracle 如何拯救誤操作truncate的表)Oracle
- Diffrence Between delete and truncatedelete
- truncate 比 delete 慢delete
- drop、delete 與truncatedelete
- SQL – TRUNCATE vs DELETESQLdelete
- truncate操作巨慢
- Truncate and data_object_idObject
- TRUNCATE資料恢復資料恢復
- truncate delete drop 區別delete
- truncate delete 的區別delete
- openGauss lo_truncate
- 【Linux之truncate 命令用法】Linux
- 簡述truncate、delete和dropdelete
- Oracle Truncate表恢復(ODU)Oracle
- OGG 獲取truncate 操作
- Truncate,Delete,Drop的比較.delete
- truncate與delete的區別delete
- truncate 比 delete 慢的原因。delete
- 執行truncate在pl/sqlSQL
- truncate和delete 的區別delete
- partition table中truncate應用
- 分割槽表truncate慢處理
- Oracle大表清理truncate .. reuse storageOracle
- SQL truncate 、delete與drop區別SQLdelete
- oracle truncate 與 delete 的區別Oracledelete
- truncate,delete,drop的異同點delete
- 禁止客戶端 誤 truncate table客戶端
- truncate 和 delete 的效能對比delete
- kingbase——建立truncate函式函式
- Sqlserver 如何truncate linked server的表SQLServer
- SQL資料庫中Truncate的用法SQL資料庫
- 如何在Linux中使用 Truncate 命令Linux
- truncate操作消除ORACLE SEG壞塊解析Oracle
- undo truncate 導致qps下降分析
- delete和truncate刪除的區別delete
- 揭祕Oracle資料庫truncate原理Oracle資料庫