Mysql的锁机制

       不同的存储引擎支持不同的锁机制。MyISAM和MEMORY存储引擎采用的是表级锁;InnoDB存储引擎默认情况下是支持行级锁,也支持表级锁。

       表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低

       行级锁:开销小,加锁慢;会出现死锁,锁定粒度小,发生锁冲突的概率最低,并发度最高

一、MyISAM表锁

       Myisam不支持事务

       mysql的表级锁有两种模式:表共享读锁 和 表独占写锁

       (1) 写锁    当一个线程获得对一个表的写锁之后,只有持有锁的线程可以对表进行跟新操作,其他线程的读写操作都会等待,知道锁释放为止。

session1session2

获取表的write锁定:

     lock table mylock write;   (mylock是表名)

当前session对表的查询、插入、更新操作都可行:

     select * from mylock;

     insert into mylock values(5,'e');

当前session对表的查询等等操作会被阻塞:

select * from mylock

释放锁:unlock tables;

       (2) 读锁

            lock table read 加读锁后,当前session更新或者访问其他表会提示错误;另一个session可以查询表中数据,更新就会等待

session1session2

获得表的read锁定:

    lock table mylock read;

当前session可以查询该表记录:

    select * from mylock;

当前session可以查询该表记录:

   select * from mylock;

当前session不能查询没有锁定的表

   select * from person;

Table ‘person’ was not locked with LOCK TABLES;

当前session可以查询或者更新未锁定的表:

select * from mylock;

insert into person values(1,'zhangsan');

当前session插入或者更新表会提示错误:

   insert into mylock values (6,'f') 

   update mylock set name='aa' where id = 1;

Table 'mylock' was locked with a READ lock and can't be updated

当前session插入数据会等待获得锁 :

    insert into mylock values(6,'f');

释放锁:unlock tables;获得锁,更新成功

       (3) 注意

            myisam 一般不需要用户使用命令显示加锁,MyISAM在执行查询语句之前,会自动给涉及的所有表加读锁,在执行更新操作之前,会自动给涉及的表加写锁。

            MyISAM的并行插入问题:myisam表的读和写是串行的,在一定条件下,MyISAM也支持查询和插入操作并发执行。

            session1 获取表的readlocal锁定:lock table mylock read local;

            session1中不能插入修改mylock表,不能查询没有锁定的表;

           session2可以向mylock插入数据,但是该插入的数据,session1不能查看。

            session2修改mylock表中数据,会阻塞等待。

             session1释放锁:unlock tables;

    show status like 'table%'   --- table_locks_waited 的值比较高,则说明存在着严重的表级锁征用情况。

二、InnoDB锁

       (1) 事务及ACID属性

             Actomicity 原子性  要么全部执行,要么全部都不执行

             Consistent 一致性  事务开始和完成时,数据必须保持一致

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

             Durable 持久性       事务完成后,对于数据的修改是永久性的

         (2) 并发事务带来的问题

               脏读、不可重复读、幻读    --- 都是数据一致性问题,通过 锁解决

               show status like ‘%innodb_row_lock%’

                    InnoDB_row_lock_waits和InnoDB_row_lock_time_avg的值比较高,说明锁争用比较严重。

          (3)行锁

                共享锁(s) 又称读锁;排他锁(X) 又称写锁

                mysql Innodb 引擎默认的修改数据语句:update、delete、insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型。

                手动加排他锁: select .... for update;共享锁:select....lock in share mode

                 InnoDB行锁是通过给索引上的索引项加锁实现的,只有通过索引条件检索数据,InnoDB才能使用行级锁,否则使用表锁。

                    ①  tab表中没有主键没有索引;

session1session2

set autocommit=0;  ----  系统默认开启事务,但并未默认提交事务,需手动提交;

 select * from tab where id = 1;

set autocommit=0;

select * from tab where id = 2;

select * from tab where id =1 for update;
select * from tab where id = 2 for update;

             默认情况下,autocommit为1,开启事务,并且在执行完sql后,默认提交。

             在autocommit为1的情况下,手动 start transaction;  需要手动提交。

             session1只给了一行id=1加了排他锁,但session2在请求其他行锁的时候,会出现等待,因为没有索引的情况下,innodb使用表锁。

                 tab表中,id是主键索引

session1session2

set autocommit=0;

set autocommit=0;

select * from tab where id =1 and name='1' for update;
select * from tab where id = 1 and name = '4' for update; 虽然session2访问的是和session1不同的记录,但是使用了相同的索引,所以需要等待锁。

                   ③ 共享锁 所有事务都可以读取,但是所有session都不能修改,当前session也不能修改

                   ④ 排他锁  加上排他锁后,不能在此行加其他锁;只有当前session才可以对数据进行修改,其他session可读,不可修改。       

                   ⑤ 意向共享锁 Intertion Shared Locks (简称IS锁,属于表锁)

                        表示事务准备给数据行加上共享锁,也就是一个数据在加入共享锁之前必须先取得该表的IS锁

                   ⑥ 意向排他锁 Intention Exclusive Locks(简称IX锁,表锁)

                        表示事务准备给数据行加上排他锁,也就是一个数据在加入排他锁之前必须先取得该表的IX锁

                            意向锁是InnoDB数据操作之前自动加的,不需要用户干预

                   ⑦ 自增锁 AUTO-INC Locks 

                             针对自增列自增长的一个特殊的表级别锁

                             show variables like '%innodb_autoinc_lock_mode%'

                            --- 默认是1,代表连续

                             自增列中,事务之前是10,若事务添加10条记录,若事务执行失败回滚,则表中下次新增,也会从21开始。

                  ⑧ 死锁

session1session2
①select * from tab where id =1 for update;①select * from tab where id = 2 for update;
②select * from tab where id = 2 for update;②select * from tab where id =1 for update;

                     mysql中,如果发现死锁,会随机自动释放。

                     session1中②执行,等待。然后session2中②执行,可以出结果,则session1中的②报错:

                    最后给id=2加的锁(session2中的①),最后给谁加的锁,再给那个加锁就会报错,那个session的锁就会释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值