1. 程式人生 > 資料庫 >詳解MySQL與Spring的自動提交(autocommit)

詳解MySQL與Spring的自動提交(autocommit)

1 MySQL的autocommit設定

MySQL預設是開啟自動提交的,即每一條DML(增刪改)語句都會被作為一個單獨的事務進行隱式提交。如果修改為關閉狀態,則執行DML語句之後要手動提交 才能生效。
查詢當前會話的自動提交是否開啟:

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit  | ON  |
+---------------+-------+

查詢全域性的自動提交是否開啟:

mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit  | ON  |
+---------------+-------+

通過修改autocommit變數可以關閉和開啟操作

關閉當前會話的自動提交模式
mysql> set autocommit=0;

 
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit  | OFF  |
+---------------+-------+

 全域性的autocommit還是開啟狀態
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit  | ON  |
+---------------+-------+

 
 關閉全域性的autocommit
mysql> set global autocommit=0;

 
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit  | OFF  |
+---------------+-------+

如果想要MySQL服務重啟之後仍能生效,需要設定系統環境變數。MySQL5.7 在cnf配置檔案中[mysqld]下面設定autocommit的值。

[mysqld]
...
autocommit=0

Spring中對自動提交的控制

MySQL的JDBC驅動包 mysql-connector-java 會給會話的connection預設開啟自動提交,譬如 mysql-connector-java-8.0.22版本的程式碼:

//com.mysql.cj.protocol.a.NativeServerSession.java
  private boolean autoCommit = true;

常用的資料庫連線池 如HikariCP,druid等,預設也是開啟自動提交,會將connection的自動提交設定都改為true。
druid在初始化DataSource的時候設定connection的autocommit為true。程式碼如下:

com.alibaba.druid.pool.DruidAbstractDataSource.java
  protected volatile boolean             defaultAutoCommit             = true;
  ...
  public void initPhysicalConnection(Connection conn,Map<String,Object> variables,Object> globalVariables) throws SQLException {
    if (conn.getAutoCommit() != defaultAutoCommit) {
      //將connection的autocommit設定為true
      conn.setAutoCommit(defaultAutoCommit);
    }
    ...
 
  }

HikariCP 初始化DataSource的預設配置 中autocommit也是true:

com.zaxxer.hikari.HikariConfig.java
  public HikariConfig()
  {
   ...
   isAutoCommit = true;
  }

對於事務管理器PlatformTransactionManager管理的顯式事務(譬如@Transactional註解宣告)在 開啟事務時會關閉自動提交模式。 程式碼如下:

	@Override
	protected void doBegin(Object transaction,TransactionDefinition definition) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
      		........

			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,// so we don't want to do it unnecessarily (for example if we've explicitly
			// configured the connection pool to set it already).
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
                //關閉自動提交模
                con.setAutoCommit(false);
			}

      		.......
		}

		catch (Throwable ex) {
     		.......
		}
	}

總結

MySQL的autocommit模式預設是開啟狀態,為了防止手動的DML操作導致失誤,生產環境可以設定為預設關閉的狀態。一般的jdbc 連線池預設都是開啟狀態,而且是可配置的。顯式事務下會設定成關閉狀態,單純的修改資料庫環境的autocommit不會對程式碼的行為產生影響。

以上就是詳解MySQL與Spring的自動提交(autocommit)的詳細內容,更多關於MySQL 自動提交(autocommit)的資料請關注我們其它相關文章!