Menu Close

myisam锁操作

misaim表支持表锁,innodb支持表锁也支持行锁。
表锁:加锁快,不会出现死锁,锁定粒度大,发生锁冲突机率高,并发度低。
可以使用 mysql> show status like 'tables%';查看表锁争用情况,'Table_locks_waited'的value如果较高,则说明存在表锁争夺情况。

myisam表锁

表锁测试

使用tmux或者打开两个终端,进入mysql会话,在会话1加写锁:‘lock table table_name write’;

其中table_name是数据表名。锁定之后,只有在会话1里可以进行查看、插入操作,

在会话2执行一样的操作则会进入等待。 使用“unlock tables”释放锁后,会话2获得锁,操作才得以继续。

如何加表锁

myisam在执行查询语句前,会自动给涉及的所有表加读锁(获得锁才可以正常操作,没有获得锁则等待),在执行更新、删除、插入动作时,会自动加写锁(隐式加锁),这个过程不需要用户干预。

给表显示加锁,一般是为了在一定程度模拟事物操作,实现对某一时间点多个表的一致性读取,比如有order表和order_goods表,一个是订单表,有总价格(total),一个是订单详细表,有多个商品,有商品小记(sub_total),这时候需要验证两张表价格是否一致,如果在不加锁的情况下直接验证,则可能在验证的过程中会有新的数据插入,造成数据的不一致,这时候就需要将两表加锁。 mysql> lock tables order read local , order_detail read local; 验算完后,再释放锁mysql>unlock tables;

注意:在执行lock tables ... 后,只能访问显示加锁的这些表(未加锁的表则不能访问,如果是加读锁,则不可写),所以需要在加锁时,同时取得所有需要设计表带锁。

注意:如果一张表在sql中重复出现并且使用别名,则需要在加锁时同步锁定。

例:select * from table_a as a,tables_b as b.....,在加锁时就需要 mysql>lock table table_a as a read , table_a as b read;

并发插入

查询和插入操作并发进行。

myisam存储引擎有一个系统变量“concurrent_insert”来控制并发操作的行为,其值[0,1,2]

1、当值为0时,不允许并发插入。

2、当值为1时,如果表中没有空洞(自增id,1到100之间没有删除过记录),允许在一个进程读表的同时,另一个进程从尾部插入纪录,也是默认值。

3、当值为2时,无论有没有空洞,都允许在表尾并发插入纪录。

测试:

1)在终端进入mysql会话1,mysql>lock table table_a read local;   #加读锁,这里测试读写并发,

此时,不能对锁定表进行插入、更新操作。

2)mysql会话2,可以插入(重点,这时会从尾部插入本条纪录,但在会话1中,是不显示此纪录),但更新会被等待。

3)查询刚才插入的纪录,为空。

4)会话1释放锁后,可以查询刚才插入的纪录,并且,会话2中的更新操作会被执行。

myisam的锁调度

我们知道,读锁和写锁是互斥的,读写是串行的,这时,如果一个进程请求读锁,同时另一个进程请求写锁,mysql会如何处理呢? 答案是”写锁“先得,写锁具有优先级,mysql认为写比读重要。这也是myisam表不太适合大量更新和大量查询操作的原因,大量的更新操作会造成查询操作很难获得锁,因而造成阻塞,幸好,我们可以通过设置来调节Myisam的调度行为。

1、通过指定启动参数low-priority-updates,使“读”优先。

2、通过执行命令 SET LOW_PRIORITY_UPDATES=1,使得“写”请求降低。

3、通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注