Mysql——锁问题
2016-05-14 21:59
513 查看
1、概述
不同的存储引擎支持不同的锁机制,MyISAM和MEMORY存储引擎采用的是表级锁;BDB存储引擎采用的是页面锁,也支持表级锁;InnoDB则即支持行级锁,也支持表级锁,默认是行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度小,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
2、MyISAM表锁
有两种模式:表共享读锁和表独占写锁。锁模式的兼容性如下表所示:
如何加表锁:
MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行更新(增删改)操作前,会自动给涉及的表加写锁,不需要用户显示加锁。注意,当用户在执行LOCK TABLES后,只能访问显示加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。
并发插入:
MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。
为0:不允许并发插入。
为1:当MyISAM表中没有空洞(即表的中间没有被删除的行),则允许在一个进程读表的同时,另一个进程从表尾插入记录。
为2:无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。
当session_1获得了一个表的READ LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他线程,虽然不能对表进行删除和更新操作,但可以对该表进行并发插入操作。
3、InnoDB锁问题
背景知识:
事务及其ACID属性。原子性、一致性、隔离性和持久性。
并发事务
更新丢失、脏读、不可重复读、幻读。
事务隔离级别
4、InnoDB实现了一下两种类型的行锁:
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排它锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
为了允许行锁和表锁共存,实现多粒度锁值,InnoDB还有两种内部使用的意向锁,都是表锁:
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁钱必须先取得该表的IX锁。
相关语句:
共享锁:select * from table_name where … lock in share mode;
排他锁:select * from table_name where … for update;
注意,在使用共享锁时,如果两个事务 获得共享锁时,都需要对该记录进行更新操作,则很有可能造死锁。因此,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT…FOR UPDATE方式获得排他锁。
不同的存储引擎支持不同的锁机制,MyISAM和MEMORY存储引擎采用的是表级锁;BDB存储引擎采用的是页面锁,也支持表级锁;InnoDB则即支持行级锁,也支持表级锁,默认是行级锁。
表级锁:开销小,加锁快;不会出现死锁;锁定粒度小,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
2、MyISAM表锁
有两种模式:表共享读锁和表独占写锁。锁模式的兼容性如下表所示:
当前\是否兼容\请求锁 | 读锁 | 写锁 |
读锁 | 是 | 否 |
写锁 | 否 | 否 |
MyISAM在执行查询语句前,会自动给涉及的所有表加读锁,在执行更新(增删改)操作前,会自动给涉及的表加写锁,不需要用户显示加锁。注意,当用户在执行LOCK TABLES后,只能访问显示加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。
并发插入:
MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。
为0:不允许并发插入。
为1:当MyISAM表中没有空洞(即表的中间没有被删除的行),则允许在一个进程读表的同时,另一个进程从表尾插入记录。
为2:无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。
当session_1获得了一个表的READ LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他线程,虽然不能对表进行删除和更新操作,但可以对该表进行并发插入操作。
3、InnoDB锁问题
背景知识:
事务及其ACID属性。原子性、一致性、隔离性和持久性。
并发事务
更新丢失、脏读、不可重复读、幻读。
事务隔离级别
隔离级别\读取一致性及并发副作用 | 读数据一致性 | 脏读 | 不可重复读 | 幻读 |
未提交读 | 最低级别,只能保证不读取物理上损坏的数据 | 是 | 是 | 是 |
已提交读 | 语句级 | 否 | 是 | 是 |
可重复读 | 事务级 | 否 | 否 | 是 |
可序列化 | 最高级别,事务级 | 否 | 否 | 否 |
共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排它锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
为了允许行锁和表锁共存,实现多粒度锁值,InnoDB还有两种内部使用的意向锁,都是表锁:
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁钱必须先取得该表的IX锁。
请求锁模式\是否兼容\当前锁模式 | X | IX | S | IS |
X | 冲突 | 冲突 | 冲突 | 冲突 |
IX | 冲突 | 兼容 | 冲突 | 兼容 |
S | 冲突 | 冲突 | 兼容 | 兼容 |
IS | 冲突 | 兼容 | 兼容 | 兼容 |
共享锁:select * from table_name where … lock in share mode;
排他锁:select * from table_name where … for update;
注意,在使用共享锁时,如果两个事务 获得共享锁时,都需要对该记录进行更新操作,则很有可能造死锁。因此,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT…FOR UPDATE方式获得排他锁。
相关文章推荐
- MySQL存储过程+游标+触发器
- MySQL服务启动提示window无法启动MySQL服务 错误1067:进程意外终止
- mac安装mysql
- mysql5.7安装和配置
- SQL的存储过程的理解与应用(以mysql为例)
- MapServer 之 使用 MySQL 数据
- 淘宝物流mysql slave数据丢失详细原因
- MySQL的source命令不加分号和delimiter的使用
- MySQL学习笔记--视图的创建,删除,修改,算法
- MySQL SQL优化
- heartbeat v3版之mysql
- MySQL学习13:操作数据表中的记录(一)
- MySQL修改root密码的多种方法
- Mysql取某个范围内随机日期 FLOOR和LPAD
- csv文件导入mysql数据库命令
- mysql触发器案例
- MySQL 事件跟踪器 , MySQL 无须重启服务 跟踪 SQL , 也无须配置日志
- mysql root用户看不到mysql库下的所有表
- 连接MySQL错误:Can't connect to MySQL server (10060)
- LR连接mysql数据库