(16)mysql 中的表锁定及事务控制

概述

MySQL支持三种锁级别:页级表级行级。MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认状况下是采用行级锁。在默认状况下,表锁和行锁都是自动获取的,不须要额外的命令。三种锁级别优缺点以下:html

  • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的几率最高,并发度最低。
  • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度通常。
  • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高。

表锁定

1.语法

#锁定表
LOCK TABLES 
    tb_name1 [AS alias] {READ[LOCAL]|[LOW_PRIORITY] WRITE}
    tb_name2 [AS alias] {READ[LOCAL]|[LOW_PRIORITY] WRITE}
    ...
#释放表锁定
UNLOCK TABLES;复制代码
  • lock tables 能够锁定用于当前线程(会话)的表。若是被其余线程锁定,则当前线程会等待,直到能够获取全部锁定为止。
  • unlock tables释放当前线程(会话)得到的任何锁定。
  • read(读锁/共享锁):当表不存在 WRITE 写锁时 READ 读锁被执行,这该状态下,当前线程不能够修改(insert,update,delete),其余线程的修改操做进入列队,当当前线程释放锁,其余线程修改被执行。
  • read local:read local和read之间的区别是,read local容许在锁定被保持时,执行非冲突性INSERT语句(同时插入)。可是,若是您正打算在MySQL外面操做数据库文件,同时您保持锁定,则不能使用read local。对于InnoDB表,read local与read相同。
  • write(写锁/排它锁):除了当前用户被容许读取和修改被锁表外,其余用户的全部访问(读/写)被彻底阻止。注意的是在当前线程当WRITE被执行的时候,即便以前加了READ没被取消,也会被取消。
  • low_priority write:下降优先级的write,默认write的优先级高于read.假如当前线程的low_priority write在列队里面,在未执行以前其余线程传送一条read,那么low_priority write继续等待.
  • InnoDB行锁是经过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不一样,后者是经过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特色意味着:只有经过索引条件检索数据,InnoDB才使用行级锁,不然,InnoDB将使用表锁!
  • 并发插入:原则上数据表有一个读锁时,其它进程没法对此表进行更新操做,但在必定条件下,MyISAM表也支持查询和插入操做的并发进行。MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别能够为0、1或2。
    • 当concurrent_insert设置为0时,不容许并发插入。
    • 当concurrent_insert设置为1时,若是MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM容许在一个进程读表的同时,另外一个进程从表尾插入记录。这也是MySQL的默认设置。
    • 当concurrent_insert设置为2时,不管MyISAM表中有没有空洞,都容许在表尾并发插入记录。

2.举例

这是一个获取表锁及释放表锁的例子。其中session1和session2表示两个同时打开的session(链接/线程),表格中的每一行表示同一时刻两个session的运行状况,后面的例子也是一样的格式。
sql

表锁举例

事务控制

MySQL经过set autocommit、start transaction、commit、rollback等语句支持本地事务。数据库

1.语法

START TRANSACTION |BEGIN [WORK]
COMMIT [WORK][AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK][AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT={0|1}复制代码
  • 默认状况下,MySQL是自动提交的,若是须要经过明确的Commit和Rollback来提交和回滚事务,那么就须要经过明确的事务控制命令来开始事务。
  • start transaction 或begin语句开始一项新的事务。
  • commit和rollback用来提交或者回滚事务。
  • chain和release子句分别用来定义在事务提交或者回滚以后的操做,chain会当即启动一个新事物,而且和刚才的事务具备相同的隔离级别,release则会断开和客户端的链接。
  • set autocommit能够修改当前链接的提交方式,若是设置了set autocommit=0,则设置以后的全部事务都须要经过明确的命令进行提交或者回滚。

2.举例

举例一
使用start transaction和commit and chain。
session

事务控制1-1

事务控制1-2

事务控制1-3

举例二
在锁表期间,用start transaction命令开启新事务,会形成隐含的unlock tables被执行。
并发

事务控制2-1

事务控制2-2

举例三
在事务中能够经过定义savepoint,指定回滚事务的一个部分,可是不能指定提交事务的一个部分。对于复杂的应用,能够定义多个不一样的savepoint,知足不一样的条件时,回滚不一样的savepoint。须要注意的是,若是定义了相同名字的savepoint,则后面定义的savepoint会覆盖以前的定义。对于再也不须要使用的savepoint,能够经过release savepoint命令删除savepoint,删除后的savepoint,不能再执行rollback to savepoint命令。
事务控制3-1

事务控制3-2

参考

blog.csdn.net/xiao7ng/art…
www.cnblogs.com/huangye-dre…
c.biancheng.net/cpp/html/14…spa

相关文章
相关标签/搜索