工作两年了,这是第一次在csdn开始写博客,记录一下自己。
事务的定义
数据库事务(Transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
事务的特性
事务拥有四大特性,分别为原子性、一致性、隔离性、持久性:
1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
栗子:
就拿最经典的转账来举例子,A账户给B账户转账200元,那么就是A账户-200元,B账户+200元。如果这两条sql都执行成功,那么转账操作就会成功,如果有一条sql操作失败,那么转账操作就都失败了。
// 开启事务,这是推荐的操作
start transaction
update 账户表 set 金额 = 金额 - 100 where name = 'A';
update 账户表 set 金额 = 金额 + 100 where name = 'B';
if Error then
rollback
else
commit
2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。通俗的来讲就是数据执行前后数据需要保持一致。
栗子:
还是用转账案例来讲。账户A有1000元,账户B有1000元。账户A给账户B转账200元。sql执行完毕之后,那么账户A和账户B最后的总金额是2000元保持不变。
3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。通俗的来讲就是,多个事务并发执行的时候,一个事务不影响另一个事务的操作。比如要查看数据更新的状态,那么事务A将查看的数据是事务B更新之前或更新之后的数据,不会看到该数据中间的状态。
栗子:
账户A有1000元,账户B有1000元,账户C有1000元。在同一事务中,账户A给账户B转账200元,账户C给账户B转账100元。那么事务A去查询账户B的余额,只会看到账户B的余额为转账之前的1300元或者是转账之前的1000元,不会看到其他的结果。
4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
并发写事务会产生的问题
1、脏读:事务A读取了事务B中没有提交的数据。
栗子:
哈哈,还是转账的栗子。账户A中有1000元,开始事务A,账户A取走200元,没有提交,这时候切换到事务B中,事务B查看账户A余额,此时查看到账户A中的余额还是1000元,因为事务A没有提交,所以产生了脏读。
2、不可重复读:在一个事务里面读取了两次某个数据,读出来的数据不一致。
栗子:
还是这个栗子。事务A开启事务,查看账户A中的余额为1000元,此时切换到事务B中,事务B开启事务,对取走账户A中的200元,提交。此时切换到事务A中,查看到账户A余额为800元,事务A两次读取到的数据不一致。这就是不可重复读。
3、幻读:在一个事务里面的操作中发现了未被操作的数据。
栗子:
现在咱们换个栗子,事务A开启事务对A班的学生缴纳学费情况列表都改为已缴纳然后提交,切换到事务B中,给A班的学生列表中增加一个新入学的新生,这个学生当然是没有缴纳学费的了,然后提交,此时在切换回事务A中,查看学生缴纳学费信息情况,发现有一个学生没有缴纳,这就是幻读,就跟产生了幻觉一样。
事务的隔离级别
数据库的隔离级别有4个,由高到低分别是:
读未提交(Read uncommitted)、读已提交(Read committed)、可重复读(Repeatable read)、序列化(Serializable)。这四个隔离级别可以解决脏读,不可重复读和幻读等问题。
隔离级别 | 是否出现脏读 | 是否出现不可重复读 | 是否出现 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed(Oracle,sqlserver默认隔离级别) | × | √ | √ |
Repeatable read(Mysql默认隔离级别) | × | × | √ |
Serializable | × | × | × |
隔离级别和并发性能的关系:
事务的隔离级别越高,他们的并发性能越差
Mysql查看当前隔离级别
select @@tx_isolation;
mysql设置隔离级别
set session transaction isolation level 隔离级别