Mysql事务
1. 事务
简单来说,事务就是操作一系列事件,要么全部完成,要么全部不完成。典型例子为银行转账
(Innodb 才支持事务,默认REPEATABLE-READ,一般不需要修改,用了NEXT-KEY LOCK算法,不损失性能下避免幻读)
2. 特性(ACID)
原子性:一系列事件,要么全部完成,要么全部不完成
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)、级别越小,请求的锁越小
3. JDBC事例
账号1 转 账号2 人民币50元
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/test";
String username = "root";
String password = "";
Connection conn = (Connection) DriverManager.getConnection(url, username,password);
try{
//关闭自动提交
conn.setAutoCommit(false);
//账号1减去50
String sql1 = "UPDATE account SET money = money-50 WHERE id = 1";
PreparedStatement ps1 = conn.prepareStatement(sql1);
ps1.executeUpdate();
//报错
int a = 1 / 0;
//账号2加50
String sql2 = "UPDATE account SET money = money+50 WHERE id = 2";
PreparedStatement ps2 = conn.prepareStatement(sql2);
ps2.executeUpdate();
//提交
conn.commit();
//关闭事务,防止后面使用不提交
conn.setAutoCommit(true);
} catch (SQLException e) {
try {
//回滚
conn.rollback();
conn.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally {
conn.close();
}
}
4. 事务隔离级别
Read uncommitted:级别最低,什么都避免不了
Read committed:可避免脏读
Repeatable read:可避免脏读,不可重复读
Serializable:可避免脏读,不可重复读,虚读
Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降
建议细看:事务隔离级别的图文
脏读:一个事务读取到另外一个事务未提交的数据
丢失修改:两个事务同时访问数据,第一个修改数据后,第二个也修改数据,导致第一个修改数据丢失
不可重复读:第一个事务读取到数据后,另外一个事务修改数据并提交后第一个事务再次读取,第一个事务两次读取的数据不一样
幻读:在一个事务内读取到了别的事务插入的数据,导致前后读取不一致,和不可重复读差别在于修改和增删
5. 查看与修改事务级别
//查看当前事物级别:
SELECT @@tx_isolation;
//设置事务级别
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]