您的位置:首页 > 数据库

数据库的一些基本概念

2016-03-21 17:19 441 查看
本文虽为原创,但是内容多是从网上东一块西一块引用过来的,文章可以看做是学习记录

锁的类型有三种:

共享(S)锁:多个事务可封锁一个共享页;任何事务都不能修改该页; 通常是该页被读取完毕,S锁立即被释放。

排它(X)锁:仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。

更新(U)锁:用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。

http://www.cnblogs.com/mfryf/archive/2012/02/13/2349759.html

例4:(死锁的发生)

----------------------------------------

T1:

begin tran

select * from table (holdlock) (holdlock意思是加共享锁,直到事物结束才释放)

update table set column1='hello'

T2:

begin tran

select * from table(holdlock)

update table set column1='world'

假设T1和T2同时达到select,T1对table加共享锁,T2也对table加共享锁,当T1的select执行完,准备执行update时,根据锁机制,T1的共享锁需要升级到排他锁才能执行接下来的update.在升级排他锁前,必须等table上的其它共享锁释放,但因为holdlock这样的共享锁只有等事务结束后才释放,所以因为T2的共享锁不释放而导致T1等(等T2释放共享锁,自己好升级成排他锁),同理,也因为T1的共享锁不释放而导致T2等。死锁产生了。

上面的例子是针对SqlServer的。

http://www.cnblogs.com/zhouqianhua/archive/2011/04/15/2017049.html

共享锁即在select 时自动产生,排它锁在insert,update以及delete时自动产生。

(mysql不完全是这样的)

http://www.cnblogs.com/zche/archive/2013/04/30/3052109.html

相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。在本书的示例中,显式加锁基本上都是为了方便而已,并非必须如此。

如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。

意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。

排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。

举例说明下意向共享锁,比如一个事务t执行了这样一个语句:select * from table lock in share model ,如果这个语句执行成功,就对表table上了一个意向共享锁。lock in share model就是说事务t1在接下来要执行的语句中要获取S锁。如果t1的select * from table lock in share model执行成功,那么接下来t1应该可以畅通无阻的去执行只需要共享锁的语句了。意向排它锁的含义同理可知,上例中要获取意向排它锁,可以使用select *
from table for update 。

http://blog.csdn.net/xifeijian/article/details/20315565

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。
http://blog.csdn.net/xifeijian/article/details/20313977

死锁问题

http://blog.knowsky.com/260327.htm

索引

有以下四种:

普通索引(可以有重复)

唯一索引

它与前面的普通索引类似,不同的就是:普通索引允许被索引的数据列包含重复的值。而唯一索引列的值必须唯一,但允许有空值。

主键索引(就是加在主键上的唯一所有)

它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引:

组合索引

为了形象地对比单列索引和组合索引,为表添加多个字段:

CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, city VARCHAR(50) NOT NULL, age INT NOT NULL ); 为了进一步榨取MySQL的效率,就要考虑建立组合索引。就是将 name, city, age建到一个索引里:

并发

并发带来的问题

1 脏读

1 sessionA写了一条数据(并没有自动提交)

2 sessionB去读,就读到sesionA更新的数据

3 sessionA rollbacke

那么sessionB就是脏读#

2 不可重复读

1 sessionA读到一条数据

2 sessionB修改了那条数据

3 sessionA再读那条数据的时候,发现与第一次读到的不一样了#(步骤1与步骤3是在一个事务里的)

这就是不可重复读#

3 幻读

1 sessionA通过查询条件在一张表里查到了4条数据

2 sessionB更新了相同条件的数据#

2 sessionA再次使用相同的查询条件发现读到数据总数不是4#(步骤1与步骤3是在一个事务里的)

这就是幻读

数据库的隔离级别一般有四种#

分别是

read uncommitted 读取未提交内容

read committed 读取提交内容

repeatable read 可重复读

serializable 可串行化

mysql默认的隔离比较是repeatable read

隔离比较与并发问题的关系如下:



另外

InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了幻读问题。

MVCC只能工作在repeatable read与read committed级别

MySQL数据库事务隔离级别(Transaction Isolation Level)

数据库隔离级别以及mysql隔离级别

关于MVCC

从上面的描述可以看到,在查询时要符合以下两个条件的记录才能被事务查询出来:

1) 删除版本号 大于 当前事务版本号,就是说删除操作是在当前事务启动之后做的。

2) 创建版本号 小于或者等于 当前事务版本号 ,就是说记录创建是在事务中(等于的情况)或者事务启动之前。

mysql的mvcc(多版本并发控制)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: