本文共 6063 字,大约阅读时间需要 20 分钟。
锁是计算机协调多个进程或线程并发访问某一资源的机制(os的pv操作)
在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。
如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素
从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂
相对其他数据库而言,MySQL的锁机制比较简单
表级锁
行级锁
对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求
对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作
MyISAM表的读操作与写操作之间,以及写操作之间是串行的
CREATE TABLE mylock ( id int(11) NOT NULL AUTO_INCREMENT, NAME varchar(20) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;INSERT INTO mylock (id, NAME) VALUES ('1', 'a'); INSERT INTO mylock (id, NAME) VALUES ('2', 'b'); INSERT INTO mylock (id, NAME) VALUES ('3', 'c'); INSERT INTO mylock (id, NAME) VALUES ('4', 'd');
MyISAM写锁阻塞读
lock table mylock write; select * from mylock;insert into mylock values(5,'e'); select * from mylock;unlock tables;
MyISAM读阻塞写
session1和session2相当于两个不同的进程
MyISAM的并发插入问题
MyISAM表的读和写是串行的
在一定条件下,MyISAM也支持查询和插入操作的并发执行
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺
show status like 'table%';
mysql> show status like 'table%';+-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Table_locks_immediate | 352 || Table_locks_waited | 2 |+-----------------------+-------+
Table_locks_waited的值比较高,则说明存在着较严重的表级锁争用情况
事务及其ACID属性
事务是由一组SQL语句组成的逻辑处理单元,事务具有4属性,通常称为事务的ACID属性。
并发事务带来的问题
相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持更多用户的并发操作
当并发事务可能出现问题
脏读
不可重复读
幻读
幻读和不可重复读是同一个级别的
| read uncommitted | √ | √ | √ |
| read committed | | √ | √ || repeatable read | | | √ || serializable | | | |# 5.1.7 之后show variables like 'transaction_isolation';SELECT @@transaction_isolation# 5.1.7 之前SELECT @@tx_isolationshow variables like 'tx_isolation'
+---------------+-----------------+| Variable_name | Value |+---------------+-----------------+| tx_isolation | REPEATABLE-READ |+---------------+-----------------+
可以通过检查 innodb_row_lock 状态变量来分析系统上的行锁的争夺情况
show status like 'innodb_row_lock%';
+-------------------------------+-------+| Variable_name | Value |+-------------------------------+-------+| Innodb_row_lock_current_waits | 0 || Innodb_row_lock_time | 18702 || Innodb_row_lock_time_avg | 18702 || Innodb_row_lock_time_max | 18702 || Innodb_row_lock_waits | 1 |+-------------------------------+-------+
Innodb_row_lock_time_avg,Innodb_row_lock_waits,Innodb_row_lock_time这三项比较常用
允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和排他写锁
若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁
加排他锁可以使用select …for update语句
加共享锁可以使用select … lock in share mode语句
InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来实现的
create table tab_no_index(id int,name varchar(10)) engine=innodb;insert into tab_no_index values(1,'1'),(2,'2'),(3,'3'),(4,'4');
create table tab_with_index(id int,name varchar(10)) engine=innodb;alter table tab_with_index add index id(id);insert into tab_with_index values(1,'1'),(2,'2'),(3,'3'),(4,'4');
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁
所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现冲突的
按照上表的数据,使用id索引查询,不同的数据行
select * from tab_with_index where id = 1 and name='1' for updateselect * from tab_with_index where id = 1 and name='4' for update
在一定条件下,MyISAM允许查询和插入并发执行,我们可以利用这一点来解决应用中对同一表查询和插入的锁争用问题。
InnoDB表锁和行锁
用户可以通过设计和SQL调整等措施减少锁冲突和死锁
转载地址:http://cojkz.baihongyu.com/