乐观锁不是数据库自带的,需要我们自己去实现,假设丢失更新不一定发生。
不会出现死锁,发生锁冲突几率高,并发低。
对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们之所以选择InnoDB表的理由。但在个另特殊事务中,也可以考虑使用表级锁。
第一种情况是: 事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度。
第二种情况是: 事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销。
(1)使用LOCK TALBES虽然可以给InnoDB加表级锁,但必须说明的是,表锁不是由InnoDB存储引擎层管理的,而是由其上一层MySQL Server负责的,仅当autocommit=0、innodb_table_lock=1(默认设置)时,InnoDB层才能知道MySQL加的表锁,MySQL Server才能感知InnoDB加的行锁,这种情况下,InnoDB才能自动识别涉及表级锁的死锁;否则,InnoDB将无法自动检测并处理这种死锁。
(2)在用LOCAK TABLES对InnoDB锁时要注意,要将AUTOCOMMIT设为0,否则MySQL不会给表加锁;事务结束前,不要用UNLOCAK TABLES释放表锁,因为UNLOCK TABLES会隐含地提交事务;COMMIT或ROLLBACK产不能释放用LOCAK TABLES加的表级锁,必须用UNLOCK TABLES释放表锁,正确的方式见如下语句。
例如,如果需要写表t1并从表t读,可以按如下做:
SET AUTOCOMMIT=0; LOCAK TABLES t1 WRITE, t2 READ, ...; [do something with tables t1 and here]; COMMIT; UNLOCK TABLES;在 RDS MySQL 实例日常使用中,有些情况下会发现出现 Innodb 表级锁等待的情况,下面列出常见的2个原因。
显式 lock table执行了 lock tables tab_name read; 导致 DML 会话等待在表的表级锁上。
lock tables tab_name read; 隐式 lock tablemysqldump 使用默认参数进行数据导出时,会默认的开启 –lock-tables 选项,进而导致导出表上的DML操作等待在表级锁上。
对于 mysqldump 方式的导出,建议在业务低峰期进行导出,并且设置 –single-transaction 选项进行 Innodb 引擎表导出,避免出现 Innodb 表级锁等待的情况。
会出现死锁,发生锁冲突几率低,并发高 行锁分 共享锁 和 排它锁。 注意几点:
1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。 2.两个事务不能锁同一个索引,例如: 事务A先执行: select math from zje where math>60 for update; 事务B再执行: select math from zje where math<60 for update; 这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞,但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。其他事物可读不可写
共享锁 又称 s锁,读锁 若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A, 其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。 这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
其他事物不可读不可写
排他锁又称 x锁,写锁 若事务T对数据对象A加上X锁,事务T可以读A也可以修改A, 其他事务不能再对A加任何锁,直到T释放A上的锁。 这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
insert ,delete , update在事务中都会自动默认加上排它锁
又称gap锁
其实这个多出来的GAP锁,就是RR隔离级别,相对于RC隔离级别,不会出现幻读的关键。确实,GAP锁锁住的位置,也不是记录本身,而是两条记录之间的GAP。所谓幻读,就是同一个事务,连续做两次当前读 (例如:select * from t1 where id = 10 for update;),那么这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),第二次的当前读,不会比第一次返回更多的记录 (幻象)。
如何保证两次当前读返回一致的记录,那就需要在第一次当前读与第二次当前读之间,其他的事务不会插入新的满足条件的记录并提交。为了实现这个功能,GAP锁应运而生。