3.MySQL中的锁

  mysql中的锁分全局锁、表锁、行锁。

  1.全局锁

  当执行命令 flush tables with read lock (FTWRL) 即可对整库加锁,全局锁的用途是做整库备份。

  当数据库所用引擎支持事务时可用一致性视图来解决这个问题。即用可重复读隔离级别,当导数据之前开启一个事物即可做到数据的一致性。MySQL自带的逻辑备份命令是mysqldump, 当使

用 mysqldump --single-transaction 时即在导入数据前开启一个事物,来确保拿到一致性视图。

  注:(1)  set global readonly = true也可以锁住整库,但是风险很大,当客户端断开连接时锁不会释放。

    (2)  single-transaction 方法只适用于所有的表使用事务引擎的库。

  2.表级锁

  (1)表锁

    语法:lock tables 表名 read/write 即对表加读锁或写锁,用unlock tables 表名即可主动释放锁。

  (2)元数据锁(MDL)

    元数据锁不需要显示加上,在访问一个表时会被自动加上。对一个表做增删改查时加MDL读锁,对一个表的结构做更改时加MDL写锁,读锁之间不互斥,读锁和写锁、写锁和写锁之间互斥。

    

    如何安全的给一个小表加一个字段?

    分析:首先要解决长事务,因为长事务会占用MDL锁(可在information_schema中的innodb_trx表中查看),若有长事务可考虑暂停DDL,或者kill这个长事务。

       如果是个热点表(有频繁请求的表),则可用NOWAIT / WAIT N语法:alter table 表名 NOWAIT add column ; alter table 表名 WAIT N add column;

  3.行锁

    两阶段锁协议:在Innodb事务中,行锁是在需要的时候加上,等事务结束的时候才释放。

    如果在一个事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁往后放,如电影院购票场景,把修改影院账号余额的操作放在最后。

    死锁解决方案:

    (1)超时等待:

      查看超时时间:show variables like "innodb_lock_wait_timeout",默认是50s。

      设置超时时间:set  innodb_lock_wait_timeout = 50;

    (2)死锁检测:

      innodb_deadlock_detect默认设置为on,开启死锁检测。死锁检测会占用额外资源,怎样解决这种热点行更新导致性能问题呢?

      a.确定业务在数据库层不会有死锁发生,可以直接关掉死锁检测;

      b.控制并发事物量:在并发访问进入innodb引擎之前对并发访问进行排队,可以用消息中间件处理,也可修改mysql源码处理(需DBA人员)。

    

posted @ 2019-06-17 20:19  曲项向天歌  阅读(210)  评论(0编辑  收藏  举报