您的位置:首页 > 数据库 > MySQL

mysql事务与锁

2017-03-08 10:39 567 查看

事务控制

start transaction|begin [work]
commit [work] [and [no] chain] [[no] release]
rollback [work] [and [no] chain] [[no] release]
set autocommit={0|1}


分布式事务只支持InnoDB存储引擎。

两阶段

事务ACID

原子性(Atomicity):要么全执行,要么全不执行

一致性(Consistent):事务开始和完成时,数据必须保持一致状态

隔离性(Isolation):不受外部并发操作影响

持久性(Durable):数据修改时永久性的

术语

更新丢失:后面的更新覆盖了前面的更新

脏读:修改未提交之前,另一个事务去读了

不可重复读:一个事务内,两个时间点读的数据不一致

幻读:一个事务按照相同的查询条件读取以前检索过的数据,却发现其他事务插入了满足其查询条件的数据

事务的隔离级别

级别脏读不可重复读幻读
可读取未确认Read uncommitted可能可能可能
可读取确认Read committed不可能可能可能
可重复读不可能不可能可能
可串行化(序列化)Serializable不可能不可能不可能
MySQL的默认隔离级别是可重复读

mysql锁

各存储引擎的锁

MyISAM和MEMORY存储引擎采用的是表级锁

BDB存储引擎采用的是页面锁,但也支持表级锁

InnoDB存储引擎支持行级锁,也支持表级锁

特性
表级锁开销小,加锁快;不会出现死锁;锁定粒度大,发生冲突的概率最高,并发度最低。
行级锁开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
页面锁开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般
MyISAM的表锁

查询表级锁争用情况

show status like 'table%';


如果Table_locks_waited的值比较高,则说明存在着较严重的表级锁争用情况。

表级锁的锁模式

表共享读锁

表独占写锁

MyISAM总是一次获得sql语句所需要的全部锁,这是MyISAM表不会出现死锁的原因。

并发插入

MyISAM存储引擎有一个系统变量concurrent_insert

concurrent_insert值说明
0不允许并发插入
1如果表中没有空洞,MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录
2无论MyISAM表中有没有空洞,都允许在表尾并发插入记录
锁调度

通过设置启动参数low-priority-updates使MyISAM引擎默认给予读请求以优先的权利

通过执行命令set low-priority-updates=1,使得该连接发出的更新请求优先级降低

通过指定insert,update,delete语句的low_priority属性,降低该语句的优先级

查询优先可以解决查询相对重要的应用(用户登录)中读锁等待严重的问题。读写冲突,可以给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,mysql就暂时将写请求的优先级降低,给读进程一定获得锁的机会。一些需要长时间运行的查询操作,也会使写进程”饿死”,尽量避免出现长时间运行的查询操作,对于复杂的查询,不要一个sql写完,否则执行时间可能较长。在可能的情况下,尽量用中间表等措施对sql语句做一定的分解,使每一步查询时间都比较短,从而减少锁冲突。统计类的sql,可以安排在夜间空闲时刻执行。

InnoDB锁问题

InnoDB与MyISAM的最大不同有两点

支持事务

采用行级锁

获取InnoDB行锁争用情况

show status like 'innodb_row_lock%'


如果InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比较高,则锁争用比较严重。

查看锁等待情况

select * from innodb_locks \G;


设置InnoDB Monitors观察锁冲突情况

create table innodb_monitor(a int) engine=innodb;

show engine innodb status\G;

drop table innodb_monitor;


InnoDB的行锁

共享锁(S):类似读锁

排他锁(X):类似写锁

表锁,意向锁

意向共享锁(IS)

意向排他锁(IX)

当前模式\是否兼容\请求锁模式XIXSIS
X冲突冲突冲突冲突
IX冲突兼容冲突兼容
S冲突冲突兼容兼容
IS冲突兼容兼容兼容
InnoDB行锁实现方式

InnoDB行锁是通过给索引上的索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁,InnoDB行锁分为3中情形。

Record lock:对索引项加锁

Gap lock:对索引项之间的”间隙”、第一条记录前的”间隙”或最后一条记录后的”间隙”加锁。

Next-key lock:前两种的组合,对记录及前面的间隙加锁。

InnoDB这种行锁实现特点意味着,如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样。

next-key锁

范围条件检索数据,符合条件的数据行会加锁,条件范围内的间隙也会加锁,比如:select * from emp where empid>100 for update;其中,empid的值分别是1,2,…,100,101,InnoDB不仅会对符合条件的101记录加锁,也会对empid大于101(这些记录不存在)的间隙(GAP)加锁。一方面为了防止幻读,另一方面,为了满足其恢复和复制的需要。注意:范围更新,无论出于那个隔离级别都使用next-key锁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mysql 事务