最近刚开始研究并发,有讲的不对的,请大牛们指导修正
什么是并发:并发就是同时操作,比如两个人同时操作一条数据,一个人删除,另一个人更新
遇到并发时如何处理:一般会用到线程安全或者锁来解决
一、同时更新的解决方案(更新和删除混合操作时也适用)
1.通过更新锁来实现,在更新的sql语句中增加更新锁,这样某个人更新数据时,别人就不能更新了,如:(缺点,并发量很大时,等待时间较长)
begin tran
select * from address WITH (UPDLOCK) where [Name]='Z'
waitfor delay '00:00:10'
update address set [Name]='ZZ'
commit tran
Ps:如果另一个人更新数据则再加更新锁时,则会阻塞当前查询,直到其它连接释放更新锁。如果只是查询,不加更新锁,则直接可以读取更新锁的记录
2.使用NHerbinate来解决(缺点,并发量大时,等待时间较长)
var rc = GetSession().CreateQuery("from SerialNoGenerator g where id='1'").SetLockMode("g", LockMode.Upgrade).UniqueResult<SerialNoGenerator>();
rc.SerialNo += 1;
rc.Today = DateTime.Now;
session.Update(rc);
PS:LockMode.Upgrade解释是 不管缓存中是否存在对象,总是通过select语句到数据库中加载该对象,如果映射文件中设置了版本元素,就执行版本检查,比较缓存中的对象是否和数据库中对象的版本一致,如果数据库系统支持悲观锁(如Oracle/MySQL),就执行select...for update语句,如果不支持(如Sybase),执行普通select语句
3.悲观锁,修改时增加行锁和排它锁(更新时,其他人无法访问该数据,体验不好)
select top 1 Number from wf_Fault a with(rowlock,xlock)
update 记录
4.代码中线程同步(lock和一个静态型object变量进行配合,当前用户操作完,下个用户才能再进行操作),java中使用synchronized
lock (syncObj)
{
更新数据
}
5.通过时间戳实现(与日期和时间无关,是一个二进制数据)
更新时判断之前取出的时间戳与数据库中的时间戳是否一直
update testhxj set name='a2' where id=1 and timeversion=0x00000000001739A1
6.通过队列解决并发问题
二、插入的并发解决方案
1.通过数据库的约束来实现,比如定义一个ID列,为主键,当插入时,如果ID相同则会报异常
PS:
大型网站高并发,还要用到如下技术
1.高性能的服务器,高性能的数据库,高性能的web容器,
2.HTML静态化
3.图片服务器分离,文件服务器
4.数据库集群,库表散列
5.缓存
6.镜像
7.负载均衡