Discuss / SQL / 个人理解

个人理解

Topic source

饼cookies

#1 Created at ... [Delete] [Delete and Lock User]

我来谈谈我的理解,有问题的地方请大家提出:

COMMIT是指提交事务,即试图把事务内的所有SQL所做的修改永久保存。如果COMMIT语句执行失败了,整个事务也会失败

这句的意思是commit这条命令是把执行成功的部分提交了。但commit命令失败也不会进行更新。

情景:

BEGIN;UPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance + 100 WHERE id = 2;COMMIT;

第一行SQL执行成功,第二行SQL执行失败的话,数据库中的第一行 SQL执行的结果会由commit进行提交更新,而第二条由于失败并不会更新。

有些时候,我们希望主动让事务失败,这时,可以用ROLLBACK回滚事务,整个事务会失败

情景:

BEGIN;UPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance + 100 WHERE id = 2;ROLLBACK;

第一句和第二句SQL都成功了,但是由于是ROLLBACK所有数据并没有更新。

如果rollback失败了,此时不处理,等到客户端断开,MySQL内部默认会回滚,前提是这个链接不要有其它的一些操作。MySQL内部一般不会rollback失败,因为此时数据库会加一个锁。

廖雪峰

#2 Created at ... [Delete] [Delete and Lock User]

你的理解是错的。

begin 到 commit之间的所有更新语句要么全部执行要么全部回滚,执行一半那不叫事务。

石年618

#3 Created at ... [Delete] [Delete and Lock User]

楼下“九月”举例就很好的说明楼主的理解  也很符合   但是廖老师说这样理解又不对   实在难以理解?

廖雪峰

#4 Created at ... [Delete] [Delete and Lock User]

事务包含一到多条sql,要么全部执行成功,要么全部执行取消,没有执行一半的状态。

饼cookies

#5 Created at ... [Delete] [Delete and Lock User]

那按这么来理解:

事务的本质是要么全部执行成功,要么全部执行取消,

所以commit要和rollback进行对立的使用,在现实中执行更新的SQL语句都正常-->调用commit,SQL语句一旦有一句错误-->调用rollback;

还有一个疑问:那么begin 到 commit之间的SQL语句有错误还使用commit进行提交的情况是不是也属于事务吗?

饼cookies

#6 Created at ... [Delete] [Delete and Lock User]

我想了想觉得即使有错误的update也属于事务

饼cookies

#7 Created at ... [Delete] [Delete and Lock User]

上面的疑问应该改成

begin 到 commit之间的SQL语句有错误还使用commit进行提交的情况事务是不是也算成功了呢

廖雪峰

#8 Created at ... [Delete] [Delete and Lock User]

首先要明白SQL语句如果本身有错,比如update写成ubdate,表名列名写错了,这属于编程bug,赶紧改对

其次编程语言中执行sql是一条一条发到数据库的,如果执行的sql本身有问题,比如语法错误,直接就调用rollback了

try {
    executeUpdate("update bad_table ...");
    executeUpdate("update user ...");
    commit();
} catch (SQLException e) {
    rollback();
}

你硬要这么写:

try {
    try {
        executeUpdate("update bad_table ...");
    } catch (SQLException e) {
        // 出错了坚决不回滚,我就要继续执行下一条SQL
    }
    executeUpdate("update user ...");
    commit();
} catch (SQLException e) {
    rollback();
}

那你看到的效果就是第一个SQL语句报错,第二个语句执行成功

这叫垃圾代码

饼cookies

#9 Created at ... [Delete] [Delete and Lock User]

明白了,谢谢廖老师


  • 1

Reply