`
gy3135990
  • 浏览: 51173 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySQL 锁

阅读更多

MySQL 支持对 MyISAM 和 MEMORY 表进行表级锁定,对 InnoDB 表进行行级锁定。

 

在许多情况下,可以根据猜测应用程序使用哪类锁定类型最好,但一般很难说出某个给出的锁类型就比另一个好。一切取决于应用程序,应用程序的不同部分可能需要不同的锁类型。

 

为了确定是否想要使用行级锁定的存储引擎,应看看应用程序做什么并且混合使用什么样的选择和更新语句。例如,大多数Web应用程序执行许多选择,而很少进行删除,只对关键字的值进行更新,并且只插入少量具体的表。基本MySQL MyISAM 设置已经调节得很好。

 

在 MySQL 中对于使用表级锁定的存储引擎,表锁定时不会死锁的。这通过总是在一个查询开始时立即请求所有必要的锁定并且总是以同样的顺序锁定表来管理。

 

对 WRITE,MySQL使用的表锁定方法原理如下:
 如果在表上没有锁,在它上面放一个写锁。
 否则,把锁定请求放在写锁定队列中。

 

对 READ,MySQL使用的锁定方法原理如下:
 如果在表上没有写锁定,把一个读锁定放在它上面。
 否则,把锁请求放在读锁定队列中。

 

当一个锁定被释放时,锁定可被写锁定队列中的线程得到,然后是读锁定队列中的线程。

 

这意味着,如果你在一个表上有许多更新,SELECT语句将等待直到没有更多的更新。

 

可以通过检查 table_locks_waited 和 table_locks_immediate 状态变量来分析系统上的表锁定争夺:

 

mysql> show global status like "table_locks%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 36    |
| Table_locks_waited    | 0     |
+-----------------------+-------+
2 rows in set (0.00 sec)

 

Table_locks_immediate 发生表锁定操作, 但表锁定后马上释放
Table_locks_waited  发生表锁定, 并因此具有锁等待

 

对于 SQL 执行过程中, 需要对 SQL 进行硬解析, 计算 SQL 的运行成本后得到执行计划, 在执行 SQL 语句的时候需要查询当前资源是否具有锁机制, 如果当前资源被锁定中, 必须等待资源释放后才能够继续执行 SQL.

 


利用 SCHEMA sbtest.new 作为测试对象. 参考下面表结构。

 

mysql> desc sbtest.new;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)

 

 

 

下面两个例子举例说明锁定的发生。

 

例子 1 读锁定

 

当前具有两个 session 登录到 MySQL 服务器中, 简称 sessionA 与 sessionB。

 


sessionA 中执行下面操作。

 

sessionA> show global status like "table_locks%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 36    |
| Table_locks_waited    | 0     |
+-----------------------+-------+
2 rows in set (0.00 sec)

 

解释:查询当前 MySQL 中表锁定信息。

 


sessionA> lock table sbtest.new write;
Query OK, 0 rows affected (0.00 sec)

 

解释:对测试表 sbtest.new 锁定,该操作只会影响其他会话对 sbtest.new 表执行 DDL 及 DML 操作。

 


sessionA> show global status like "table_locks%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Table_locks_immediate | 37    |
| Table_locks_waited    | 0     |
+-----------------------+-------+
2 rows in set (0.00 sec)

 

解释:当执行 lock table 操作之后,系统会对 sbtest.new 表执行一次锁定操作,当完成在表中数据库头部标记锁定资源操作后,释放锁。

 

在当前 sessionA 执行锁定操作状态下,不影响 sessionA 对表 sbtest.new 进行增删改操作,参考例子。

 

sessionA> insert into sbtest.new values (4),(5),(6);
Query OK, 3 rows affected (0.04 sec)
Records: 3  Duplicates: 0  Warnings: 0

 

sessionA> select * from sbtest.new;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
+------+
6 rows in set (0.00 sec)

 

sessionA> delete from sbtest.new where id > 3;
Query OK, 3 rows affected (0.06 sec)

 


完成上述操作后, 切换到 sessionB 会话中, 执行下面操作。

 

sessionB> select * from sbtest.new;

 

解释:当 sessionB 进行表查询时,由于 sessionA 执行锁定操作,导致查询等待,直到锁定结束为止。

 

利用管理员创建 sessionC 登录到 MySQL, 利用 show processlist 命令显示当前登录到 MySQL 终端的所有状态状态信息。

 

sessionC> show processlist;
+----+------+---------+------+---------------------------------+--------------------------+
| Id | db   | Command | Time | State                           | Info                     |
+----+------+---------+------+---------------------------------+--------------------------+
|  1 | NULL | Sleep   |  120 |                                 | NULL                     |
|  2 | NULL | Query   |    0 | NULL                            | show processlist         |
|  3 | NULL | Query   |  112 | Waiting for table metadata lock | select * from sbtest.new |
+----+------+---------+------+---------------------------------+--------------------------+
3 rows in set (0.00 sec)

 

要使用 show processlist 必须具有 PROCESS 权限,由于排版关系,返回信息进行部分折断,从 State 状态栏中可以清楚看到, ID 3 的会话当前正在处于查询等待状态, Waiting for table metadata lock 显示当前等待状态信息。

 

 

 

只要 sessionA 对表执行解锁操作,sessionB 就能够重新获得资源,继续之前 SQL 操作。

 

sessionA> unlock tables;
Query OK, 0 rows affected (0.00 sec)

 

sessionB> select * from sbtest.new;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (29 min 52.91 sec)

 

 

 

例子 2 死锁

 

MySQL 在使用 InnoDB 引擎时,默认使用自动提交机制,该机制能够自动帮我们完成事务,自动提交机制并不能够为我们提高事务性能,我们稍后进行描述。

 

认识一下死锁的发生。我们需要两个会话,分别是 sessionA 与 sessionB。分别创建两个表,t_lock.a 与 t_lock.b, t_lock.a 与 t_lock.b 结构一致,如下描述。

 

mysql> desc t_lock.a;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

 

mysql> desc t_lock.b;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| name  | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

 

测试过程中,sessionA 与 sessionB 需要关闭自动提交功能。
1. sessionA 登录到数据库,分别在两个表中插入测试数据。

 

sessionA> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

 

sessionA> insert into t_lock.a values (1,'from sessionA');
Query OK, 1 row affected, 1 warning (0.00 sec)

 

sessionA> insert into t_lock.b values (1,'from sessionA');
Query OK, 1 row affected, 1 warning (0.00 sec)

 

sessionA> commit;
Query OK, 0 rows affected (0.04 sec)

 

2. sessionA 更新 A 表中数据,不提交事务。

 

sessionA> update t_lock.a set name='new data' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

 

sessionA> select * from t_lock.a;
+----+----------+
| id | name     |
+----+----------+
|  1 | new data |
+----+----------+
1 row in set (0.00 sec)

 

3. sessionB 更新 B 表数据, 再更新 A 表数据,由于当前 A 表数据被 sessionA 修改中,数据处于保护状态,导致 sessionB 尝试修改 A 表数据时候出现锁定等待。锁定过程中,系统显示进程为更新中。

 

sessionB> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

 

mysql> update t_lock.b set name='update data' where id=1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

 

sessionB> select * from t_lock.b;
+----+------------+
| id | name       |
+----+------------+
|  1 | update dat |
+----+------------+
1 row in set (0.00 sec)

 

sessionB> update t_lock.a set name='update data' where id=1;

 

sessionA> show full processlist;
+----+------+---------+------+----------+---------------------------------------------------+
| Id | db   | Command | Time | State    | Info                                              |
+----+------+---------+------+----------+---------------------------------------------------+
|  2 | NULL | Query   |    8 | Updating | update t_lock.a set name='update data' where id=1 |
|  3 | NULL | Query   |    0 | NULL     | show full processlist                             |
+----+------+---------+------+----------+---------------------------------------------------+
2 rows in set (0.00 sec)

 


4. 这个时候当 sessionA 尝试修改 B 表数据,因为 sessionB 当前为锁定状态,而且 sessionB 对 B 表中数据具有锁定状态中,则出现死锁。sessionB 会自动终止尝试修改 A 表数据事务, 并返回下面错误信息。而且下面两个事务操作都被终止。

 

sessionA> update t_lock.b set name='new data' where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

 

sessionB> update t_lock.a set name='update data' where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

 

sessionA> select * from t_lock.a;
+----+----------+
| id | name     |
+----+----------+
|  1 | new data |
+----+----------+
1 row in set (0.00 sec)

 

sessionB> select * from t_lock.b;
+----+------------+
| id | name       |
+----+------------+
|  1 | update dat |
+----+------------+
1 row in set (0.00 sec)

 

 

转载地址:http://blog.csdn.net/signmem/article/details/7689157

分享到:
评论

相关推荐

    MYSQL锁机制全揭秘

    MySQL锁机制是数据库管理系统中用于协调多个事务或者进程,以保证数据的完整性和一致性的一套规则。在数据库操作中,保证数据并发访问时的一致性、有效性是至关重要的,锁机制正是为此而生。 MySQL支持不同存储引擎...

    MYSQL锁表问题的解决方法

    本文将介绍几种解决MySQL锁表问题的方法。 1. **查看并杀死锁定进程** 使用`SHOW PROCESSLIST`命令可以查看当前所有正在执行的SQL语句及其状态,包括是否被锁定。如果发现有锁定的进程,可以使用`KILL`命令来终止...

    mysql 锁机制及mysql中的锁介绍.pdf

    系统介绍mysql锁机制

    MYSQL 解锁与锁表介绍

    MySQL锁概述   相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁...

    MYSQL锁机制

    ### MySQL锁机制详解 #### 一、MySQL锁机制概述 MySQL中的锁机制是数据库管理系统用于控制并发事务对数据资源访问的关键技术之一。合理地管理和利用锁机制能够有效地防止数据不一致性和提高系统的并发处理能力。...

    MySQL锁的详细介绍

    "MySQL锁的详细介绍" MySQL锁机制是 MySQL 中的一个重要概念,它决定了数据库中数据的读写权限和并发控制。本文将对 MySQL 锁机制进行详细的介绍,包括锁分类、锁类型、锁机制、行锁原理等内容。 一、锁分类 ...

    mysql锁详解

    资源名称:mysql锁详解资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。

    mysql锁表解表

    MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)...

    mysql锁解决并发问题共7页.pdf.zip

    这份名为"mysql锁解决并发问题共7页.pdf"的文档很可能详细阐述了这些锁机制及其应用场景。 在MySQL中,锁主要分为两大类:行级锁(Row-Level Locks)和表级锁(Table-Level Locks)。行级锁能提供更细粒度的锁定,...

    MySQL锁详细介绍

    MySQL锁是数据库管理系统中用于控制并发访问的一种机制,它的主要目的是确保在多用户环境中数据的一致性和完整性。在介绍MySQL锁之前,我们首先要理解为什么需要引入锁。在并发操作数据库时,可能出现数据不一致的...

    Mysql 锁机制的详细说明

    【MySQL 锁机制详解】 MySQL 的锁机制是数据库管理系统中用于协调多个并发事务对数据进行访问的一种机制,确保数据的一致性和完整性。在开发中,虽然我们可能并不总是主动使用锁,但它们在多用户环境下确保数据正确...

    MySQL锁与事务脑图.pdf

    MySQL锁与事务知识脑图

    MySQL锁类型以及子查询锁表问题、解锁1

    MySQL中的锁机制是数据库并发控制的关键部分,它确保了在多用户环境中数据的一致性和完整性。在MySQL中,主要存在两种类型的锁:行级锁(Row-Level Locks)和表级锁(Table-Level Locks)。InnoDB存储引擎默认支持...

    MySQL锁和事务、InnoDB架构分析.zip

    MySQL锁和事务、InnoDB架构分析.zipMySQL锁和事务、InnoDB架构分析.zipMySQL锁和事务、InnoDB架构分析.zipMySQL锁和事务、InnoDB架构分析.zipMySQL锁和事务、InnoDB架构分析.zipMySQL锁和事务、InnoDB架构分析....

    MySQL锁详解

    MySQL的锁机制对于数据库系统的性能和稳定性起着至关重要的作用。在数据库设计和开发过程中,合理地使用锁策略,能够有效避免死锁现象,提高并发处理能力。接下来,将详细介绍MySQL中的不同类型的锁及其适用场景。 ...

    MySQL锁机制_管理 .mht

    MySQL锁机制_管理(并发锁,行锁,表锁,预加锁,全局锁等等).mht

    mysql锁分析(csdn)————程序.pdf

    MySQL 锁分析 MySQL 锁机制是 MySQL 数据库中用于管理并发访问的机制, MySQL 锁机制主要有三种类型:表锁、行锁、页锁。每种锁机制都有其特点和应用场景。 表锁 表锁是 MySQL 中最基本的锁机制,表锁分为共享锁...

    MySQL锁竞争避免机制探析.pdf

    《MySQL锁竞争避免机制探析》 MySQL是一个广泛应用于互联网中小型网站的关系型数据库管理系统,以其体积小、速度快、开源等优势受到青睐。然而,在多线程环境下,不同用户并发对同一数据表进行读写操作时,锁竞争...

    深入理解Mysql锁与事务隔离级别1

    《深入理解MySQL锁与事务隔离级别》 在数据库管理中,锁和事务隔离级别是确保数据一致性与并发控制的重要概念。本文将详细阐述MySQL中的锁机制以及事务的四种隔离级别,以帮助读者更好地理解和应用这些关键概念。 ...

Global site tag (gtag.js) - Google Analytics