diff --git a/changes/1.5.0.md b/changes/1.5.0.md
index 09855468b443a1bc3eef83bc7c646235530eceee..b062dcad38066b48261d381f30539e88c99b27ae 100644
--- a/changes/1.5.0.md
+++ b/changes/1.5.0.md
@@ -78,6 +78,7 @@ Seata 鏄竴娆惧紑婧愮殑鍒嗗竷寮忎簨鍔¤В鍐虫柟妗堬紝鎻愪緵楂樻€ц兘鍜岀畝鍗�
   - [[#3236](https://github.com/seata/seata/pull/3236)] 浼樺寲鎵ц瑙i攣鎿嶄綔鐨勬潯浠讹紝鍑忓皯涓嶅繀瑕佺殑store鎿嶄綔銆�
   - [[#3485](https://github.com/seata/seata/pull/3485)] 浼樺寲 ConfigurationFactory 涓棤鐢ㄧ殑try/catch
   - [[#3505](https://github.com/seata/seata/pull/3505)] 浼樺寲GlobalTransactionScanner绫讳腑鏃犵敤鐨刬f鍒ゆ柇
+  - [[#3544](https://github.com/seata/seata/pull/3544)] 浼樺寲鏃犳硶閫氳繃Statement#getGeneratedKeys鏃讹紝鍙兘鑾峰彇鍒版壒閲忔彃鍏ョ殑绗竴涓富閿殑闂
   - [[#3549](https://github.com/seata/seata/pull/3549)] 缁熶竴涓嶅悓琛ㄤ腑鐨剎id瀛楁鐨勯暱搴�
   - [[#3551](https://github.com/seata/seata/pull/3551)] 璋冨ぇRETRY_DEAD_THRESHOLD鐨勫€间互鍙婅缃垚鍙厤缃�
   
diff --git a/changes/en-us/1.5.0.md b/changes/en-us/1.5.0.md
index d054bd46313774dcdea60faa40390b177631f86b..d939f0cd645104116d054c690c8392ca79fa5b62 100644
--- a/changes/en-us/1.5.0.md
+++ b/changes/en-us/1.5.0.md
@@ -175,10 +175,9 @@
   - [[#3236](https://github.com/seata/seata/pull/3236)] optimize the conditions for executing unlocking
   - [[#3485](https://github.com/seata/seata/pull/3485)] optimize useless codes in ConfigurationFactory
   - [[#3505](https://github.com/seata/seata/pull/3505)] optimize useless if judgments in the GlobalTransactionScanner class
+  - [[#3544](https://github.com/seata/seata/pull/3544)] optimize the get pks by auto when auto generated keys is false
   - [[#3549](https://github.com/seata/seata/pull/3549)] unified the length of xid in scripts
   - [[#3551](https://github.com/seata/seata/pull/3551)] make RETRY_DEAD_THRESHOLD bigger and configurable
-                                                        
-
   
 
   ### test	
diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java
index 03fc704eb421261755f02226c358fa1a006a1218..9b73dff4a78239f293f64a62f964bc8087576464 100644
--- a/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java
+++ b/rm-datasource/src/main/java/io/seata/rm/datasource/exec/mysql/MySQLInsertExecutor.java
@@ -32,6 +32,7 @@ import io.seata.sqlparser.util.JdbcConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.math.BigDecimal;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.HashMap;
@@ -41,6 +42,7 @@ import java.util.Objects;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * @author jsbxyyx
@@ -55,6 +57,13 @@ public class MySQLInsertExecutor extends BaseInsertExecutor implements Defaultab
      */
     public static final String ERR_SQL_STATE = "S1009";
 
+    /**
+     * The cache of auto increment step of database
+     * the key is the db's resource id
+     * the value is the step
+     */
+    public static final Map<String, BigDecimal> RESOURCE_ID_STEP_CACHE = new ConcurrentHashMap<>(8);
+
     /**
      * Instantiates a new Abstract dml base executor.
      *
@@ -127,8 +136,17 @@ public class MySQLInsertExecutor extends BaseInsertExecutor implements Defaultab
             // specify Statement.RETURN_GENERATED_KEYS to
             // Statement.executeUpdate() or Connection.prepareStatement().
             if (ERR_SQL_STATE.equalsIgnoreCase(e.getSQLState())) {
-                LOGGER.warn("Fail to get auto-generated keys, use 'SELECT LAST_INSERT_ID()' instead. Be cautious, statement could be polluted. Recommend you set the statement to return generated keys.");
-                genKeys = statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()");
+                LOGGER.error("Fail to get auto-generated keys, use 'SELECT LAST_INSERT_ID()' instead. Be cautious, " +
+                        "statement could be polluted. Recommend you set the statement to return generated keys.");
+                int updateCount = statementProxy.getUpdateCount();
+                ResultSet firstId = genKeys = statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()");
+
+                // If there is batch insert
+                // do auto increment base LAST_INSERT_ID and variable `auto_increment_increment`
+                if (updateCount > 1 && canAutoIncrement(pkMetaMap)) {
+                    firstId.next();
+                    return autoGeneratePks(new BigDecimal(firstId.getString(1)), autoColumnName, updateCount);
+                }
             } else {
                 throw e;
             }
@@ -171,4 +189,39 @@ public class MySQLInsertExecutor extends BaseInsertExecutor implements Defaultab
         // mysql default keyword the logic not support. (sample: insert into test(id, name) values(default, 'xx'))
         throw new NotSupportYetException();
     }
+
+    protected Map<String, List<Object>> autoGeneratePks(BigDecimal cursor, String autoColumnName, Integer updateCount) throws SQLException {
+        BigDecimal step = BigDecimal.ONE;
+        String resourceId = statementProxy.getConnectionProxy().getDataSourceProxy().getResourceId();
+        if (RESOURCE_ID_STEP_CACHE.containsKey(resourceId)) {
+            step = RESOURCE_ID_STEP_CACHE.get(resourceId);
+        } else {
+            ResultSet increment = statementProxy.getTargetStatement().executeQuery("SHOW VARIABLES LIKE 'auto_increment_increment'");
+
+            increment.next();
+            step = new BigDecimal(increment.getString(2));
+            RESOURCE_ID_STEP_CACHE.put(resourceId, step);
+        }
+
+        List<Object> pkValues = new ArrayList<>();
+        for (int i = 0; i < updateCount; i++) {
+            pkValues.add(cursor);
+            cursor = cursor.add(step);
+        }
+
+        Map<String, List<Object>> pkValuesMap = new HashMap<>(1, 1.001f);
+        pkValuesMap.put(autoColumnName,pkValues);
+        return pkValuesMap;
+    }
+
+    protected boolean canAutoIncrement(Map<String, ColumnMeta> primaryKeyMap) {
+        if (primaryKeyMap.size() != 1) {
+            return false;
+        }
+
+        for (ColumnMeta pk : primaryKeyMap.values()) {
+            return pk.isAutoincrement();
+        }
+        return false;
+    }
 }
diff --git a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java
index 32b9a56273923d22cf7daf3eeb05f632c2bd0829..023fe03ab3da2a16e497366d8ee51efa3b8ea133 100644
--- a/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java
+++ b/rm-datasource/src/test/java/io/seata/rm/datasource/exec/MySQLInsertExecutorTest.java
@@ -15,11 +15,17 @@
  */
 package io.seata.rm.datasource.exec;
 
+import com.mysql.jdbc.ResultSetImpl;
+import com.mysql.jdbc.util.ResultSetUtil;
 import io.seata.common.exception.ShouldNeverHappenException;
+import io.seata.common.util.ReflectionUtil;
 import io.seata.rm.datasource.ConnectionProxy;
+import io.seata.rm.datasource.DataSourceProxy;
 import io.seata.rm.datasource.PreparedStatementProxy;
 import io.seata.rm.datasource.StatementProxy;
 import io.seata.rm.datasource.exec.mysql.MySQLInsertExecutor;
+import io.seata.rm.datasource.mock.MockDataSource;
+import io.seata.rm.datasource.mock.MockResultSet;
 import io.seata.rm.datasource.sql.struct.ColumnMeta;
 import io.seata.rm.datasource.sql.struct.Row;
 import io.seata.rm.datasource.sql.struct.TableMeta;
@@ -35,6 +41,9 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -73,12 +82,18 @@ public class MySQLInsertExecutorTest {
     private HashMap<String,Integer> pkIndexMap;
 
     @BeforeEach
-    public void init() {
+    public void init() throws SQLException {
         ConnectionProxy connectionProxy = mock(ConnectionProxy.class);
         when(connectionProxy.getDbType()).thenReturn(JdbcConstants.MYSQL);
+        when(connectionProxy.getDataSourceProxy()).thenReturn(new DataSourceProxy(new MockDataSource()));
 
         statementProxy = mock(PreparedStatementProxy.class);
         when(statementProxy.getConnectionProxy()).thenReturn(connectionProxy);
+        when(statementProxy.getTargetStatement()).thenReturn(statementProxy);
+
+        MockResultSet resultSet = new MockResultSet(statementProxy);
+        resultSet.mockResultSet(Arrays.asList("Variable_name", "Value"), new Object[][]{{"auto_increment_increment", "1"}});
+        when(statementProxy.getTargetStatement().executeQuery("SHOW VARIABLES LIKE 'auto_increment_increment'")).thenReturn(resultSet);
 
         StatementCallback statementCallback = mock(StatementCallback.class);
         sqlInsertRecognizer = mock(SQLInsertRecognizer.class);
@@ -565,6 +580,20 @@ public class MySQLInsertExecutorTest {
         Assertions.assertFalse(insertExecutor.checkPkValuesForSinglePk(pkValues, false));
     }
 
+    @Test
+    public void test_autoGeneratePks() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        Method method = MySQLInsertExecutor.class.getDeclaredMethod("autoGeneratePks", new Class[]{BigDecimal.class, String.class, Integer.class});
+        method.setAccessible(true);
+        Object resp = method.invoke(insertExecutor, BigDecimal.ONE, "ID", 3);
+
+        Assertions.assertNotNull(resp);
+        Assertions.assertTrue(resp instanceof Map);
+
+        Map<String, List> map = (Map<String, List>) resp;
+        Assertions.assertEquals(map.size(), 1);
+        Assertions.assertEquals(map.get("ID").size(), 3);
+    }
+
     private List<String> mockInsertColumns() {
         List<String> columns = new ArrayList<>();
         columns.add(ID_COLUMN);