美文网首页
mysql的悲观锁和乐观锁

mysql的悲观锁和乐观锁

作者: bug去无踪 | 来源:发表于2020-01-22 16:24 被阅读0次

    一、乐观锁:直白的说就是乐观的认为程序不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现

    解决办法:
    1.加版本号
    update tbl1 set name=XXX, version=version+1 where game_id=XXX and version=XXXX; //如果版本号和之前查到的不一样,说明有其他进程对该数据进行了修改
    2.CAS操作
    内存值、预期值、更新值 (直白就是sql语句where后面的条件就是预期值(game_id,log_date),数据库中的值就是内存值(game_id,log_date),要更新的值就是更新值)update tbl1 set name=XXX where game_id=XXX and log_date=XXXX;

    二、悲观锁:总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在Java中,synchronized的思想也是悲观锁。

    注意:要使用数据库的悲观锁,我们必须关闭mysql数据库的自动提交事物属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
    悲观锁分为两种:共享锁(读锁)和排它锁(写锁)

    共享锁是其它事务可以读但是不能写:实现方式是在sql后加LOCK IN SHARE MODE,比如SELECT ... LOCK IN SHARE MODE

    排他锁是只有自己的事务有权限对此数据进行读写:实现方式是在sql后加FOR UPDATE,比如SELECT ... FOR UPDATE ,即在符合条件的rows上都加了排它锁,其他session也就无法在这些记录上添加任何的S锁或X锁。
    通过对比,发现for update的加锁方式无非是比lock in share mode的方式多阻塞了select...lock in share mode的查询方式,并不会阻塞快照读

    从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适

    使用select…for update会把数据给锁住,不过我们需要注意一些锁的级别,MySQL InnoDB默认Row-Level Lock,所以只有「明确」地指定主键,MySQL 才会执行Row lock (只锁住被选取的数据) ,否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。

    悲观锁:总是认为会产生并发问题,其他线程会改变数据,共享锁和排他锁 (必须关闭数据库字自动提交事物,必须明确的指定主键,否则锁会锁住整张表)

    相关文章

      网友评论

          本文标题:mysql的悲观锁和乐观锁

          本文链接:https://www.haomeiwen.com/subject/loauzctx.html