本文对锁、事务、并发控制做一个总结,看了网上很多文章,描述非常不准确。如有与您观点不一致,欢迎有理有据的拍砖!
mysql服务器逻辑架构
每个连接都会在mysql服务端产生一个线程(内部通过线程池管理线程),比如一个select语句进入,mysql首先会在查询缓存中查找是否缓存了这个select的结果集,如果没有则继续执行 解析、优化、执行的过程;否则会之间从缓存中获取结果集。
mysql并发控制——共享锁、排他锁
共享锁
共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰;
排他锁
排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。
锁策略
锁的开销是较为昂贵的,锁策略其实就是保证了线程安全的同时获取最大的性能之间的平衡策略。
mysql锁策略:talbe lock(表锁)
表锁是mysql最基本的锁策略,也是开销最小的锁,它会锁定整个表;
具体情况是:若一个用户正在执行写操作,会获取排他的“写锁”,这可能会锁定整个表,阻塞其他用户的读、写操作;
若一个用户正在执行读操作,会先获取共享锁“读锁”,这个锁运行其他读锁并发的对这个表进行读取,互不干扰。只要没有写锁的进入,读锁可以是并发读取统一资源的。
通常发生在DDL语句\DML不走索引的语句中,比如这个DML update table set columnA=”A” where columnB=“B”.
如果columnB字段不存在索引(或者不是组合索引前缀),会锁住所有记录也就是锁表。如果语句的执行能够执行一个columnB字段的索引,那么会锁住满足where的行(行锁)。
mysql锁策略:row lock(行锁)
行锁可以最大限度的支持并发处理,当然也带来了最大开销,顾名思义,行锁的粒度实在每一条行数据。
事务
事务就是一组原子性的sql,或者说一个独立的工作单元。
事务就是说,要么mysql引擎会全部执行这一组sql语句,要么全部都不执行(比如其中一条语句失败的话)。
比如,tim要给bill转账100块钱:
1.检查tim的账户余额是否大于100块;
2.tim的账户减少100块;
3.bill的账户增加100块;
这三个操作就是一个事务,必须打包执行,要么全部成功,要么全部不执行,其中任何一个操作的失败都会导致所有三个操作“不执行”——回滚。
CREATE DATABASE IF NOT EXISTS employees;
USE employees;
CREATE TABLE `employees`.`account` (
`id` BIGINT (11) NOT NULL AUTO_INCREMENT,
`p_name` VARCHAR (4),
`p_money` DECIMAL (10, 2) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ;
INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('1', 'tim', '200');
INSERT INTO `employees`.`account` (`id`, `p_name`, `p_money`) VALUES ('2', 'bill', '200');
START TRANSACTION;
SELECT p_money FROM account WHERE p_name="tim";-- step1
UPDATE account SET p_money=p_money-100 WHERE p_name="tim";-- step2
UPDATE account SET p_money=p_money+100 WHERE p_name="bill";-- step3
COMMIT;
一个良好的事务系统,必须满足ACID特点:
事务的ACID