@@ -2171,6 +2171,22 @@ exec_parse_message(const char *query_string, /* string to execute */
21712171 */
21722172 if (IS_SINGLENODE ())
21732173 ((SelectStmt * )raw_parse_tree -> stmt )-> disableLockingOptimization = false;
2174+ else if (enableLockOptimization )
2175+ {
2176+ SelectStmt * stmt = (SelectStmt * )raw_parse_tree -> stmt ;
2177+
2178+ /*
2179+ * If GUC 'enableLockOptimization' is on, we try to optimize the lock for
2180+ * select-for-update and similar queries.
2181+ *
2182+ * If the lock cannot be optimized, use the default way.
2183+ */
2184+ stmt -> disableLockingOptimization = false;
2185+ if (!checkCanOptSelectLockingClause (stmt ))
2186+ {
2187+ ((SelectStmt * )raw_parse_tree -> stmt )-> disableLockingOptimization = true;
2188+ }
2189+ }
21742190 else
21752191 ((SelectStmt * )raw_parse_tree -> stmt )-> disableLockingOptimization = true;
21762192 }
@@ -2472,6 +2488,26 @@ exec_bind_message(StringInfo input_message)
24722488
24732489 portal -> is_extended_query = true;
24742490
2491+ /*
2492+ * If GUC 'enableLockOptimization' is on, we try to optimize the lock for
2493+ * select-for-update and similar queries.
2494+ *
2495+ * If the lock for query can be optimized, we use tuple lock instead of
2496+ * relation lock to improve Concurrency Performance. LockRows is executed
2497+ * on segment, but reader gangs cannot execute LockRows, so we need to
2498+ * dispatch query plan to writer gangs, that's why we reset is_extended_query
2499+ * to false here.
2500+ */
2501+ if (enableLockOptimization && IsA (psrc -> raw_parse_tree -> stmt , SelectStmt ))
2502+ {
2503+ SelectStmt * stmt = (SelectStmt * )psrc -> raw_parse_tree -> stmt ;
2504+
2505+ if (checkCanOptSelectLockingClause (stmt ))
2506+ {
2507+ portal -> is_extended_query = false;
2508+ }
2509+ }
2510+
24752511 /*
24762512 * Prepare to copy stuff into the portal's memory context. We do all this
24772513 * copying first, because it could possibly fail (out-of-memory) and we
@@ -2973,6 +3009,45 @@ exec_execute_message(const char *portal_name, int64 max_rows)
29733009 if (max_rows <= 0 )
29743010 max_rows = FETCH_ALL ;
29753011
3012+ /*
3013+ * If the lock for select-for-update and similar queries is optimized, we should
3014+ * fetch all rows here.
3015+ *
3016+ * Since we optimize the lock for query, the query plan is dispatched to writer
3017+ * gangs to execute. If we do not fetch all rows here, the writer gangs are occupied
3018+ * and can not execute other query plans.
3019+ */
3020+ if (enableLockOptimization )
3021+ {
3022+ CachedPlanSource * psrc ;
3023+
3024+ if (portal -> prepStmtName )
3025+ {
3026+ PreparedStatement * pstmt ;
3027+
3028+ pstmt = FetchPreparedStatement (portal -> prepStmtName , true);
3029+ psrc = pstmt -> plansource ;
3030+ }
3031+ else
3032+ {
3033+ /* special-case the unnamed statement */
3034+ psrc = unnamed_stmt_psrc ;
3035+ if (!psrc )
3036+ ereport (ERROR ,
3037+ (errcode (ERRCODE_UNDEFINED_PSTATEMENT ),
3038+ errmsg ("unnamed prepared statement does not exist" )));
3039+ }
3040+
3041+ if (IsA (psrc -> raw_parse_tree -> stmt , SelectStmt ) &&
3042+ checkCanOptSelectLockingClause ((SelectStmt * )psrc -> raw_parse_tree -> stmt ) &&
3043+ max_rows != FETCH_ALL )
3044+ {
3045+ ereport (ERROR ,
3046+ (errcode (ERRCODE_INTERNAL_ERROR ),
3047+ errmsg ("Should fetch all rows for query if lock optimization is enabled" )));
3048+ }
3049+ }
3050+
29763051 completed = PortalRun (portal ,
29773052 max_rows ,
29783053 true, /* always top level */
0 commit comments