14.mysql锁机制

MySQL锁机制

锁是计算机协调多个进程或线程并发访问某一资源的机制

例如在淘宝买商品的模型,只有一件商品时,如何解决谁买到商品的问题

这里要用到事务,先从库存表中取出物品数量,然后再插入订单,付款后插入付款表信息,

然后再更新商品数量,再这个过程中使用锁可以对有限的资源进行保护,解决隔离和并发的矛盾。

锁的分类
  1. 按数据操作的类型分

    • 读锁

      共享锁,针对同一份数据,多个读操作可以同时进行而不相互影响

    • 写锁

      排它锁,当前写操作未完成前,会阻断其他写锁和读锁

  2. 从对数据操作的粒度来分

    • 表锁

      偏读,偏向MyISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,发生锁冲突的概率大,并发度最低。

      #上锁
      #lock table 锁名字 read(write) 表名字2 read(write) 其它;
      show open tables;
      #解锁
      unlock tables;
      
      #exp : 读阻塞写的例子
      lock table mylock read;
      
      #session2可以读mylock,session1不能修改mylock,而且session1不能读被锁表之外的其他表,sessoin2,修改mylock时导致阻塞,
      update mylock set name='a2' where id=1;
      
      #exp : 
      lock table mylock write;
      #session1可以读、改锁定表mylock,但不可以读其他表,session2读写mylock被阻塞
      
      

      MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁。MyISAM的读写调度时写优先,不适合做写为主表的引擎。写锁后其他线程不能做任何操作,大量的更新会使查询很难得到锁。

      #分析表锁定
      show status like ‘table%’;

      Table_locks_immediate:产生表级锁定的次数,表示可以立即获取锁的查询次数

      Table_locks_waited:出现表级锁定争用而发生的等待次数

      读锁阻塞写,写锁都阻塞(不同事务间)

      共享锁(S锁)又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

      排他锁(X锁)又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

    • 行锁

      偏写,偏向InnoDB存储引擎(5.5版本以后默认引擎),开销大,加锁慢,会出现死锁,锁定粒度小,发生锁冲突的概率最低。

      CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

      读己之所写(不同session读到数据不一样)

      autocommit=0;
      #*****
      commit;
      

      提交更新以后,其他事务(行锁)的更新才可以正常(否则阻塞)。

      无索引行锁升级为表锁

#强制类型转换 ==>varchar 不写 ‘’ 例如:
update test_innodb_lock set a=41 where b=4000;
```

 #### 间隙锁
 
 幻读的问题存在是因为新增或者更新操作,这时如果进行范围查询的时候(加锁查询),会出现不一致的问题,这时使用不同的行锁已经没有办法满足要求,需要对一定范围内的数据进行加锁,间隙锁就是解决这类问题的。在可重复读隔离级别下,数据库是通过行锁和间隙锁共同组成的(next-key lock),来实现。
 
 ##### 间隙锁的危害
 
 当我们用范围条件而不是相等条件检索数据时,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的引索项加锁,对于键值在条件范围内但不存在的记录,叫做"间隙",InnoDB也会对这个“间隙”加锁,这种锁机制就是间隙锁(Next-Key锁)
 
 **造成在锁定的时候无法插入锁定值范围内的任何数据。**
 
 ```mysql
 update test_innodb_lock set b='0629' where a>1 and a<6;
 ```
 
 **如何锁定一行**
 
 ```mysql
 #for update
 select * from test where a=8 for update;
 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值