zoukankan      html  css  js  c++  java
  • mysql的锁机制,以及乐观锁,悲观锁,以及热点账户余额问题

    mysql的简单锁机制。

    myisam

    1、只支持表级锁,所以经常更新的表结构不适宜用。

    2、select也会产生锁表

    innodb

    1、支持事务,行级锁,表级锁,执行行级锁的前提是sql语句的索引有效,否则,执行表级锁。

    2、不存在字段锁问题,直接锁行的。

    3、select不会请求锁,自然也不会产生锁表,update,insert,delete都会请求锁,所以会产生锁表

    执行串行并行问题

    1、同一个connection下,串行执行。

    2、不同connection下,并行关系。验证方法:执行一个慢查询中间执行一个快查询便可验证

    3、所以java这种非页面级的mysql连接,一般有连接线程池。以提高并行执行效率。

    4、但是从微观角度来说,所有执行都是串行的。譬如自增id永远不会重复出现一样。

    像php这种页面级的mysql连接,则不存在连接线程池问题,因为每个页面过来其实都是新开一个线程的问题。

    事务的乐观锁和悲观锁

    悲观锁:

    begin;/begin work;/start transaction; (三者选一就可以)
    //1.查询出商品信息
    select status from t_goods where id=1 for update;
    //2.根据商品信息生成订单
    insert into t_orders (id,goods_id) values (null,1);
    //3.修改商品status为2
    update t_goods set status=2;
    //4.提交事务
    commit;/commit work;
    

    我们使用了select…for update的方式,这样就通过开启排他锁的方式实现了悲观锁,id为1的 那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行, InnoDB默认行级锁。行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住,这点需要注意。悲观并发控制实际上是“先取锁再访问”的保守策略,则执行for update的时候锁定了t_goods表,也就是说没有commit之前已经锁表了,根据微观串行可知,是线程安全的。

    死锁:

    假如两个并行事务s1和s2,s1先锁定t1,s2先锁定t2,然后s1需要等待t2解锁,s2需要等待t1解锁。就陷入无限等待的情况。

    乐观锁:

    begin;

    1.查询出商品信息
    select (status,status,version) from t_goods where id=#{id}
    2.根据商品信息生成订单
    3.修改商品status为2
    update t_goods 
    set status=2,version=version+1
    where id=#{id} and version=#{version};
    commit;
     

    一般我们使用版本号的方式来实现乐观锁,乐观锁直到commit的时候才去锁定,乐观锁由于是commit才锁定,所以不存在死锁问题。但是也存在线程安全问题,假如两个connection实例,同时在commit之前修改了同一数据,commit先后的时候就会出现数据version不一致的问题。

     热点账户解决方案

     

  • 相关阅读:
    _I、_O、_IO的含义
    ARM启动代码中_main 与用户主程序main()的区别
    ARM汇编程序中的伪指令
    oracle密码过期问题
    等待界面-调转页面前button篇
    等待效果
    winfrom中Application.Restart()
    自动刷新处理
    泛微E8二次开发
    我的菜园子
  • 原文地址:https://www.cnblogs.com/zenghansen/p/7090310.html
Copyright © 2011-2022 走看看