autocommit=1 时 insert 不生效?先确认当前会话模式
MySQL 默认开启自动提交(
autocommit=1),但这个值可能被会话级修改,或在连接池、ORM 中被重置。执行
INSERT后查不到数据,第一反应不该是“SQL 写错了”,而是检查当前事务状态:
SELECT @@autocommit;返回
0表示已关闭自动提交,此时所有 DML 都处于未提交事务中,除非手动
COMMIT或断开连接(部分客户端会回滚)。常见陷阱是用命令行连上后执行了
SET autocommit = 0,后续忘了恢复,导致看似“插入成功”实则未落盘。
显式事务中 COMMIT 和 ROLLBACK 的触发边界
显式事务以
BEGIN或
START TRANSACTION开始,以
COMMIT或
ROLLBACK结束。关键点在于:一旦执行了
COMMIT,该事务内所有变更永久生效;而
ROLLBACK仅回滚到最近一次
BEGIN(或隐式事务起点),不是回滚整个会话历史。注意以下行为: DDL 语句(如
CREATE TABLE)在大多数存储引擎中会隐式触发
COMMIT,导致前面未提交的 DML 一并提交 执行
SET autocommit = 1会立即提交当前活跃事务(如果存在) 客户端异常断开且未设
wait_timeout超时前,MySQL 通常会回滚未完成事务
Python pymysql / MySQLdb 中 autocommit 参数的实际作用
创建连接时传入
autocommit=True,等价于连接建立后立刻执行
SET autocommit = 1;设为
False则默认进入手动提交模式。但要注意: 即使
autocommit=False,调用
cursor.execute("INSERT ...") 也不会报错,只是暂存于事务中
必须显式调用 conn.commit()才真正写入;忘记调用就断开连接,数据丢失 使用上下文管理器(
with conn:)时,Python 的
mysqlclient和较新版本
pymysql会在退出时自动
commit,但前提是没发生异常;有异常则
rollback示例:
conn = pymysql.connect(autocommit=False)<br>cursor = conn.cursor()<br>cursor.execute("INSERT INTO t VALUES (1)")<br># 忘记 conn.commit() → 数据不会持久化如何安全地临时关闭 autocommit 做批量操作
批量插入/更新时关掉
autocommit能减少日志刷盘次数,提升性能,但风险也集中:一个出错可能导致整批失败。稳妥做法是: 用
START TRANSACTION显式包裹操作,而非全局
SET autocommit = 0控制单次事务数据量(如每 1000 行
COMMIT一次),避免长事务阻塞 MVCC 清理 确保应用层捕获
IntegrityError等异常并主动
ROLLBACK,否则连接可能卡在未完成事务状态 不要依赖超时自动回滚——
innodb_lock_wait_timeout控制锁等待,不控制事务生命周期 真正容易被忽略的是:某些中间件(如 ProxySQL、ShardingSphere)会拦截或改写
COMMIT语句,开启事务后务必验证实际提交行为是否符合预期。
