重新认识Mysql的MyISAM表锁(共享读独占写)(一、Mysql锁的概念和特点)在Mysql数据库中系统,不同的存储引擎支持不同的锁定机制。例如,MyISAM和MEMORY存储引擎使用表级锁。BDB使用页锁,也支持表级锁。InnoDB存储引擎支持行级锁和表级锁。默认情况下,使用行级锁。MySQL三种锁的特点大致可以归纳为:模式解锁、加锁速度、死锁、粒度、并发性能。概率最高,并发度最低。行级锁代价高昂且加锁速度慢;可能会出现死锁;加锁粒度最小,锁冲突概率最低,并发度也最高。页锁开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。本博客将记录MyISAM存储引擎中的表级锁(二)MyISAM表锁方式1.MyISAMLockRead(共享读)共享读:MyISAM表的读操作不会阻塞其他用户读同一个表表请求,但它会阻止对同一个表的写请求。操作命令//locklocktabletablenameread//unlockunlocktables实战场景:clientA:locktablerolesread;//读锁select*fromroleswhereid=1;//查询成功clientB:select*fromroleswhereid=1;//查询成功updaterolessetname='root';//卡住,等待释放锁ClientA:unlocktables;//解锁clientB:updaterolessetname='root2';//更新成功2.MyISAMLockWrite(读写)独占写:MyISAM表的写操作会阻塞其他用户对同一张表的读写操作。操作命令//locklocktabletablenamewrite//unlockunlocktables实战场景:clientA:locktableroleswrite;//writelockselect*fromroleswhereid=1;//查询成功更新角色setname='admin'whereid=1;//更新成功clientB:select*fromroleswhereid=1;//卡住了,等待锁释放ClientA:unlocktables;//解锁clientB:select*fromroleswhereid=1;//查询成功(3.)通过查看系统table_locks_waited(表锁等待,无法立即获取数据)和table_locks_immediate(立即获取锁的查询次数)状态变量分析表级锁竞争showstatuslike'%table_lock%'分析:如果Table_locks_waited值比较高,说明表级锁竞争严重,性能问题,高并发,优化。(4)关于MyISAM锁调度MyISAM存储引擎读写锁是互斥的,读操作是串行的。那么,如果一个进程对MyISAM的某个表请求读锁,而另一个进程也对同一张表请求写锁,MySQL是如何处理的呢?答案是写进程先获取锁。不仅如此,即使读进程先请求先到锁等待队列,写请求晚到,写锁也会插在读请求之前!这是因为MySQL认为写入请求通常比读取请求更重要。这也是MyISAM表不适合有大量更新操作和查询操作的应用的原因,因为大量的更新操作会使查询操作很难获得读锁,可能会永远阻塞。这种情况有时会变得非常糟糕!幸运的是,我们可以通过一些设置来调整MyISAM的调度行为。通过指定启动参数low-priority-updates,MyISAM引擎默认会优先处理读请求。通过执行命令SETLOW_PRIORITY_UPDATES=1,降低该连接发送的更新请求的优先级。通过指定INSERT、UPDATE和DELETE语句的LOW_PRIORITY属性来降低语句的优先级。以上三种方法虽然不是update-first或者query-first方法,但是在查询比较重要的应用(比如用户登录系统)中,仍然可以用它们来解决读锁等待严重的问题。另外,MySQL还提供了一种折衷的方法来调整读写冲突,即为系统参数max_write_lock_count设置一个合适的值。当一个表的读锁达到这个值时,MySQL会暂时降低写请求的优先级。,给读进程一定的机会获取锁。参考:《MySQL数据库锁机制之MyISAM引擎表锁和InnoDB行锁详解》
