本文概览:介绍通过”select …for update”实现悲观锁。
1 介绍
悲观锁,就是在一个事务中,对某一行数据进行加行锁,其他事务不能在对此行数据修改,只能等待到该事务进行了提交。
2 实现
1、实现
可以通过在事务中执行”slect .. for update”、”update …” 、” insert ….”三种语句来实现(前提必须在一事务内进行):
1 2 3 4 5 6 7 8 9 10 11 12 |
# 开启事务 begin; # 通过select...for update行锁 select ... ....for update # 通过update上行锁 update ... where ... # 通过insert上行锁 insert ... # 提交事务 commit; |
2、举例
第一步 在终端1,执行
1 2 3 4 5 6 7 8 9 10 |
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from bank_info where id =1 for update; +----+-----------+--------------+----------+-------------+----------+---------------------+---------------------+ | id | bank_code | name | easy_pay | bank_mobile | net_bank | create_time | update_time | +----+-----------+--------------+----------+-------------+----------+---------------------+---------------------+ | 1 | 4001 | 中国银行 | 5 | 1 | 1 | 2017-07-23 11:10:45 | 2017-06-01 00:00:00 | +----+-----------+--------------+----------+-------------+----------+---------------------+---------------------+ 1 row in set (0.00 sec) |
第二步 在终端2,执行如下更新命令,此时会被hang住,等待终端1释放锁。
1 |
mysql> select * from bank_info where id =1 for update\G; |
第三步 在终端1,执行commit操作,此时在终端2就会显示出结果
1 |
mysql> commit; |
3、总结
- 总结1 在上面测试中,如果终端1,执行了select …. for update,此时如果只是在终端2执行 “select * from where …”而不是 “select .. for update”,此时会立刻返回结果,不会阻塞。
3 乐观锁和悲观锁比较
1 、查询
悲观锁在锁的时候。都是可以支持查询的。所以两种锁都不会影响查询。
2、更新时
并发不大的情况下,其实二者更新一样,但是在并发写比较多时候,乐观锁更新失败会很多。
3、总结
还是使用悲观锁。
4 应用
1、购买产品时限制人数
2、更新用户理财持仓
5 优化
对于某些情况下,在高并发情况下可能会存在select for update阻塞在同一条数据上,赞成数据库连接池被占满。比如 一个产品的库存记录,同时又多笔订单来更新库存。
解决这种问题,可以在select for update之前增加一个分布式锁。参考
(全文完)