MySql中的锁(表锁,行锁)
锁是计算机协调多个进程或春线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU,RAM,I/O)的争用之外,数据也是一种工许多用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问的性能的一个重要因素。从这个角度来说,锁堆数据库而言显得尤其重要,也更加复杂。
概述
相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。MySQL大致可以归纳为以下2种锁:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率最小,并发度也最高。
页面锁:开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间。并发度一般。
MySQL表级锁的锁模式(MyISAM)
MySQL表级锁有两种模式:读锁(Table Read Lock)和写锁(Table Write Lock)。
对MyISAM读操作,不会阻塞其他用户对同一表请求,但是会阻塞对同一表的写请求;
对MyISAM的写操作,则会阻塞其他用户对同一表的读和写操作。
MyISAM读操作和写操作之间,以及写操作之间是串行的。
当一个线程获得对一个表的写操作后,只有持有所线程可以对表进行更新操作,其他线程的读,写操作都会等待,直到锁被释放。
如何加表锁:
MyISAM在执行查询语句(SELECT)前,会自动给设计的所有表加读锁,在执行更新操作(UPDATE, DELETE,INSERT)前,会自动给涉及的表加写锁。这个过程并不需要用户干预,因此用户一般不需要直接用户LOCK TABLE命令给MyISAM表显示加锁。
在用LOCK Tables给表显示加锁时,必须同时取得所有涉及表的锁,并且MySQL支持锁升级。也就是说,在执行LOCK TABLE后,只能访问显示加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。其实,在自动加锁的情况下也是基本如此,MySQL问题一次获得SQL语句所需要的全部锁。这也是MyISAM表不会出现死锁的原因。
并发锁:
在一定条件下,MyISAM也支持查询和操作的并发进行。
MyISAM存储引擎有一个系统变量concurrent_insert,专门泳衣控制其并发插入的行为,其值分别为0,1或者2.
当concurrent_insert设置为0时,不允许并发插入。
当concurrent_insert设置为1时,如果MyISAM允许在一个读表的同时,另一个进程从表尾插入记录,这也是MyISAM的默认设置。
当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾插入记录,都允许在表尾并发插入记录。
可以咯用MyISAM存储引擎插入特性,来解决应用中对同一表查询和插入锁争用。例如,将concurrent_insert系统变量为2,总是允许并发插入;同时,通过定期在系统空闲时段执行OPTIONMIZE 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语句做一定的“分解”,使每一步查询都能在较短时间完成。从而减少锁冲突。如果复杂查询不可避免,应尽量安排在数据库空闲的时段执行。
InnoDB锁问题
InnoDB与MyISAM的最大不同有两点:一是支持事物(TRANSACTION);二是采用了行级锁。
行级锁和表级锁本来就有许多不同之处,另外,事物的引入也带来了一些新的问题。
1.事物(Transaction)及其ACID属性
事物是有一组SQL语句组成的逻辑处理单元,事物具有4属性,通常称为ACID属性。
原子性(Actomicity):事物是一个原子操作,其对数据的修改,要么全部执行,要么全都不执行。
一致性(Consistent):在事物开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事物的修改,以保持完整性;事物结束时,所有的内部数据结构(如B树索引和双向链表)也都必须是正确的。
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事物在不受外部并发操作影响的“独立”环境执行。这意味着事物处理过程中的中间状态对外部是不可见的。
持久性(Durable):事物完成之后,它对数据库的修改时永久的,即使出现系统故障也能够保持。
2.并发事物带来的问题
相对于穿行处理莱索,并发事物处理能大大增加数据库的利用率,提高数据库的事物吞吐量,从而可以支持更多的用户。但是并发事物处理也会带来一些问题。主要包括以下几种。
更新丢失(Lost Update):当两个或者多个事物选择同一行,然后给予最初选定的值更新该行时,由于每个事物都不知道其他事物的存在,就会发生丢失更新问题,最后的更新覆盖了其他事物锁做的更新。例如,两个编辑人员制作统一文档的电子副本。每个编辑人员独立的更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的修改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件。则可避免此问题。
脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务提交之前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”的数据,并据此做进一步的处理,就会产生未提交的数据以来关系。这种现象被形象的叫做“脏读”。
不可重复读(Non-Repeatable Reads):一个事务在读取某些数据已经发生了改变,或某系记录已经被删除了,这种现象叫做“不可重复读”。
幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事物插入了满足其查询条件的新数据,这种现象就称为“幻读”。
事物的隔离级别
在并发事物处理带来的问题中,“更新丢失”通常应该是完全避免的,但是防止更新丢失,并不能但依靠数据库事物控制器来解决,需要应用程序对要更新的数据加必要的锁来解决,因此,防止更新丢失时应用的责任。
“脏读”,“不可重复读”和“幻读”都是数据库一致性问题,必须由数据库提供一定的事物隔离机制来解决,数据库实现事物隔离的方式,基本可以分为以下两种。
一种是在读取数据前,对其加锁,组织其他市区对数据进行修改。
另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别的一致性读取。从用户的角度,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC)也经常称为多版本数据库。
事物4种隔离级别比较
隔离级别 | 数据一致性 | 脏读 | 不可重复读 | 幻读 |
未提交读(Read uncommitted) | 最低级别,只能保证不读取物理上损坏的数据 | 是 | 是 | 是 |
已提交读(Read committed) | 语句级 | 否 | 是 | 是 |
可重复读(Repeatable read) | 事务级 | 否 | 否 | 是 |
可序列化(Serializable) | 最高级别,事务级 | 否 | 否 | 否 |
InnoDB的行锁模式和加锁方法
InnoDB实现了以下两种类型的行锁:
共享锁(s):允许一个事务去读一行,阻止其他事物获得相同数据集的排他锁。
排他锁(X):允许获取排他锁的事物更新数据,阻止其他事物获得相同的数据共享读锁和排他写锁。
另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用放意象锁,这两种意象锁都是表锁。
意向共享锁(IS):事物打算给数据行共享锁,事物在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事物打算给数据行加排他锁,事物在给一个数据行家排他锁之前必须先取得该表的IX锁。
MySql中的锁(表锁,行锁)的更多相关文章
- mysql中InnoDB存储引擎的行锁和表锁
Mysql的InnoDB存储引擎支持事务,默认是行锁.因为这个特性,所以数据库支持高并发,但是如果InnoDB更新数据的时候不是行锁,而是表锁的话,那么其并发性会大打折扣,而且也可能导致你的程序出错. ...
- mysql 多列唯一索引在事务中select for update是不是行锁?
在表中有这么一索引 UNIQUE KEY `customer_id` (`customer_id`,`item_id`,`ref_id`) 问1. 这种多列唯一索引在事务中select for upd ...
- mysql死锁-查询锁表进程-分析锁表原因【转】
查询锁表进程: 1.查询是否锁表 show OPEN TABLES where In_use > 0; 2.查询进程 show processlist 查询到相对应的进程===然 ...
- 极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间
极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间 笔记体会: 方案一,事务相 ...
- mysql--->innodb引擎什么时候表锁什么时候行锁?
mysql innodb引擎什么时候表锁什么时候行锁? InnoDB基于索引的行锁 InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁 ...
- mysql中的回表查询与索引覆盖
了解一下MySQL中的回表查询与索引覆盖. 回表查询 要说回表查询,先要从InnoDB的索引实现说起.InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Sec ...
- mysql中把一个表的数据批量导入另一个表中
mysql中把一个表的数据批量导入另一个表中 不管是在网站开发还是在应用程序开发中,我们经常会碰到需要将MySQL或MS SQLServer某个表的数据批量导入到另一个表的情况,甚至有时还需要指定 ...
- MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
悲观锁: 顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁.上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交或者回滚.传统的关 ...
- mysql中lock tables与unlock tables(锁表/解锁)使用总结
php mysql lock tables 使用有感 mysql 的 表锁 lock tables 感觉就像一个 封闭的空间 mysql发现 lock tables 命令的时候,会将带有锁标记的表(t ...
- MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 7) --行锁功能:怎么减少行锁对性能的影响? MySQL的行锁是在引擎层由各个引擎自己实现的.因此,并不是所有的引擎都支持行锁,如 ...
随机推荐
- Spiral Matrix螺旋遍历矩阵
假定有: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] 这样一个数组矩阵,现要求对其进行顺时针方向螺旋形从外至内地遍历,即输出: [1,2,3,6,9,8,7,4 ...
- Docker-端口映射与容器互联
在使用docker过程中,通常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间有能够互相访问到对方的服务除了通过网络访问外,Docker还提供了两个很方便的功能来满足服务访问的基本需求 ...
- Qt之任务栏系统托盘图标
转自 --> http://blog.csdn.net/qivan/article/details/7506306 托盘图标,一个自己脑子出现很久的词,可惜自己都没动手去实现.最近看见的,听见 ...
- PS 滤镜— —Twirl Filter
clc; clear all; close all; addpath('E:\PhotoShop Algortihm\Image Processing\PS Algorithm'); I=imread ...
- NO3:步履蹒跚-完成第一章节学习
第一章小记: 每个C程序都要求有一个main()函数(多于一个main()函数是不合法的(已犯错:在VS 2010一个项目里两个C文件都有main函数,不能编译通过,必须删除一个文件,永记)).mai ...
- Java集合操作类Collections的一些常用方法
public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); ...
- ACM学习历程—Hihocoder 1289 403 Forbidden(字典树 || (离线 && 排序 && 染色))
http://hihocoder.com/problemset/problem/1289 这题是这次微软笔试的第二题,过的人比第三题少一点,这题一眼看过去就是字符串匹配问题,应该可以使用字典树解决.不 ...
- ACM学习历程—HDU 5459 Jesus Is Here(递推)(2015沈阳网赛1010题)
Sample Input 9 5 6 7 8 113 1205 199312 199401 201314 Sample Output Case #1: 5 Case #2: 16 Case #3: 8 ...
- cloudera上面安装Spark2.0
Cloudera默认值是提供Spark1.6的安装,下面介绍如何来安装spark2.1 1. csd包:http://archive.cloudera.com/spark2/csd/ 2. parce ...
- 上海-北京间通过Azure Storage的RA-GRS类型的存储账户进行快速复制
Azure的Blob存储分成多种类型,目前主要有: 其中RA-GRS可以在上海-北京两个数据中心间同步数据.并且,在第二个数据中心可以只读的方式读取这个存储账户中的Blob内容. 虽然GRS采用的是准 ...