首页 > 代码库 > 数据库之子查询和事务隔离级别
数据库之子查询和事务隔离级别
数据库大的知识点,特此补上。看的还是《漫画数据库》。
一、查询
如果要从一个数据库里面检索出某一字段为最大的数据项,那用什么方法呢?——其实用子查询就可以查到。
1)子查询是查询里面再嵌套查询。
people表:
如果我要查询年龄最大的那一行数据项。就可以使用子查询。
select * from people where age = (select max(age) from people);选出people里面的最大年龄,再选出年龄等于最大值的数据。
当然,还有另外一种方法。
select * from people order by age desc limit 1;通过从大到小的排序,并且限制数据为一条,那么就是最大的了。当然,有两条数据都是最大,那么这条语句就不完美了。
2)相关子查询
子查询内部嵌套的表格其实可以使用外部指定的表格,为相关子查询。这里说的不是外部和内部的表格一定是不同的。看例子。
假如现在选出年龄大于本国平均年龄的人,单单用子查询是查不了的,因为我们需要每条数据的国家都和平均年龄的国家对应。
select * from people p where age>(select avg(age) from people where count ry = p.country);
选出平均年龄的时候,如果没有where country = p.country那么选出来的只是大于全部人的平均年龄的数据。
但是有了之后,假如选到country为a的数据,那就会根据a国家的平均年龄进行比较,最终得到结果。
灵活运用子查询功能是很强大的。
二、事务隔离级别
1)事务
既然谈到事务隔离级别,先要说明事务是什么东西,之前论坛一个老鸟也面试过别人这样的问题,
数据库进行数据的检索,插入、更新和删除,用户的一系列操作我们称为事务,最重要的一点,保证数据的一致性和完整性。
保证数据的一致性和完整性是怎么来的?其实数据库事务具有酸性。开玩笑,其实是ACID属性。
A,Atomicity,原子性,事务必须结束与提交或者回滚的任意一个任务。
C,Consistency,一致性,执行数据库事务不能破坏数据库的一致性,举个例子(你从银行取了1000元,那么其他关联表要跟着变)。
I,Isolation,隔离性,两个事务的执行互不干扰。
D,Durability,持久性,事务完成,便将更改持久保存于数据库,不会被回滚。
2)执行控制——利用锁
共享锁,一个事务读取数据时,可以加共享锁,就是其他事务只能读取数据,不能更改数据。
独占锁,一个事务更改数据时,可以加独占锁,就是其他事务不能读取数据,也不能更改数据。
3)隔离级别
笔试题中有考到,第一时间想到赃读,不可重复读这些。隔离级别的倒忘光了。
设定隔离级别后的现象。
先解释三个现象:
脏读:dirty read,事务1提交之前,事务2读取了1中的数据,1一旦回滚,2读取了不存在的数据的现象。
我本金10元,往银行存了10元,后面没存了,但是银行那边读多10元,并且按20元处理。
不可重复读:non-repeatable read,事务1读取时,事务2更新并提交,事务1再读取,发现前后数据不同。
银行查账单,发现你有10元,然后你取了10元出来,银行再查,发现余额为0。前后不同。
虚度(幻读):phatom,事务1检索多行数据,事务2插入符合检索条件的新数据,事务1第二次检索发现前后数据不同。
银行查询你的消费清单,你又跑去消费了,然后后面再查发现新消费的账单怎么不在第一次的查询里面,如幻影般消失。
read uncommited,读未提交,以上三种现象都可能会发生。
read commited,读提交,防止脏读,脏读的问题解决就是提交完成的数据才给你读,不然一旦回滚,读出来就是错的。
repeateable read,重复读,防止脏读和不可重复读,不可重复读确实是发生在事务提交之后,问题在于读取的时候又有事务进行更改,所以问题解决是,一旦读取数据,就不让你在中途进行更新(MySQL默认级别)。
serializable,序列化,防止三种现象,幻读问题是,你事务进行检索数据之后,有人插入新的数据,后面再检索发现多了一条,好比银行小姐明明就看你消费100元,后面你又刷卡1000,后面查出来的总消费是1100,这是银行小姐就慌张了。
解决问题所在就是读取数据时还禁止其他事务进行插入或者删除。
这样看来,其实事务的隔离机制就是在控制事务后其他事务不能进行的操作,隔离级别越高,条件就越多,代价越大,但是也不会出现任何的三种现象。
4)悲观锁和乐观锁
悲观锁:给加载的数据加锁,不让其他事务更新和加载,这样,脏读和不可重复读都不会出现,虚读还是有的,因为还是可以插入或者删除数据。
乐观锁:并不会像悲观那样锁死,基于数据版本的记录,更新最后的更新,这样的话,其实不可重复读的问题还是存在的。
根据不同的数据库设计和性能要求进行所需要的隔离级别,才是最恰当的。
数据库之子查询和事务隔离级别