返回信息流有一个sql脚本,用于向mysql中导入几百万条数据,脚本内容大概如下:
```SQL
create table A (...);
start transaction;
insert into A values(...),(...);
/* many insert statements here */
insert into A values(...),(...);
commit;
```
在shell下使用了如下语句进行导入:
```Bash
$ nohup mysql -uroot -p<password> <db_name> < file.sql
```
由于数据量比较大,因此导入时间比较长
在导入进行的过程中,将这个导入的进程kill掉,但登录到mysql中可以看到成功导入了一部分数据
那么脚本中写的事务语句是不是没有生效呢,还是有其它原因造成了一部分数据可以成功导入?
(开启了事务而没有commit的话,中间所有的insert语句不是应该都不会生效吗?)
这是一条镜像帖。来源:北邮人论坛 / database / #10631同步于 2017/10/27
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Database机器人发帖
【问题】MySQL从sql导入数据
lzj0218
2017/10/27镜像同步13 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
查询了下事务的处理方式
http://www.cnblogs.com/langtianya/p/4777662.html
set autocommit=0,
当前session禁用自动提交事物,自此句执行以后,每个SQL语句或者语句块所在的事务都需要显示"commit"才能提交事务。
start transaction
指的是启动一个新事务。
我觉得吧,如果你要这样开启事务导入,建议每个insert 后面都有commit
呃,我的目的就是想关闭自动提交,让所有insert都执行后再一起提交,
问题是为什么事务提交之前杀掉了进程还是有一部分数据提交了
【 在 GOON 的大作中提到: 】
: 查询了下事务的处理方式
: http://www.cnblogs.com/langtianya/p/4777662.html
:
: ...................
发自「贵邮」
按楼上的说法如果set autocommit=0无效的话看看你的存储引擎用的mylsam还是innodb,mylsam不支持事务处理,所以你设定=0也是无效的,但是可以执行不会报错
autocommit=0时,commit之前的语句当作一个整体,只有碰到commit的时候才会全部提交,要么全过要么全死,错误的话会callback到执行前,所以你的目的和这个配置是有关的,我用的5.7版本的默认是on 也就是1,
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
存储引擎是innodb,autocommit=0这个倒是没有设,因为看到mysql文档里说start transaction时应该会自动关闭autocommit,直到遇到commit或rollback语句:
To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=@A WHERE type=1;
COMMIT;
With START TRANSACTION, autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK. The autocommit mode then reverts to its previous state.
参考自:https://dev.mysql.com/doc/refman/5.7/en/commit.html
【 在 phpy 的大作中提到: 】
: 按楼上的说法如果set autocommit=0无效的话看看你的存储引擎用的mylsam还是innodb,mylsam不支持事务处理,所以你设定=0也是无效的,但是可以执行不会报错
【 在 lzj0218 的大作中提到: 】
: 存储引擎是innodb,autocommit=0这个倒是没有设,因为看到mysql文档里说start transaction时应该会自动关闭autocommit,直到遇到commit或rollback语句:
: To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement:
: START TRANSACTION;
: ...................
看了这篇文章,找了些资料,楼主可以对照看看
1.确认加了rollback回滚命令,错误时会回滚,如果没加错误不会回滚,怀疑楼主事务中没加这句话;
2.检查表结构真的为innodb? show create table xxx;
3.是否支持innodb引擎 show engines; 有些版本特别老的my.cnf文件里还会有skip-innodb这句话将这句注释掉,这个可能性很小;
第2条可以确认是innodb,第3条我用的是mysql5.7对innodb的支持应该是没有问题的
第1条不是太懂麻烦详细说一下,事务里面一定要写rollback吗?
刚刚试了一下,begin之后insert几条数据,然后不commit直接退出数据库,再重连以后这几条数据都没有插入进去,所以我觉得在导入sql脚本时如果直接kill掉进程和这个是类似的,没有commit应该什么都没写进去吧(但实际上写成功了所以觉得有问题)
另外,就算在脚本里写了rollback,进程被直接杀掉应该也是执行不到的?
【 在 phpy 的大作中提到: 】
: 看了这篇文章,找了些资料,楼主可以对照看看
: 1.确认加了rollback回滚命令,错误时会回滚,如果没加错误不会回滚,怀疑楼主事务中没加这句话;
: 2.检查表结构真的为innodb? show create table xxx;
: ...................
有点绕,组织了很久的语言,先说下commit和rollback的原理吧,提交数据有三种类型,显式,隐式,自动,显式里面有commit和rollback,commit rollback 都是用在执行 curd之后的,curd执行完之后,处理的数据都会放在回滚段中(除了select语句),等待commit或者rollback(这里应该知道为什么楼主这次测试的时候没带commit其实是给不进去数据的),当用户执行commit后,放在回滚段中的数据就会被删除。
而楼主第一次插入了部分数据的原因可能就是在干掉进程前已经完成了一部分事务,然后干掉的时候commit将回滚段的数据提交了, 于是插入了一部分数据,而带上rollback就可以回滚到上次rollback(如果没有回滚到begin),意思就是清除rollback1/begin-rollback2回滚段的数据,不做修改