1.开关事务
2.事务的四大特性
3.隔离性
4.锁机制
事务:逻辑上的一组操作,要么全成功,要么全不成功
1.开关事务
数据库:
start transaction
Rollback
Commit
JDBC:
conn.setAutoCommit(false);
conn.commit()
conn.rollback()
SavePoint sp = conn.setSavePoint();
conn.rollback(sp);
2.事务的四大特性
原子性,一致性,隔离性,持久性
(1).原子性:每个事务是不可分割的一个工作单位
(2).一致性:无论是否成功,数据库都是一个完整性的状态,即符合所以约束
(3).隔离性:一个事务不能被其他用户干扰
(4).持久性:一旦被提交,改变就是永久性的
3.隔离性
(1).使用场景:
两个线程同时查询,没有线程问题;
两个线程并发修改,肯定有线程问题,用锁机制;
一个查询一个修改,可能有问题
(2).一个查询一个修改会出现以下几种情况:
脏读:一个事务读取到另一个事务未提交的数据
不可重复读:在一个事务中,第一次和第二次读某一行数据,得到的结果不相同
虚读(幻读):一个事务读取到别的事务插入的数据,导致前后数据不一样
(3).针对不同(2)中情况需要设置不同的隔离性:
Read uncommitted:不防止任何问题
Read committed:可防止脏读
Repeatable read:可防脏读/不可重复读,不可防虚读
Serializable:可防所有问题
(4).Mysql跟Oracle的隔离性区别:
Mysql默认的隔离级别是Repeatable read
Oracle默认的隔离级别是Read committed
(5).查看当前的隔离级别:
select @@tx_isolation
(6).设置隔离级别:
set [global/session] transaction isolation level xxxx;
不写就是默认session,仅修改当前客户端和数据库,global是修改整个数据库
4.锁机制
对于一个查询一个修改,可以通过隔离性解决。对于同时修改,就需要锁机制来解决了。
(1).锁的概念和分类
共享锁:在非Serializable隔离级别下,做查询不加锁。在Serializable隔离级别下,做查询加共享锁
特点:共享锁之间可共存,共享锁不与排它锁共存
排它锁:无论在什么隔离级别下,做增删改都加排它锁
特点:排它锁和其他任何锁都不共存
(2).多次查询会不会造成问题?会。会造成更新丢失问题
情景:银行查询状态,如果是0,则往账户打钱,如果是1就不打钱。当客户因为网速原因点击多次时,多个线程并发查询到0,就会打钱多次。
解决方法:乐观锁,悲观锁
(3).乐观锁,悲观锁
悲观锁:认为每次都会造成更新丢失,每次查询都加排它锁
select * from demo for update(手动加排它锁)
乐观锁:认为每次查询不会造成更新丢失,用一个版本字段控制
update order set state = 1 and version = 1 where id=0 and version=0