`

Myisam引擎锁

 
阅读更多

Mysql的锁机制也分为三大类:

 

page Lock页级锁 、 table LOCK 表锁  、行锁

 

page Lock页级锁:NDB事务引擎。

 

首先查看当前的锁状态--

 

mysql>show status like ‘table%’;

+--------------------------------- +-------+

| Variable_name                   | Value  |

+---------------------------------+--------+

| Table_locks_immediate  | 2979   |

| Table_locks_waited              | 0      |

+---------------------------------+--------+

如果table_locks_waited的值过高的话,就会导致表锁争抢严重,应该做出调整。

 

Myisam引擎的表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)

 

对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;

对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;MyISAM表的读操作与写操作之间,以及写操作之间是串行的.

 

Demo for Lock:(表独占写锁(Table Write Lock))

lock table table_name write;

此时对table_name这张表加了表独占写锁(Table Write Lock),

导致其他session无法访问table_name中的数据信息,就是read操作也无法执行。

当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。

mysql> lock table world.city write;

Query OK, 0 rows affected (0.00 sec)

 

session2:此时的状态

mysql>use world

Database changed

mysql>select count(*) from city;

处于等待。

 

直到session1执行,unlock tables;

session2:

mysql>select count(*) from city;

+----------+

| count(*) |

+----------+

|     4081 |

+----------+

1 row in set (51.65 sec)

 

 

Myisam 表在做select查询的时候都会隐式的加一个读锁给相关的表,只能读不能写。。

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,

在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,

这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。

给MyISAM表显示加锁,一般是为了在一定程度模拟事务操作,实现对某一时间点多个表的一致性读取

 

 

Lock tables orders read local, order_detail read local;

Select count(clause) from orders;

Select sum(clause) from order_detail;

Unlock tables;

上面的例子在LOCK TABLES时加了“local”选项,其作用就是在满足MyISAM表并发插入条件的情况下,

允许其他用户在表尾并发插入记录,有关MyISAM表的并发插入问题,在后面的章节中还会进一步介绍。

 

mysql> lock table city read;

Query OK, 0 rows affected (0.01 sec)

 

mysql> select * from country;

ERROR 1100 (HY000): Table 'country' was not locked with LOCK TABLES

myisam表在加锁以后只能访问这些已经显示加了锁的表。

mysql> insert into city (ID) values(98876555)

    -> ;

ERROR 1099 (HY000): Table 'city' was locked with a READ lock and can't be updated

myisam表加了读锁,就只能执行读操作,不能更新表数据,

 

 

 

 

一个session使用LOCK TABLE命令给表film_text加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;同时,另外一个session可以查询表中的记录,但更新就会出现锁等待。

表20-3                     MyISAM存储引擎的读阻塞写例子

 

session_1

session_2

获得表film_text的READ锁定

mysql> lock table film_text read;

Query OK, 0 rows affected (0.00 sec)

 

当前session可以查询该表记录

mysql> select film_id,title from film_text where film_id = 1001;

+---------+------------------+

| film_id | title            |

+---------+------------------+

| 1001    | ACADEMY DINOSAUR |

+---------+------------------+

1 row in set (0.00 sec)

其他session也可以查询该表的记录

mysql> select film_id,title from film_text where film_id = 1001;

+---------+------------------+

| film_id | title            |

+---------+------------------+

| 1001    | ACADEMY DINOSAUR |

+---------+------------------+

1 row in set (0.00 sec)

当前session不能查询没有锁定的表

mysql> select film_id,title from film where film_id = 1001;

ERROR 1100 (HY000): Table 'film' was not locked with LOCK TABLES

其他session可以查询或者更新未锁定的表

mysql> select film_id,title from film where film_id = 1001;

+---------+---------------+

| film_id | title         |

+---------+---------------+

| 1001    | update record |

+---------+---------------+

1 row in set (0.00 sec)

mysql> update film set title = 'Test' where film_id = 1001;

Query OK, 1 row affected (0.04 sec)

Rows matched: 1  Changed: 1  Warnings: 0

当前session中插入或者更新锁定的表都会提示错误:

mysql> insert into film_text (film_id,title) values(1002,'Test');

ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated

mysql> update film_text set title = 'Test' where film_id = 1001;

ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated

其他session更新锁定表会等待获得锁:

mysql> update film_text set title = 'Test' where film_id = 1001;

等待

释放锁

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

等待

 

Session获得锁,更新操作完成:

mysql> update film_text set title = 'Test' where film_id = 1001;

Query OK, 1 row affected (1 min 0.71 sec)

Rows matched: 1  Changed: 1  Warnings: 0

 
mysql> lock table actor read;
Query OK, 0 rows affected (0.00 sec)
但是通过别名访问会提示错误:
mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name <> b.last_name;
ERROR 1100 (HY000): Table 'a' was not locked with LOCK TABLES
需要对别名分别锁定:
mysql> lock table actor as a read,actor as b read;
Query OK, 0 rows affected (0.00 sec)
 
 
3:     上文提到过MyISAM表的读和写是串行的,但这是就总体而言的。在一定条件下,MyISAM表也支持查询和插入操作的并发进行。

MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。

     当concurrent_insert设置为0时,不允许并发插入。

     当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),

MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。

     当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

 

session_1获得了一个表的READ LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他的线程(session_2),虽然不能对表进行删除和更新操作,但却可以对该表进行并发插入操作,这里假设该表中间不存在空洞。

表20-4              MyISAM存储引擎的读写(INSERT)并发例子

 

session_1

session_2

获得表film_text的READ LOCAL锁定

mysql> lock table film_text read local;

Query OK, 0 rows affected (0.00 sec)

 

当前session不能对锁定表进行更新或者插入操作:

mysql> insert into film_text (film_id,title) values(1002,'Test');

ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated

mysql> update film_text set title = 'Test' where film_id = 1001;

ERROR 1099 (HY000): Table 'film_text' was locked with a READ lock and can't be updated

其他session可以进行插入操作,但是更新会等待:

mysql> insert into film_text (film_id,title) values(1002,'Test');

Query OK, 1 row affected (0.00 sec)

mysql> update film_text set title = 'Update Test' where film_id = 1001;

等待

当前session不能访问其他session插入的记录:

mysql> select film_id,title from film_text where film_id = 1002;

Empty set (0.00 sec)

 

释放锁:

mysql> unlock tables;

Query OK, 0 rows affected (0.00 sec)

等待

当前session解锁后可以获得其他session插入的记录:

mysql> select film_id,title from film_text where film_id = 1002;

+---------+-------+

| film_id | title |

+---------+-------+

| 1002    | Test  |

+---------+-------+

1 row in set (0.00 sec)

Session2获得锁,更新操作完成:

mysql> update film_text set title = 'Update Test' where film_id = 1001;

Query OK, 1 row affected (1 min 17.75 sec)

Rows matched: 1  Changed: 1  Warnings: 0

        可以利用MyISAM存储引擎的并发插入特性,来解决应用中对同一表查询和插入的锁争用。例如,将concurrent_insert系统变量设为2,总是允许并发插入;同时,通过定期在系统空闲时段执行OPTIMIZE TABLE语句来整理空间碎片,收回因删除记录而产生的中间空洞。

 

Myisam锁调度:

 

MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的。那么,一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得锁。不仅如此,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!这是因为MySQL认为写请求一般比读请求要重要。这也正是MyISAM表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。这种情况有时可能会变得非常糟糕!幸好我们可以通过一些设置来调节MyISAM的调度行为。

        通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。

       通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。

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

        虽然上面3种方法都是要么更新优先,要么查询优先的方法,但还是可以用其来解决查询相对重要的应用(如用户登录系统)中,读锁等待严重的问题。

        另外,MySQL也提供了一种折中的办法来调节读写冲突,即给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。

        上面已经讨论了写优先调度机制带来的问题和解决办法。这里还要强调一点:一些需要长时间运行的查询操作,也会使写进程“饿死”!因此,应用中应尽量避免出现长时间运行的查询操作,不要总想用一条SELECT语句来解决问题,因为这种看似巧妙的SQL语句,往往比较复杂,执行时间较长,在可能的情况下可以通过使用中间表等措施对SQL语句做一定的“分解”,使每一步查询都能在较短时间完成,从而减少锁冲突。如果复杂查询不可避免,应尽量安排在数据库空闲时段执行,比如一些定期统计可以安排在夜间执行。

分享到:
评论

相关推荐

    mysql的 myisam引擎锁问题

    比如:myisam和memory存储引擎采用的是表级锁,bdb采用的是页面锁,但也支持表级锁,innodb存储引擎即支持行级锁也支持表级锁,但默认情况下是行级锁。  三种锁的特性大致归纳如下:  (1)表级锁:开销小,加锁...

    Innodb与Myisam引擎的区别与应用场景

    ### Innodb与Myisam引擎的区别与应用场景 在MySQL数据库管理系统中,选择合适的存储引擎对于确保数据的安全性、完整性和性能至关重要。其中,InnoDB和MyISAM是最为常见的两种存储引擎,它们各自具备独特的特性和...

    mysql事务与锁机制(存储引擎和锁、MyISAM锁机制、InnoDB锁机制、Next-Key锁、Dead-Lock).docx

    MyISAM引擎采用表级锁,其特点是在读操作时不会阻止其他线程对同一表的读请求,但在写操作时会阻塞其他线程的读写请求。这种锁机制使得读写操作之间以及写写操作之间呈串行化状态,即一次会话获取写锁后,其他所有...

    mysql架构与存储引擎(MySQL逻辑架构、InnoDB引擎、MyISAM引擎、存储引擎选择).docx

    ##### 2、MyISAM引擎 - **基础描述**:MyISAM是MySQL早期版本的默认存储引擎,不支持事务处理和行级锁,但提供了全文索引支持。 - **特点描述**: - **锁表机制**:在读取数据时使用共享锁,在写入数据时使用...

    《MYSQL备份与恢复》之 Innodb与 MyISAM引擎

    《MYSQL备份与恢复》之 Innodb与 MyISAM引擎 一、系统环境 1.1 ubuntu 12.0.4 X86_64 1.2 percona-xtrabackup-2.0.3.tar.gz 1.3 xtrabackup简介 xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时...

    MyISAM 锁1

    MyISAM是MySQL数据库中的一种存储引擎,它在处理数据时使用了特定的锁定机制来实现并发控制。本文将深入探讨MyISAM的锁机制,包括读锁和写锁,并通过示例展示其工作原理。 首先,我们来看MyISAM的读锁(READ lock)...

    MyISAM,InnoDB存储引擎1

    其中,MyISAM和InnoDB是最常用的两种存储引擎,各有其特点和适用场景。 MyISAM存储引擎是MySQL早期的默认引擎,以高速存储和检索以及全文搜索能力著称。在MyISAM中,每个表由三个物理文件组成:.frm存储表定义,....

    8.MySQL存储引擎--MyISAM与InnoDB区别1

    MySQL存储引擎--MyISAM与InnoDB区别 MySQL是一种关系型数据库管理系统,它支持多种存储引擎,每种存储引擎都有其特点和优缺。MyISAM和InnoDB是MySQL中最常用的两种存储引擎,它们都有其优缺点,本文将对比MyISAM...

    MyISAM和InnoDB的异同

    #### MyISAM引擎概述 MyISAM是MySQL早期默认使用的存储引擎,它主要适用于读取密集型的应用场景。MyISAM支持表级锁定,这意味着当一个表被用于写入操作时,整个表都会被锁定,直到该操作完成。这会导致其他查询或...

    MySQL存储引擎之争-InnoDB与MyISAM全面对决

    本文主要讨论的是InnoDB和MyISAM这两个引擎的对决,两者在事务处理、数据恢复、并发控制、存储空间占用以及读取性能等方面都有显著差异。 首先,InnoDB存储引擎支持事务处理,这使得它适用于那些需要确保数据完整性...

    MySQL存储引擎MyISAM与InnoDB区别总结整理

    MyISAM存储引擎的特点是:表级锁、不支持事务和全文索引,适合一些CMS内容管理系统作为后台数据库使用,但是使用大并发、重负荷生产系统上,表锁结构的特性就显得力不从心; 以下是MySQL 5.7 MyISAM存储引擎的版本...

    mysql的myisam解决并发读写解决方法

    在MySQL数据库系统中,MyISAM是一种非常常用的存储引擎。它以其高效性和简单的结构而在许多场景下得到广泛应用,尤其是在那些读取操作远多于写入操作的应用场景中。然而,当面对高并发的读写操作时,MyISAM的表现...

    MyISAM InnoDB 区别

     7、如果是用MyISAM的话,merge引擎可以大大加快应用部门的开发速度,他们只要对这个merge表做一些select count(*)操作,非常适合大项目总量约几亿的rows某一类型(如日志,调查统计)的业务表。  当然Innodb也不是...

    MYSQL 解锁与锁表介绍

    比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但...

    MySQL面试必备+Explain的讲解+简单优化+MyISAM、InnoDB存储引擎区别+MySQL为什么选择B+树索引+MySQL中的锁

    MySQL存储引擎 区别(MyISAM, InnoDB) 1,innodb支持事务,myisam不支持事务 2,innodb支持外键,而myisam不支持。...5,innodb支持行级锁,myisam锁的粒度是表级 6,myisam表示保存成文件的形式,在跨平台的数

    MySQL存储引擎解析.doc

    MyISAM是早期常用的引擎,它支持表级锁定,这意味着在执行更新或插入操作时,整个表会被锁定,导致其他读写操作必须等待。因此,MyISAM不适用于高并发的读写场景。此外,MyISAM不支持事务处理,不提供事务回滚功能,...

    MySQL课程之MySQL存储引擎入门

    - **相关参数配置**:可以通过修改my.cnf配置文件来调整MyISAM引擎的参数,如`key_buffer_size`用于设置索引缓存大小。 - **锁机制**:MyISAM采用表级锁定,意味着在写操作期间,整个表都会被锁定,可能导致并发...

    MySQL锁详解

    MyISAM和MEMORY存储引擎使用表级锁,BDB存储引擎支持页面锁,同时也可以使用表级锁,而InnoDB存储引擎则同时支持行级锁和表级锁,默认采用行级锁。 表级锁具有开销小,加锁速度快的特点,不会出现死锁,但是锁定...

    MySQL存储引擎中的MyISAM和InnoDB区别详解

    MySQL存储引擎中的MyISAM和InnoDB是两种最常见的选择,它们各自有独特的特性和适用场景。以下是关于这两种存储引擎的详细对比: 1. **存储结构**: - MyISAM:每个表由三个文件组成,分别是`.frm`(表定义)、`....

Global site tag (gtag.js) - Google Analytics