1、事务的四大特性:ACID
原子性:事务包含的操作,要么全部提交,要么全部回滚;
一致性:事务必须使数据库从一个一致性状态变到另外一个一致性状态,即数据库不论事务实行前后都必须处于一个一致性状态
例如:A B两个账户之间不论怎么转账,转账前后,两个账户的和相同;
隔离性:多个并发事务之间相互隔离;即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
持久性:一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
2、如果不考虑事务的隔离性,会发生的几种问题:
a、脏读:读取另一未提交事务的数据;
b、不可重复读(多次读取数据不一致):读取了另一提交事务的数据,不可重复读的是同一数据项。本事务范围内多次查询,却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了;
c、幻读:读取了另一提交事务的数据,幻读针对的是一批数据整体。
事务1:将数据库中一批数据的某一数据项为1的修改为2;查询修改结果;
此时,事务2:插入了一条该数据项认为1的数据,并提交;
事务1:又查询一次,会发现还有一行没有修改,即产生了幻读;
3、隔离级别及实现方式:
a、未提交读:
- 事务对当前被读取的数据不加锁;
- 事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级共享锁,直到事务结束才释放。
表现:
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,能读到事务2对该记录的修改版本,即使该修改尚未被提交。
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束。
b、已提交读:解决脏读,
- 事务对当前被读取的数据加 行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;
- 事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。
表现:
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,读到的只能是事务2对其更新前的版本,要不就是事务2提交后的版本。
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束。
c、可重复读:解决脏读、不可重复读,锁行
- 事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加 行级共享锁,直到事务结束才释放;
- 事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。
表现:
- 事务1读取某行记录时,事务2也能对这行记录进行读取、更新;当事务2对该记录进行更新时,事务1再次读取该记录,读到的仍然是第一次读取的那个版本。
- 事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束。
d、串行化:解决脏读、不可重复读、幻读,锁表;该级别要求事务被串行执行,就是说事务必须一个接着一个的执行而不能并发执行。应用程序在使用该级别时需要做好由于序列化失败而需要的重试操作。
- 事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;
- 事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。
表现:
- 事务1正在读取A表中的记录时,则事务2也能读取A表,但不能对A表做更新、新增、删除,直到事务1结束。
- 事务1正在更新A表中的记录时,则事务2不能读取A表的任意记录,更不可能对A表做更新、新增、删除,直到事务1结束。
4、MySql支持4中隔离级别,默认隔离级别是可重复读;innodb实现行锁是建立在索引项上的,没有索引就是表锁;
Oracle只支持 已提交读和串行化;
GreenPlum支持4中隔离级别,但内部只存在 已提交读、串行化 两个隔离级别
5、锁
参考:https://blog.youkuaiyun.com/learning_oracle_lh/article/details/46639557