如何在使用 JDBC 驱动程序和 MySQL DBMS 时回滚 DDL 语句,例如 CREATE TABLE 和 DROP TABLE?

How to roll back DDL statements such CREATE TABLE and DROP TABLE while using JDBC driver with MySQL DBMS?

我有一个示例代码,它创建一个 table,在其中插入一些行,然后尝试取消整个事务,但是 conn.rollback() 似乎只对 INSERT 语句有效,而 CREATE TABLE 保持不受影响:新创建的 table 在数据库中永久保留,没有插入任何行。

这是将 JDBC 驱动程序与 MySQL DBMS 一起使用时的标准行为吗?

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestBatch {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC",
                "root", "root")) {

            // drop table
            try (Statement dropStatement = conn.createStatement()) {
                dropStatement.executeUpdate("DROP TABLE IF EXISTS mytable");
            }

            // create table, insert rows and rollback
            conn.setAutoCommit(false);
            try (Statement stmt = conn.createStatement()) {
                stmt.addBatch("CREATE TABLE mytable (id INT)");
                stmt.addBatch("INSERT INTO mytable VALUES (1)");
                stmt.addBatch("INSERT INTO mytable VALUES (2)");
                stmt.executeBatch();
                conn.rollback();
            } finally {
                conn.setAutoCommit(true);
            }
        } catch (SQLException e) {
            System.err.println(e.getMessage());
        }

    }
}

请注意,我使用的是 MySQL Server 8.0 和 Connector/J 版本。 8.0.17,参数default-storage-engine(在C:\ProgramData\MySQL\MySQL Server 8.0\my.ini中)设置为 INNODB.

正如 Paul Spiegel 和 Arnaud 所说,DDL 语句无法在 MySQL 中回滚。即使 MySQL 8 也是如此:https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

无论好坏,DDL 语句都会提交任何挂起的事务,如果它们是本地的并且不能在 XA 事务中使用(因为这会导致一个参与者在事务协调器没有发出命令的情况下提交数据)。