再谈事务和锁:mysql innodb
先看看mysql文档最好:
http://dev.mysql.com/doc/refman/5.1/en/innodb-lock-modes.html
http://dev.mysql.com/doc/refman/5.1/en/innodb-transaction-model.html
http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
http://dev.mysql.com/doc/refman/5.1/en/innodb-record-level-locks.html
http://dev.mysql.com/doc/refman/5.1/en/lock-tables.html
首先InnoDB默认是行级锁,但是,不是说事务里面的select语句是自动加了锁的,需要使用LOCK IN SHARE MODE
设定S锁 或 FOR UPDATE
设定X锁。 并且要看事务隔离级别。例如SERIALIZABLE级别下,本事务下所有不带锁的查询将自动设置为LOCK IN SHARE MODE
。参见http://dev.mysql.com/doc/refman/5.1/en/set-transaction.html
This level is like
REPEATABLE READ
, butInnoDB
implicitly converts all plainSELECT
statements toSELECT ... LOCK IN SHARE MODE
if autocommit is disabled. If autocommit is enabled, theSELECT
is its own transaction. It therefore is known to be read only and can be serialized if performed as a consistent (nonlocking) read and need not block for other transactions. (To force a plainSELECT
to block if other transactions have modified the selected rows, disable autocommit.)
然而update和delete语句是加了X锁的[这个照其文档意思是这样,我没找到明确说明]。insert语句就用不了行级锁了,因为这待插入的数据还没存储。
select 语句即使加了锁,但是如果查找条件没有明确使用索引,则导致锁表。
舉個例子:
假設有個表單 products ,裡面有 id 跟 name 二個欄位,id 是主鍵。
例1: (明確指定主鍵,並且有此筆資料,row lock)
SELECT * FROM products WHERE id='3' FOR UPDATE;
例2: (明確指定主鍵,若查無此筆資料,無 lock)
SELECT * FROM products WHERE id='-1' FOR UPDATE;
例2: (無主鍵,table lock)
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
例3: (主鍵不明確,table lock)
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
例4: (主鍵不明確,table lock)
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
锁和事务的关系这里我再明白了些,参照三级封锁协议两段锁以及隔离级别 ,锁是事务实现并发控制隔离级别的实现方法。为了避免并发操作存在的异常情况出现,在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同 。
虽然各数据库对此标准的实现各有不同,但是它们需要保证这一点。对于使用者则需依据实际情况定义好适当的事务隔离策略再来调用个数据库native sql来实现这些策略来达到应用目的,而不是以为只要使用了事务就万事大吉了。
参考:
http://blog.csdn.net/zdl1016/article/details/6946060
http://hi.baidu.com/thinkinginlamp/blog/item/d677cffcb7098482b901a014.html
http://www.neo.com.tw/archives/900
http://www.tapy.org/index.php/archives/228
http://blog.chinaunix.net/space.php?uid=123581&do=blog&id=2944289