一.什么是事务?
事务,由一个有限的数据库操作序列构成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
假如A转账给B 100 元,先从A的账户里扣除 100 元,再在 B 的账户上加上 100 元。如果扣完A的100元后,还没来得及给B加上,银行系统异常了,最后导致A的余额减少了,B的余额却没有增加。所以就需要事务,将A的钱回滚回去,就是这么简单。
二.事务的四大特性
- 原子性: 事务作为一个整体被执行,包含在其中的对数据库的操作要么全部都执行,要么都不执行。
- 一致性: 指在事务开始之前和事务结束以后,数据不会被破坏,数据必须处于一致状态。假如A账户给B账户转10块钱,不管成功与否,A和B的总金额是不变的。
- 隔离性: 多个事务并发访问时,事务之间是相互隔离的,一个事务不应该被其他事务干扰,多个并发事务之间要相互隔离。。
- 持久性: 表示事务完成提交后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。
三.事务并发存在的问题
1. 更新丢失: 两个事务都同时更新一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了。
2. 脏读: 一个事务读取到了另一个事务未提交的数据操作结果。
3. 不可重复读:一个事务对同一行数据重复读取两次,但是却得到了不同的结果
(1)虚读:事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。
(2)幻读:事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据(这里并不要求两次查询的SQL语句相同)。
四、事务的隔离级别
- 未授权读取, (读未提交)(Read Uncommitted): 允许脏读取、不可重复读,不允许更新丢失。一个事务会读到其他事务未提交的数据的,即存在脏读问题。事务B都还没commit到数据库呢,事务A就读到了,感觉都乱套了。实际上,读未提交是隔离级别最低的一种。
- 授权读取, (读已提交) (Read Committed): 允许不可重复读,不允许脏读 隔离级别设置为读已提交(READ COMMITTED) 时,已经不会出现脏读问题了,当前事务只能读取到其他事务提交的数据。 提交读的隔离级别会有什么问题呢?
在同一个事务A里,相同的查询sql,读取同一条记录(id=1),读到的结果是不一样的,即不可重复读。所以,隔离级别设置为read committed的时候,还会存在不可重复读的并发问题。
- 可重复读(Repeatable Read): 不允许不可重复读取、脏读, 但有可能出现幻读
- 序列化(Serializable):(串行化) 提供严格的事务隔离. 当数据库隔离级别设置为serializable的时候,事务B对表的写操作,在等事务A的读操作。其实,这是隔离级别中最严格的,读写都不允许并发。事务串行化顺序执行,可以避免脏读、不可重复读与幻读。它保证了最好的安全性,性能却是个问题~
- DEFAULT: PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别. Mysql默认:可重复读. Oracle默认:读已提交
五、在MySQL数据库中查看当前事务的隔离级别:
select @@tx_isolation;
设置全局隔离级别为读提交级别:
mysql> set global transaction isolation level read committed;
在MySQL数据库中设置事务的隔离 级别:
set [glogal | session] transaction isolation level 隔离级别名称;
set tx_isolation=’隔离级别名称;’