MyISAM锁 与 INNODB锁

2 篇文章 0 订阅

本文双引号内容为重要点 ,在markdown中双引号的内容为红色

一 MyISAM锁

表锁

表锁:不会出现死锁,容易发生锁冲突,并发低

(1) 表锁的两种模式: "表共享锁 (Table Read Lock)" 和 "表独占写锁 (Table Write Lock)"

 注: 
    共享锁,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
    独占写锁,则会阻塞其他用户对同一表的读和写请求;
    读操作和写操作之间,以及写操作之间是串行的;
    "当一线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。"
    
(2) 如何加锁:MyISAM在sql查询时会将涉及到的表加上读锁,在执行插入或更新时会加写锁。用户也可以用LOCK TABLE去显式的加锁。

 示例:
     LOCK tables orders read local,order_detail read local;   加锁
     SELECT SUM(total) FROM orders;
     SELECT SUM(subtotal) FROM order_detail;
     UNLOCK tables;                                           解锁
     
     "local"选项作用是满足MYISAM并发插入条件的情况下,允许其他用户在表尾插入记录,若不加"local"选项,则不允许。
 注:
    显式的加锁一般是应用于:需要在一个时间点实现多个表的一致性读取。不然的话,可能读第一个表时,其他表由于还没进行读操作,
没有自动加锁,可能数据会发生改变。并且显示加锁后只能访问加锁的表,不能访问其他表。
 

并发锁

    并发锁:在一定条件下MYISAM支持查询与插入并发执行
    条件:MYISAM引擎系统变量concurrent_insert
    值:
        0 不允许并发插入
        1 进程在读取表的时候允许另一个进程在表尾插入记录, MySQL默认设置
        2 无论MYISAM表中有没有空洞,都允许在表尾插入记录,也允许并发插入记录表    
             
    空洞:指表中的数据出现断层

锁的调度情况

默认情况:
        MyISAM存储引擎的读和写锁是互斥,读操作是串行的。在没有做任何调整的情况下,写进程会比读进程
    优先获得锁,即使读进程优先于写进程请求。

    大量的更新操作会造成查询操作很难获取到读锁,从而导致永远阻塞情况。
    
    "MySQL认为写请求一般比读请求重要"
    
调整方式:
    通过"low-priority-updates" 参数,使MyISAM引擎默认给予读请求以优先的权利。
    通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
    通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级

二 INNODB锁

行锁

行锁:会出现死锁,发生锁冲突几率低,并发高

"mysql的行锁是通过索引加载的,要是对了的sql语句没有走索引,则会全表扫描,行锁无法实现,取而代之的是表锁。"

(1) 行锁的两种模式: "共享锁(S)" 和 "排他锁(X)"
    
    注:
        共享锁(S):当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,
        但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。

        排它锁(X):当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。
        另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁,这两种"意向锁都是表锁"。
        
        衍生:
            意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
            意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
        
    示例:
         select math from zje where math > 60 "lock in share mode";  共享锁
         select math from zje where math > 60 "for update";          排他锁
         
    重点:
        1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
        2.两个事务不能锁同一个索引。
            示例:
                事务A先执行:
                select math from zje where math > 60 for update;
                事务B再执行:
                select math from zje where math < 60 for update;
                这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞。
                但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。
        3.insert ,delete , update在事务中都会自动默认加上排它锁。
       

锁冲突

示例:
    事务A将某几行上锁后,事务B又对其上锁,锁不能共存否则会出现锁冲突。
   (但是共享锁可以共存,共享锁和排它锁不能共存,排它锁和排他锁也不可以)

死锁

示例:
    两个事务,事务A锁住了1~5行,同时事务B锁住了6~10行,此时事务A请求锁住6~10行,就会阻塞直到事务B施放6~10行的锁,
而随后事务B又请求锁住1~5行,事务B也阻塞直到事务A释放1~5行的锁。死锁发生时,会产生Deadlock错误。

问题

为什么表锁不会产生死锁?
答:锁对表进行操作,将全表锁住之后自然就不会产生死锁

乐观锁

    操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突。"(一般都需要自己去实现)"
    
    示例:
        下单操作包括3步骤:

        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}";

    注:实现乐观锁与实例中的红色字体相关

悲观锁

    操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,
这点跟java中的synchronized很相似,所以悲观锁需要耗费较多的时间。
    
    "共享锁和排它锁是悲观锁的不同的实现"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值