对于数据库并发访问,可能会出现的问题
下面会顺序解决这3个问题
首先:
mysql中查看事务的隔离级别:
命令:
select @@tx_isolation;
其中,事务隔离级别有4个等级
Serializable: 可以解决所有问题,但是会锁表
Repeatable read: 可以解决脏读,和不可重复读,但是不能解决虚读
read commited: 只能解决脏读,其他均无法解决
read uncommitted: 最低级别,均无法解决
如果不考虑事务的隔离性会出现 4种问题:
1.脏读:一个事务读取到了另一个未提交的事务
2:不可重复读:两次读取的数据不一致 (update)
3. 虚读(幻读):两次读取的数据不一致 (insert ,delete)
4:丢失更新:两个事务对同一记录进行操作后,后提交的事务,将先提交的事务的数据修改了
当出现了上述问题,就要对事务设置隔离级别了
mysql 的事务隔离级别默认是:
repeatable read
Oracle 默认事务隔离级别是 read Commited
mysql 中设置事务隔离级别的命令
set session transaction isolation level
其中:
set read uncommitted 级别的话,是最不安全的
在这个级别中,你设置了 autocommit =0 ,如果你没有commit上去,所有用户也一样能读取到你未提交上的数据
因此,这个最低级别的没用
一般用第二,三个
先看 第三个,也就是 Oracle中默认的事务隔离级别
read commited ,只读取已经提交的数据
set session transaction isolation level read committed;
设置成 read commited就可以解决脏读的问题了,也就是只是读取已经 commit了的数据
这里开了两个 cmd窗口演示一下,原先数据库 是 500,右边客户将所有数据修改为100,这个时候左边客户查询一下,发现还是500,说明只能读取已经提交了的数据,没有提交了的无法读取,这时右边将数据commit一下,左边再来查询,即可读取到数据为100
那么,新的问题来了!
什么是不可重复读?
不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。原因是别的一部分事务修改了数据提交之后,这个时候该用户过来读取到新的数据,这就导致了不可重复读
要求:
接近方法,将事务隔离级别修改为可重复读:
注意:可重复读和脏读的区别:
脏读是读到了未提交的数据(有其他用户在更改数据),而不可重复读读的是已经提交的,但是违反了事务的一致性要求.
修改为可重复读,没法解决幻读的问题
幻读与不可重复读
事务的四大特性:1.原子性,2.一致性,3.隔离性,3.持久性
一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定
下面看一篇不错的文章
文中,将事务等级修改成了可重复读,于是 tom 可以成功付款1000块钱,而tom的妻子也拿走了 3000块钱
那么,就引发了另一个问题了,repeatable read没办法解决 丢失更新和幻读
原因: 它只是一个隔离级别,它能够隔离到解决 脏读和不可重复读
但是,解决丢失更新的话要用到锁才可以
下面是最高级别:
也就是串行读:
相当于单线程,第一个事务没执行完,没办法执行第二个事务,也就是没法同时进行,用锁表的方法解决了所有的问题