* CdbTryOpenTable -- Opens a table with a specified lock mode. * * CDB: Like try_table_open, except that it will upgrade the lock when needed * for distributed tables. * * Note1: Postgres will always hold RowExclusiveLock for DMLs * Note2: INSERT statement will not call this function. * Note3: This function may return NULL (eg. when just before we open the table, * other transaction
| 195 | * b. if target table is heap table, just like Postgres, do not upgrade |
| 196 | */ |
| 197 | Relation |
| 198 | CdbTryOpenTable(Oid relid, LOCKMODE reqmode, bool *lockUpgraded) |
| 199 | { |
| 200 | LOCKMODE lockmode; |
| 201 | |
| 202 | Relation rel; |
| 203 | |
| 204 | /* |
| 205 | * This if-else statement will try to open the relation and |
| 206 | * save the lockmode it uses to open the relation. |
| 207 | * |
| 208 | * If we are doing expclicit UPDATE|DELETE on catalogs (this can |
| 209 | * only be possible when GUC allow_system_table_mods is set), the |
| 210 | * update or delete does not hold locks on catalog on segments, so |
| 211 | * we do not need to consider lock-upgrade for DML on catalogs. |
| 212 | * |
| 213 | * In singlenode mode, since local deadlock detection can already |
| 214 | * detect and solve deadlocks, we act as if the global deadlock |
| 215 | * detector is enabled. |
| 216 | */ |
| 217 | if (reqmode == RowExclusiveLock && |
| 218 | (Gp_role == GP_ROLE_DISPATCH || IS_SINGLENODE()) && |
| 219 | relid >= FirstNormalObjectId) |
| 220 | { |
| 221 | if (!gp_enable_global_deadlock_detector && !IS_SINGLENODE()) |
| 222 | { |
| 223 | /* |
| 224 | * Without GDD, to avoid global deadlock, always |
| 225 | * upgrade locklevel to ExclusiveLock |
| 226 | */ |
| 227 | lockmode = ExclusiveLock; |
| 228 | rel = try_table_open(relid, lockmode, false); |
| 229 | } |
| 230 | else |
| 231 | { |
| 232 | lockmode = RowExclusiveLock; |
| 233 | rel = try_table_open(relid, lockmode, false); |
| 234 | |
| 235 | if (RelationIsValid(rel) && |
| 236 | RelationIsNonblockRelation(rel)) |
| 237 | { |
| 238 | /* |
| 239 | * AO|AOCO table does not support concurrently |
| 240 | * update or delete on segments, so we first close |
| 241 | * the relation and reopen it using upgraded lockmode. |
| 242 | * NOTE: during this time window, there is a race that |
| 243 | * the table with relid is dropped, and will lead to |
| 244 | * returning NULL. This will not cause any problem |
| 245 | * because it is caller's duty to check NULL pointer. |
| 246 | */ |
| 247 | table_close(rel, RowExclusiveLock); |
| 248 | lockmode = ExclusiveLock; |
| 249 | rel = try_table_open(relid, lockmode, false); |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | } |
| 254 | else |
no test coverage detected