MySQL Server层表现
每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低
应用在MyISAM、InnoDB、BDB等存储引擎中。
MySQL的表级锁有两种:
表锁有两种表现形式
表读锁
session1: lock table mylock read; -- 给mylock表加读锁
session1: select * from mylock; -- 可以查询
session1: select * from tdep; -- 不可以访问非锁定表
session2: select * from mylock; -- 可以查询 没有锁
session2: update mylock set name='x' where id = 2; -- 修改阻塞,自动加行写锁
session1: unlock tables; -- 释放表锁
session2: Rows matched:1 Changed:1 Warning: 0 -- 修改执行完成
session1: select * from tdep; -- 可以访问
表写锁
session1: lock table mylock write; -- 给mylock表加写锁
session1: select * from mylock; -- 可以查询
session1: select * from tdep; -- 不能访问非锁定的表
session1: update mylock set name = 'y' where id = 2; -- 可以执行
session2: select * from mylock; -- 查询阻塞
session1: unlock tables; -- 释放表锁
session2: 4 row in set (22.57 sec) -- 查询执行完成
session1: select * from tdep; -- 可以访问
MDL(metaDataLock)元数据:表结构
在Mysql5.5 版本中引入了MDL,当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁
元数据读锁
session1: begin; -- 开启事务
session2: alter table mylock add f int; -- 修改阻塞
session1: commit; -- 提交事务 或者 rollback 释放读锁
query ok, 0 row affected (38.67 sec) -- 修改完成
Records: 0 Duplicates: 0 Warnings: 0
元数据写锁
查看行锁状态
show status like 'innodb_row_lock%';
session1: begin; -- 开启事务未提交
select * from mylock where ID = 1 lock in share mode; -- 手动加id=1的行读锁,使用索引
session2: update mylock set name = 'y' where id = 2; -- 未锁定该行可以修改
session2: update mylock set name = 'y' where id = 1; -- 锁定该行修改阻塞
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction -- 锁定超时
session1: commit; -- 提交事务 或者 rollback 释放行读锁
session2: udpate mylock set name = 'y' where id = 1; -- 修改成功
Query OK, 1 row affected (0.00 sec)
Row matched: 1 Changed: 1 Warnings: 0
注: 使用索引加行锁 , 未锁定的行可以访问
session1: begin; -- 开启事务未提交
-- 手动加name='c'的行读锁, 未使用索引
select * from mylock where name = 'c' lock in share mode;
session2: update mylock set name = 'y' where id = 2; -- 修改阻塞 未用索引行锁升级为表锁
session1: commit; -- 提交事务 或者 rollback 释放读锁
update mylock set name = 'y' where id = 2; -- 修改成功
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0
注:未使用索引行锁升级为表锁
session1: begin; -- 开启事务未提交
-- 手动加id=1的行写锁,
select * from mylock where id = 1 for update;
session2: select * from mylock where id = 2; -- 可以访问
session2: select * from mylock where id = 1; -- 可以读, 不加锁
session2: select * from mylock where id = 1 lock in share mode; -- 加读锁被阻塞
session1: commit; -- 提交事务 或者 rollback 释放写锁
执行成功
主键索引产生记录锁
按照功能分类,分为两种:
先看一个事务是否是自动提交的
show variables like 'autocommit'
锁是计算机协调多个进程或线程并发访问某一资源的机制。锁使用独占的方式来保证在只有一个版本的情况下事务之间相互隔离,所以锁可以理解为单版本控制。
引入锁之后就可以支持并行处理事务,如果事务之间涉及到相同的数据项时,会使用排他锁,或者叫互斥锁,先进入的事务独占数据项以后,其他事务被阻塞,等待前面的事务释放锁。
建表语句
CREATE TABLE `test` (
`task_value` text,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`text_no` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `inx_text_no` (`text_no`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;