更新時(shí)間:2021-01-25 17:10:55 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1509次
默認(rèn)情況下, MySQL啟用自動(dòng)提交模式(變量autocommit為ON)。這意味著, 只要你執(zhí)行DML操作的語句,MySQL會(huì)立即隱式提交事務(wù)(Implicit Commit)。如果你了解SQL Server數(shù)據(jù)庫的話,你會(huì)發(fā)現(xiàn)MySQL自動(dòng)提交模式跟SQL Server有很多相似之處。
1 .MySQL的autocommit設(shè)置
MySQL默認(rèn)是開啟自動(dòng)提交的,即每一條DML(增刪改)語句都會(huì)被作為一個(gè)單獨(dú)的事務(wù)進(jìn)行隱式提交。如果修改為關(guān)閉狀態(tài),則執(zhí)行DML語句之后要手動(dòng)提交 才能生效。
查詢當(dāng)前會(huì)話的自動(dòng)提交是否開啟:
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
查詢?nèi)值淖詣?dòng)提交是否開啟:
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
通過修改autocommit變量可以關(guān)閉和開啟操作
關(guān)閉當(dāng)前會(huì)話的自動(dòng)提交模式
mysql> set autocommit=0;
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
全局的autocommit還是開啟狀態(tài)
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
關(guān)閉全局的autocommit
mysql> set global autocommit=0;
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
如果想要MySQL服務(wù)重啟之后仍能生效,需要設(shè)置系統(tǒng)環(huán)境變量。MySQL5.7 在cnf配置文件中[mysqld]下面設(shè)置autocommit的值。
[mysqld]
...
autocommit=0
2.修改autocommit模式
mysql> set session autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show session variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.00 sec)
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql>
mysql> set global autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.01 sec)
mysql> 注意,上述SQL修改會(huì)話系統(tǒng)變量或全局系統(tǒng)變量,只對(duì)當(dāng)前實(shí)例有效,如果MySQL服務(wù)重啟的話,這些設(shè)置就會(huì)丟失,如果要永久生效,就必須在配置文件中修改系統(tǒng)變量。[mysqld]
autocommit=0不過網(wǎng)上還有種方式,如下所示,在MySQL 5.6/5.7下測試,發(fā)現(xiàn)不生效,查了一下,這種方式似乎從MySQL 5.6開始已經(jīng)不生效了,必須用autocommit=0這種方式替換。[mysqld]
init_connect='SET autocommit=0'
3.Spring中MySQL對(duì)自動(dòng)提交的控制
MySQL的JDBC驅(qū)動(dòng)包 mysql-connector-java 會(huì)給會(huì)話的connection默認(rèn)開啟自動(dòng)提交,譬如 mysql-connector-java-8.0.22版本的代碼:
//com.mysql.cj.protocol.a.NativeServerSession.java
private boolean autoCommit = true;
常用的數(shù)據(jù)庫連接池 如HikariCP,druid等,默認(rèn)也是開啟自動(dòng)提交,會(huì)將connection的自動(dòng)提交設(shè)置都改為true。
druid在初始化DataSource的時(shí)候設(shè)置connection的autocommit為true。代碼如下:
com.alibaba.druid.pool.DruidAbstractDataSource.java
protected volatile boolean defaultAutoCommit = true;
...
public void initPhysicalConnection(Connection conn, Map<String, Object> variables, Map<String, Object> globalVariables) throws SQLException {
if (conn.getAutoCommit() != defaultAutoCommit) {
//將connection的autocommit設(shè)置為true
conn.setAutoCommit(defaultAutoCommit);
}
...
}
HikariCP 初始化DataSource的默認(rèn)配置 中autocommit也是true:
com.zaxxer.hikari.HikariConfig.java
public HikariConfig()
{
...
isAutoCommit = true;
}
對(duì)于事務(wù)管理器PlatformTransactionManager管理的顯式事務(wù)(譬如@Transactional注解聲明)在 開啟事務(wù)時(shí)會(huì)關(guān)閉自動(dòng)提交模式。
代碼如下:
@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");
}
//關(guān)閉自動(dòng)提交模
con.setAutoCommit(false);
}
.......
}
catch (Throwable ex) {
.......
}
}
MySQL的autocommit模式默認(rèn)是打開狀態(tài),為了防止手動(dòng)的DML操作導(dǎo)致失誤,生產(chǎn)環(huán)境可以設(shè)置為默認(rèn)關(guān)閉的狀態(tài)。一般的JDBC連接池默認(rèn)都是開啟狀態(tài),而且是可配置的。顯式事務(wù)下會(huì)設(shè)置成關(guān)閉狀態(tài),單純的修改數(shù)據(jù)庫環(huán)境的autocommit不會(huì)對(duì)代碼的行為產(chǎn)生影響。因此,MySQL的自動(dòng)提交模式還是很值得信賴的,自動(dòng)提交模式可以通過服務(wù)器變量AUTOCOMMIT來控制,且不會(huì)對(duì)顯式事務(wù)造成影響。在本站的MySQL教程中,有著對(duì)MySQL自動(dòng)提交模式的詳細(xì)講解,還沒有弄通透的小伙伴可以前去觀看學(xué)習(xí)哦。