转摘: MySQL详解--锁
原文 http://blog.csdn.net/xifeijian/article/details/20313977
背景知识
1.事务(Transaction)及其ACID属性
2.并发事务处理带来的问题
3.事务隔离级别
|
读数据一致性及允许的并发副作用
隔离级别
|
读数据一致性
|
脏读
|
不可重复读
|
幻读
|
|
未提交读(Read uncommitted)
|
最低级别,只能保证不读取物理上损坏的数据
|
是
|
是
|
是
|
|
已提交度(Read committed)
|
语句级
|
否
|
是
|
是
|
|
可重复读(Repeatable read)
|
事务级
|
否
|
否
|
是
|
|
可序列化(Serializable)
|
最高级别,事务级
|
否
|
否
|
否
|
获取InnoDB行锁争用情况
InnoDB的行锁模式及加锁方法
|
请求锁模式
是否兼容
当前锁模式
|
X
|
IX
|
S
|
IS
|
|
X
|
冲突
|
冲突
|
冲突
|
冲突
|
|
IX
|
冲突
|
兼容
|
冲突
|
兼容
|
|
S
|
冲突
|
冲突
|
兼容
|
兼容
|
|
IS
|
冲突
|
兼容
|
兼容
|
兼容
|
InnoDB行锁实现方式
|
session_1
|
session_2
|
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
|
mysql> select * from tab_with_index where id = 1 and name = '1' for update;
+------+------+
| id | name |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
|
|
|
虽然session_2访问的是和session_1不同的记录,但是因为使用了相同的索引,所以需要等待锁:
mysql> select * from tab_with_index where id = 1 and name = '4' for update;
等待
|
|
session_1
|
session_2
|
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
|
mysql> select * from tab_with_index where id = 1 for update;
+------+------+
| id | name |
+------+------+
| 1 | 1 |
| 1 | 4 |
+------+------+
2 rows in set (0.00 sec)
|
|
|
Session_2使用name的索引访问记录,因为记录没有被索引,所以可以获得锁:
mysql> select * from tab_with_index where name = '2' for update;
+------+------+
| id | name |
+------+------+
| 2 | 2 |
+------+------+
1 row in set (0.00 sec)
|
|
|
由于访问的记录已经被session_1锁定,所以等待获得锁。:
mysql> select * from tab_with_index where name = '4' for update;
|
间隙锁(Next-Key锁)
|
session_1
|
session_2
|
|
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
|
|
当前session对不存在的记录加for update的锁:
mysql> select * from emp where empid = 102 for update;
Empty set (0.00 sec)
|
|
|
这时,如果其他session插入empid为102的记录(注意:这条记录并不存在),也会出现锁等待:
mysql>insert into emp(empid,...) values(102,...);
阻塞等待
|
|
|
Session_1 执行rollback:
mysql> rollback;
Query OK, 0 rows affected (13.04 sec)
|
|
|
由于其他session_1回退后释放了Next-Key锁,当前session可以获得锁并成功插入记录:
mysql>insert into emp(empid,...) values(102,...);
Query OK, 1 row affected (13.35 sec)
|
恢复和复制的需要,对InnoDB锁机制的影响
另 外,对于“insert into target_tab select * from source_tab where ...”和“create table new_tab ...select ... From source_tab where ...(CTAS)”这种SQL语句,用户并没有对source_tab做任何更新操作,但MySQL对这种SQL语句做了特别处理。
InnoDB在不同隔离级别下的一致性读及锁的差异
|
隔离级别
一致性读和锁
SQL
|
Read Uncommited
|
Read Commited
|
Repeatable Read
|
Serializable
|
|
|
SQL
|
条件
|
||||
|
select
|
相等
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share locks
|
|
范围
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
|
|
update
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
Exclusive locks
|
|
范围
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
|
Insert
|
N/A
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
|
replace
|
无键冲突
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
|
键冲突
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
|
delete
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
|
范围
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
|
Select ... from ... Lock in share mode
|
相等
|
Share locks
|
Share locks
|
Share locks
|
Share locks
|
|
范围
|
Share locks
|
Share locks
|
Share Next-Key
|
Share Next-Key
|
|
|
Select * from ... For update
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
|
范围
|
exclusive locks
|
Share locks
|
exclusive next-key
|
exclusive next-key
|
|
|
Insert into ... Select ...
(指源表锁)
|
innodb_locks_unsafe_for_binlog=off
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
|
innodb_locks_unsafe_for_binlog=on
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
|
|
create table ... Select ...
(指源表锁)
|
innodb_locks_unsafe_for_binlog=off
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
|
innodb_locks_unsafe_for_binlog=on
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
|
什么时候使用表锁
关于死锁
|
session_1
|
session_2
|
|
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from table_1 where where id=1 for update;
...
做一些其他处理...
|
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from table_2 where id=1 for update;
...
|
|
select * from table_2 where id =1 for update;
因session_2已取得排他锁,等待
|
做一些其他处理...
|
|
mysql> select * from table_1 where where id=1 for update;
死锁
|
(4)前面讲过,在REPEATABLE-READ隔离级别下,如果两个线程同时对相同条件记录用SELECT...FOR UPDATE加排他锁,在没有符合该条件记录情况下,两个线程都会加锁成功。程序发现记录尚不存在,就试图插入一条新记录,如果两个线程都这么做,就会出 现死锁。这种情况下,将隔离级别改成READ COMMITTED,就可避免问题
对于这种情况,可以直接做插入操作,然后再捕获主键重异常,或者在遇到主键重错误时,总是执行ROLLBACK释放获得的排他锁
转摘: MySQL详解--锁的更多相关文章
- MySQL详解
MySQL详解 什么是数据库 # 用来存储数据的仓库 # 数据库可以在硬盘及内存中存储数据 # 数据库与文件存储数据区别 # 数据库本质也是通过文件来存储数据, 数据库的概念就是系统的管理存储数据的文 ...
- MySql详解(四)
MySql详解(四) MySql的DML操作 插入: 一.方式一 语法: insert into 表名(字段名,...) values(值,...); 特点: 1.要求值的类型和字段的类型要一致或兼容 ...
- MySql详解(一)
MySql详解(一) 作为一名Java开发人员,数据库的地位不用多说了.从大学时期的SqlServer,到现在最流行的MySql和Oracle.前者随着阿里巴巴的去IOE化,在互联网公司中的使用比例是 ...
- MySql详解(三)
MySql详解(三) 导入基础表 具体的SQL文件已经放入百度网盘,连接为:http://pan.baidu.com/s/1hseoVR2,后面的MySql内容都是按照这些基础表展开的. depart ...
- MySql详解(五)
MySql详解(五) MySql库的管理 一.创建库 create database [if not exists] 库名[ character set 字符集名]; 二.修改库 alter data ...
- MySql详解(七)
MySql详解(七) MySql视图 一.含义 mysql5.1版本出现的新特性,本身是一个虚拟表,它的数据来自于表,通过执行时动态生成. 好处: 1.简化sql语句 2.提高了sql的重用性 3.保 ...
- MySql详解(六)
MySql详解(六) MySql事务 一.含义 事务:一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行 二.特点(ACID) A 原子性:一个事务是不可再分割的整体,要么都执 ...
- MySQL详解--锁,事务
http://www.cnblogs.com/jukan/p/5670950.html http://blog.csdn.net/xifeijian/article/details/20313977 ...
- MySQL详解--锁,事务(转)
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数 ...
随机推荐
- windows linux 文件编码转换
查看文件编码在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vi ...
- 简单管理员权限与几个常用的PHP 常用函数,in_array(),explode(),implode(),join(),str_replace()
先把今天要用的几个函数罗列出来: //explode()转换成数组,implode()转化成字符串 explode("分隔符",需要被分割的字符串或变量) $priv=" ...
- 在GridView中使用FindControl
DataRowView dv =(DataRowView)e.Row.DataItem;string id=dv.Row["ProjectID"].ToString(); 1.在行 ...
- 一些日期的计算方式 PHP
一些日期的计算 某个月内的所有天数: public function getMonthDay ($date) { $stattime = strtotime(date('Ym01',strtotime ...
- ios9 safari currentTime audio bug
var audio = document.createElement('audio') audio.src = 'https://ic-static.vipkidteachers.com/course ...
- JdbcTemplate中queryForObject方法返回空结果或不正确结果数量的解决方法
在使用Spirng提供的JdbcTemplate中名为queryForObject API进行数据库查询时有时会抛出如下异常: org.springframework.dao.EmptyResultD ...
- 在右键菜单中加入BitLocker重新上锁功能
当使用BitLocker给磁盘上锁后,可以通过命令:manage-bde -lock d: -forcedismount 将已经解锁的磁盘重新上锁,如果觉得每次都通过命令行写命令很麻烦,那可以通过修改 ...
- [正则表达式]PCRE反向分组引用(语法)
正则表达式中,凡出现圆括号(),括号中的匹配内容就会被认为是一个分组: 根据括号从左边出现的顺序命名分组代号,分组代号由1到n(代号0通常被一些语言用来引用整个表达式匹配的结果,即使这个表达式没有分组 ...
- pyhton图片合成模块-PIL
文章链接:https://www.cnblogs.com/lilinwei340/p/6474170.html python PIL实现图片合成 在项目中需要将两张图片合在一起.遇到两种情况,一种 ...
- python3 字典(dictionary)(一)
一.定义:是另一种可变容器模型,可存储任意类型对象:(也被称为关联数组或哈希表:存储的数据是没有顺序的) 语法为: d = {key1 : value1, key2 : value2 } #----- ...