在執行DDL語句前,一定要記得設置鎖超時時間。
DDL語句會申請access exclusive鎖,access exclusive鎖是最強的排它鎖,在獲得鎖前,要求該表上沒有任何會話訪問;同時,DDL語句會阻塞任何對表的操作。例如:drop table、truncate、reindex、vacuum full、部分alter table等等。
由于DDL語句在獲得鎖前,要求該表上沒有任何會話訪問,如果有長事務、長時間執行的SQL訪問表,那么需要等待這些會話執行完成后才能獲得access exclusive鎖。在等鎖的過程中,DDL語句會阻塞該表上所有DDL語句后面執行的SQL,包括SELECT。如果該表有高并發SQL語句,那么將會導致大量的SQL語句被阻塞,進而導致數據庫連接數迅速增長、服務器CPU打滿,嚴重影響業務。
可以通過設置鎖超時解決此問題,鎖超時設置一般可以使用如下3種方式,影響范圍各不相同,超時時間推薦30~60s:
當前會話生效(即時生效):
teledb=# set lock_timeout to '30s';
用戶默認鎖超時(設置之后,新建的連接才會生效):
teledb=# alter role teledb set lock_timeout to '30s';
數據庫默認鎖超時(設置之后,新建的連接才會生效):
teledb=# alter database teledb set lock_timeout to '30s';
注意lock_timeout參數是獲取鎖的超時時間,不止對DDL語句生效,對DML、DQL也生效;因此用戶、數據庫級默認鎖超時間參數不應設置過小,設置過小可能會導致正常的DML、DQL語句超時,尤其并發業務量大,業務高峰期間,可能會因為鎖超時設置過小導致大面積SQL語句超時報錯。