mysql的锁--行锁,表锁,乐观锁,悲观锁
2016-08-02 20:31
525 查看
一 引言--为什么mysql提供了锁
最近看到了mysql有行锁和表锁两个概念,越想越疑惑。为什么mysql要提供锁机制,而且这种机制不是一个摆设,还有很多人在用。在现代数据库里几乎有事务机制,acid的机制应该能解决并发调度的问题了,为什么还要主动加锁呢?
后来看到一篇文章,“防止更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁来解决”。瞬间,世界观都崩塌了。非常不敢相信,于是自己写了代码检验一下。
数据库表是这样的。用count字段来做100次累加。
View Code
任务类里就有比较多要注意的
a. 为了不断的重试,用了一个while。因为while的终止条件一般要读了数据后才知道,所以while只放了try_times,把结束条件放在了里面的if。
b. 在while里的每一次循环就重新起一个事务。因为更新失败我们要回滚的。下一次要重起一个。
c. 这里的事务执行条件,能执行且需要执行。比如id=1的记录被删掉了,那就不能执行了;需要执行,比如程序为了把商品记录status由未上架改为已上架,但发现已经被改了,那就不需要执行。可想而知,在多线程条件每次都要判断的。
d. try_times这个东西还是设置一下。至于设多少,要看并发量。
e. 每次更新,都要检测一次冲突
f. 冲突了,要睡一阵子再重试,避开冲突。怎么设置这个值,我突然想起计网的拥塞控制,说笑的~
顺手做了个小实验,还是执行100次,冲突睡眠100ms,
总结一下:
乐观锁更适合并发竞争少的情况,最好隔那么3-5分钟才有一次冲突。当并发量为10时就能明显感觉乐观锁更慢;
上面只是一读一写。考虑如果一个事务中有3个写,如果每次写都是九死一生,事务提交比小蝌蚪找妈妈还难,这时就更要考虑是不是要用乐观锁了。
但是,当分布式数据库规模大到一定程度后,又另说了。基于悲观锁的分布式锁在集群大到一定程度后(从几百台扩展到几千台时),性能开销就打得无法接受。所以目前的趋势是大规模的分布式数据库更倾向于用乐观锁来达成external consistency。
如果对乐观锁和悲观锁的选择还不清楚,看这篇
五 待更
mvcc:http://blog.csdn.net/chen77716/article/details/6742128
意向锁,间隙锁,加锁的查看
参考:
数据库锁协议等原理:http://blog.csdn.net/gklifg/article/details/38752691
InnoDB的几种锁:http://www.cnblogs.com/chenqionghe/p/4845693.html
InnoDB的几种锁:http://blog.csdn.net/xifeijian/article/details/20313977
最近看到了mysql有行锁和表锁两个概念,越想越疑惑。为什么mysql要提供锁机制,而且这种机制不是一个摆设,还有很多人在用。在现代数据库里几乎有事务机制,acid的机制应该能解决并发调度的问题了,为什么还要主动加锁呢?
后来看到一篇文章,“防止更新丢失,并不能单靠数据库事务控制器来解决,需要应用程序对要更新的数据加必要的锁来解决”。瞬间,世界观都崩塌了。非常不敢相信,于是自己写了代码检验一下。
数据库表是这样的。用count字段来做100次累加。
public class TestLockOcc { public static void main(String[] args) throws InterruptedException { //创建线程池,里面有10个线程,共执行100次+1操作 final int THREAD_COUNT=10; final int RUN_TIME=100; ExecutorService threadPool=Executors.newFixedThreadPool(THREAD_COUNT); //用CountDownLatch保证主线程等待所有任务完成 CountDownLatch count=new CountDownLatch(RUN_TIME); for(int i=0;i<RUN_TIME;i++) threadPool.execute(new LostUpdateOcc(count)); threadPool.shutdown(); count.await(); //提示所有任务执行完 System.out.println("finish"); } }
View Code
任务类里就有比较多要注意的
a. 为了不断的重试,用了一个while。因为while的终止条件一般要读了数据后才知道,所以while只放了try_times,把结束条件放在了里面的if。
b. 在while里的每一次循环就重新起一个事务。因为更新失败我们要回滚的。下一次要重起一个。
c. 这里的事务执行条件,能执行且需要执行。比如id=1的记录被删掉了,那就不能执行了;需要执行,比如程序为了把商品记录status由未上架改为已上架,但发现已经被改了,那就不需要执行。可想而知,在多线程条件每次都要判断的。
d. try_times这个东西还是设置一下。至于设多少,要看并发量。
e. 每次更新,都要检测一次冲突
f. 冲突了,要睡一阵子再重试,避开冲突。怎么设置这个值,我突然想起计网的拥塞控制,说笑的~
顺手做了个小实验,还是执行100次,冲突睡眠100ms,
总结一下:
乐观锁更适合并发竞争少的情况,最好隔那么3-5分钟才有一次冲突。当并发量为10时就能明显感觉乐观锁更慢;
上面只是一读一写。考虑如果一个事务中有3个写,如果每次写都是九死一生,事务提交比小蝌蚪找妈妈还难,这时就更要考虑是不是要用乐观锁了。
但是,当分布式数据库规模大到一定程度后,又另说了。基于悲观锁的分布式锁在集群大到一定程度后(从几百台扩展到几千台时),性能开销就打得无法接受。所以目前的趋势是大规模的分布式数据库更倾向于用乐观锁来达成external consistency。
如果对乐观锁和悲观锁的选择还不清楚,看这篇
五 待更
mvcc:http://blog.csdn.net/chen77716/article/details/6742128
意向锁,间隙锁,加锁的查看
参考:
数据库锁协议等原理:http://blog.csdn.net/gklifg/article/details/38752691
InnoDB的几种锁:http://www.cnblogs.com/chenqionghe/p/4845693.html
InnoDB的几种锁:http://blog.csdn.net/xifeijian/article/details/20313977
相关文章推荐
- mysql 锁机制 悲观锁与乐观锁
- MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等) - lishenglong666的专栏 - CSDN博客
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
- MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
- mysql 数据库的悲观锁 乐观锁
- mysql乐观锁和悲观锁
- mysql 悲观锁 乐观锁
- MySQL学习之锁(行锁、表锁、页锁、乐观锁、悲观锁等)
- mysql乐观锁和悲观锁
- MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
- Mysql 乐观锁 悲观锁
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
- MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
- mysql-mysql悲观锁和乐观锁
- 事务 四大特性 mysql 悲观锁与乐观锁
- MySql中的悲观锁和乐观锁
- mysql悲观锁与乐观锁
- mysql悲观锁以及乐观锁总结和实践