mysql03-锁

mysql的连接层:当mysql启动时,会等待客户端连接,每次链接都会新建一个线程处理,通过对用户名,ip,密码验证,一旦连接成功,还会验证执行权限。

 

sql 连接层:sql执行的相关功能,比如 解析,优化,缓存,内置函数等。

缓存:

show variables like '%query_cache_type%';查看缓存是否开启
show variables like '%query_cache_size%';查看缓存大小

SET GLOBAL query_cache_type = 1;设置缓存开启(会报错),不过只能配置在 my.cnf 文件中

 而且不建议开启,因为QC 严格要求 2 次 SQL 请求要完全一样,包括 SQL 语句,连接的数据库、协议版本、字符

集等因素都会影响;
 
sql解析查询:

执行顺序

 

sql解释计划,优化

 id 代表执行顺序,id相同从上到下,id不同先执行id大的

type 代表执行的索引类型,

key 代表走的索引列

ken_len 代表走的索引长度

row 代表查了多少行

锁:当数据库并发访问某一资源时进行限制

mysql中的锁:行锁 表锁  页锁(gap/间隙锁),其中表锁适合 olap,行锁适合oltp,至于olap与oltp的区别可以看这篇文章:https://www.cnblogs.com/lingchen-liang/p/10690619.html

myisam由于不常用,且不被维护再次不做研究,直接说innodb

Innodb: 支持行锁

共享锁:读锁,几个事务对一行数据可以同时进行读操作,但是不允许进行写操作,不允许加排他锁,但允许上共享锁;

排他锁:写锁,当某一个事务对一行数据加了写锁,不允许其他事务写,但可以读,不允许加锁

语法:

  读锁;

 

写锁:俩个事务不能锁同一个索引,cud都会自动加上排他锁,行锁必须借助索引,否则就是表锁

-- 这个是建表语句
 
CREATE TABLE testdemo (
`id` int(255) NOT NULL ,
`c1` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`c2` int(50) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
INDEX `idx_c2` (`c2`) USING BTREE
)
ENGINE=InnoDB;
insert into testdemo VALUES(1,'1',1),(2,'2',2)

以下是加锁的例子  

BEGIN
select * from testdemo where id =1 for update
在另外一个 session 中
update testdemo set c1 = '1' where id = 2 成功
update testdemo set c1 = '1' where id = 1 等待
 
2.BEGIN
update testdemo set c1 = '1' where id = 1
在另外一个 session 中
update testdemo set c1 = '1' where id = 1 等待
 
BEGIN
update testdemo set c1 = '1' where c1 = '1'
在另外一个 session 中
update testdemo set c1 = '2' where c1 = '2' 等待
 
4.第一个 session 中
select * from testdemo where id =1 for update
第二个 session
select * from testdemo where id =1 lock in share mode
回到第一个 session UNLOCK TABLES 并不会解锁
使用 commit 或者 begin 或者 ROLLBACK 才会解锁
 
5.再来看下表锁
lock table testdemo WRITE
使用 commit,ROLLBACK 并不会解锁
使用 UNLOCK TABLES 或者 begin 会解锁
 
锁等待问题:如果实际工作中有人锁住数据库,该怎么办?
 
程序员甲,正直调试代码
BEGIN
SELECT * FROM testdemo WHERE id = 1 FOR UPDATE
你正直完成的功能也要经过那部分的代码,你得上个读锁
BEGIN
SELECT * FROM testdemo WHERE id = 1 lock in share mode
可是写锁是不允许上任何锁的,只能超时等待
 
解决方法:
select * from information_schema.INNODB_LOCKS;
找到它 饶过他
select * from sys.innodb_lock_waits
通过kill 干掉这个事务,至于被发现是否会挨揍,另说

 如果是mysql 5.6

SELECT
r.trx_id waiting_trx_id,
r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread
FROM
information_schema.innodb_lock_waits w
INNER JOIN
information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN
information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; 
原文地址:https://www.cnblogs.com/xiaoshahai/p/14100310.html