各位,问个我昨天面试的问题。

首先感慨现在面试真的很难,要求都很高,而且要求的范围都很广,而且都要求你有经验。

昨天参加一个公司的面试:先大致说下我的面试过程。

面试官首先面试了一大串的技术,Struts,hibernate,Spring的一些技术细节。我只简单用过一些Struts和Hibernate,Spring在自我研究阶段,没有项目经验。所以这个环节我回答的我自己感觉很不好。(当时就觉得肯定没戏了,想走,但面试还在继续,只有硬着头皮坚持下去。)

接着,那人问了对SQL掌握的如何,我说常用的SQL语句我都会写。然后他问了一些具体细节。接着问我是否写过存储过程,我说写过,但不是很多。

接着,他问我有没有写过多线程的应用,以及一些细节。我说项目中用的不多,具体写的也不多。但原理我是理解的。

接着,他问我多用户并发访问下,事务处理的一些具体细节。这个是我比较弱的一个方面,我胡乱说了一通,自己都不知道怎么说的。

接着,他问了我数据缓存的问题。问我是如何处理的。我说我们一般是把常用的变化不频繁的数据封装在CACHE里。在系统启动的时候就栽入。然后他问我:那你如何保持缓存信息的及时更新?我说:我是在原对象的一些增加删除编辑方法中,触发缓存信息的重新生成。然后他问我:那你这样如何避免脏读呢?对于这个问题,我自己感觉自己懂得不是很多,请BANQ大师或其他的朋友告知下,如何避免在缓存中的信息脏读呢?

[该贴被rocwo于2007年06月04日 09:31修改过]

看看sql的锁原理。

Each DB , their transaction systems are different.
for example Oracle doesnt have lock for read,write .
so even you read data from DB, use transaction.
then you dont have any dirty read problem.

for example Oracle doesnt have lock for read,write
写怎么可能不上锁呢

s锁,x锁这是理论的东西,只要是关系型数据库必然有,shanghaimin 好好看一下资料。

在数据库层面,一般都是有4层隔离级别的,通过修改配置就可以解决脏读等问题.好象默认的就不存在这个问题.

你所说的应该是cache的脏读问题吧.
使用cache前必须弄明白几个基本问题

什么样的数据适合存放到缓存中?
1 很少被修改的数据
2 不是很重要的数据,允许出现偶尔并发的数据
3 不会被并发访问的数据
4 参考数据
不适合存放到第二级缓存的数据?
1 经常被修改的数据
2 财务数据,绝对不允许出现并发
3 与其他应用共享的数据。

cache有自己的缓存策略,类似数据库的隔离级别
象ehcache就有read-write|nonstrict-read-write|read-only

配置cache后,会先上cache找数据,找不到才跑数据库找.一个绝对不允许出错,或者频繁更改的数据,不应该使用cache策略的
数据库范式是在空间与时间取平衡点,cache策略也一样,是在性能与正确性之间取平衡点

谢谢大家的热心回答。

那么我可以说那个面试官问的问题纯粹是唬人的了。

因为无法做到使用缓存又能百分百避免cache的脏读。

就我最近的学习来说,用cache完全可以避免脏读
以hibernate来说,他设有悲观锁定和乐观锁定
悲观锁定利用sql中的串行更改方式进行数据库读取和更改
乐观锁定所推荐的模式就是版本更新模式。在数据库中设立version项,进行版本更新检查
能够有效的防止脏读。~
呵呵。。

Maybe I have to rephrase my answers.


if Oracle block read and write, so we will never have diry read.
Because everything is serialized. if more than one user come to access the database, we dont need to put transaction to protect our code. Because finally the database will serialize everything.

Don't you guys think this will be the solution for Oracle.
Oracle is famous for its concurrency access.

on the contrary, to avoid dirty read,non-repeatable read,phantom read, we must use transaction to protect our sql execution in java,even for query. let alone you write sth in db concurrently.

Then you definitely need to transact your "write" SQL in java.

If we go deeper into Oracle, even two transacted "SQL write" statements try to access the same row, which will still result into
an error. of coz you need to set Oracle isolation level as SERIALIZABLE.

This is what I mean so-called no "write" lock.

rainerWJY 你的cache只是针对hibernate的2级cache来说,对于一些业务层的属性缓存呢?你怎么用锁机制来保证?你必须在更新数据库数据的时候,同步更新缓存数据才行,如果数据更新频繁,系统效率反倒降低.cache这东西还是得看应用场合的
我觉得乐观锁应该是保证数据库的数据操作的安全性,而不是脏读吧.


加锁的语句 如果该数据已有S锁 如果该数据已有X锁 如果该数据已有U锁 该锁存在的锁粒度
共享锁
(S)
select 加另外一个S锁 等待锁释放 加另外一个S锁 行、页、表
排它锁
(X) insert, update*, delete* 等待锁释放 等待锁释放 等待锁释放 行、页、表
更新锁
(U) update, delete 加另外一个U锁
等待锁释放 等待锁释放 行、页


隔离级别 0
允许脏读: 忽略排它锁和读取未提交的事务所涉及的数据
允许非重复读: 在事务中, 当select语句执行完成后, 其加到数据上的共享锁将被释放.
允许幻像读: 同上原理

隔离级别 1
不允许脏读: select语句在读取数据之前, 如果该数据上有排它锁, 则需要等待释放排它锁后才能进行.
允许不可重复读:
允许幻像读:

隔离级别 2
不允许脏读:
不允许不可重复读: select操作所加上的行级共享锁直到事务完成才会被释放
允许幻像读: 由于是行级共享锁, 所以不能保证其他行的插入或修改使新的记录符合先前的条件.


隔离级别 3
不允许脏读:
不允许不可重复读: select操作所加上的页级或表级共享锁直到事务完成才会被释放
不允许幻像读:

[该贴被gougou3250于2007年06月06日 23:51修改过]

数据库的处理的串行化不是用户级的,读的锁是可以共享的。不过对于大内存的频繁更新实在不适合使用cache。

If A is doing a transaction and not yet commited, is it possible for B to read his data in DB?

Answer this question

and I will tell you how it works inside Oracle.

btw: assume A and B are accessing the same data in DB

to lphq,

if read lock can be shared, which means read doesnt block write, then for the normal DB, the dirty read will happen?

but how does oracle avoid that happened?

togougou,

in fact, the concept is same for the concurrency control
whatever it happened in memory or in DB domain.
in java, it is thread-safe problem if you have only one machine.
in DB, it is a concurrency access issue for read and write.

Normal DB they block one operation against other to avoid dirty read, repeatable read,phantom read.
But Oracle has better solution to solve that---multi-version control.
in fact, it is the same solution also applying for SVN.