我们知道数据库中的SQL语句分为DDL(数据定义语言)、DQL(数据查询语言)、DML(数据操纵语言)、DCL(数据控制语言),详情请看SQL语句
当数据库的表中数据执行完添加、删除、和修改等数据操纵语言(DML)后,需要执行commit(提交)数据控制语言(DCL)才能使之起作用,或者需要执行rollback(回滚)数据控制语言(DCL)才能撤销DML语言的操作。
而MySQL数据库执行完DML后默认自动执行commit操作;
那如何才能去掉这个“默认”呢?这就需要在MySQL数据库中执行DML之前先执行set autocommit = 0
可关闭自动执行commit操作;待DML操作执行完后再执行commit;
即可使DML操作起作用,或者执行rollback;
即可撤销DML操作。
(但要注意的是:对于同一组sql语句,commit;
操作和rollback;
操作只能执行其中一个,即提交了就不能再回滚,回滚了就不能再提交)
例如:
create table account(
id char(36) primary key,
card_id varchar(20) unique,
name varchar(8) not null,
money float(10,2) default 0
);
set autocommit = 0;# 关闭自动提交 /*set autocommit = 1 自动提交*/
insert into account values('6ab71673-9502-44ba-8db0-7f625f17a67d','1234567890','张三',1000);
insert into account (id,card_id,name) values('9883a53d-9127-4a9a-bdcb-96cf87afe831','0987654321','张三');
#要么提交
commit;
#要么回滚
rollback;
了解了这么多,那什么是事务呢?
当执行一组DML操作时,为了确保数据的完整性和一致性,避免数据库产生错误数据,就需要通过事务(Transaction)使该组DML操作同时成功或失败。
举个例子:
一个人有两张银行卡,在这两张银行卡中来回转账(不考虑手续费),那不管转多少次,两张卡的总额是不会变的。也就是说转账必须两张卡一个增加,一个减少。或者说转账时两张卡必须同时成功或同时失败,不能只有一个成功(或失败)。
那如何操作呢?
在执行一组DML操作前,先执行set autocommit = 0
,再执行该组DML操作,最后再执行commit;
或rollback;
操作。
在开发中,我们不会在数据库操作系统中去操作数据库,通常都是用各种编程语言去操作,那如何用Java语言区操作呢?
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Test {
public static boolean Batch(String ...sqls) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver");//1、加载驱动
String url = "jdbc:mysql://127.0.0.1:3306/test";
connection = DriverManager.getConnection(url, "root", "root");//2、获取链接
connection.setAutoCommit(false);//此处是 关闭自动提交 sql语句
statement = connection.createStatement();//3、创建语句
for (String sql : sqls) {
statement.addBatch(sql);//将sql语句一条一条地插入
}
statement.executeBatch();//批量处理sql语句
connection.commit();//若上面的所有sql语句都执行成功,则提交
return true;
} catch (Exception e) {
try {
if (connection != null) {
connection.rollback();//若有数据出错,则将数据回滚
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();//处理其他异常
} finally {//释放资源
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
public static void main(String[] args) {
Test.Batch("update account set money=money-100 where card_id= '1234567890'","update account set money=money+100 where cad_id= '0987654321'");
}
}
上面的代码可以保证,当一组DML操作中有一句DML是错误的,则整组DML都不会提交,从而保障了数据的完整性和一致性。
让我们来总结一下事务的四大特性(ACID):
ACID | 定义 | 举例 |
---|---|---|
原子性(Atomicity) | 化学中的原子指不可再分的基本微粒,数据库中原子性强调事务是一个不可分割的整体,事务开始后所有操作要么全部成功,要么全部失败,不可能停滞在中间某个环节。如果事务执行过程中出错就会回滚到事务开始前的状态,所有的操作就像没有发生一样不会对数据库有任何影响。 | 无 |
一致性(Consistency) | 事务必须使数据库从一个一致性状态变换到另一个一致性状态,即一个事务执行之前和执行之后都必须处于一致性状态。 | 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还是5000,这就是事务的一致性。 |
隔离性(Isolation) | 当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离 | 比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转入钱。(占着茅坑不让别人用) |
持久性(Durability) | 一个事务一旦被提交,则对数据库的所有更新将被保存到数据库中,不能回滚。 | 无 |