千家信息网

mysql myisam的锁机制

发表于:2024-12-03 作者:千家信息网编辑
千家信息网最后更新 2024年12月03日,首先我们知道MySQL支持多种引擎,并且不同存储引擎有很多不同,最重要的 即便是自动提交模式下 当start transaction;之后,必须要显现的commit;才能释放锁资源, myisam的锁
千家信息网最后更新 2024年12月03日mysql myisam的锁机制首先我们知道MySQL支持多种引擎,并且不同存储引擎有很多不同,最重要的 即便是自动提交模式下 当start transaction;之后,必须要显现的commit;才能释放锁资源, myisam的锁机制: 不支持行级锁,支持的是表级锁,分为共享读锁和独占写锁。 1)什么是表锁 表锁:操作对象是数据表。Mysql大多数锁策略都支持(常见mysql innodb),是系统开销最低但并发性最低的一个锁策略。事务t对整个表加读锁,则其他事务可读不可写,若加写锁,则其他事务增删改都不行 2)什么是读锁 读锁:也叫共享锁、S锁,若事务T对表A加上S锁,则事务T可以读表A但不能修改表A,其他事务只能再对表A加S锁,而不能加X锁,直到T释放A上的S 锁。这保证了其他事务可以读表A,但在事务T释放表A上的S锁之前不能对表A做任何修改,总结起来就是:我读的时候你不能写; 3)什么是写锁 写锁:又称排他锁、X锁。若事务T对表A加上X锁,事务T可以读表A也可以修改表A,其他事务不能再对表A加任何锁,直到事务T释放表A上的锁。这保证了其他事务在事务T释放表A上的锁之前不能再读取和修改表A,总结起来就是:我写的时候,你不能读,也不能写。 实验一:我读的时候你不能写,但是你可以读; 首先表company_info是myisam引擎的表; 事务1,执行长时间的查询操作 mysql> select company_id from company_info where company_name like '%liluwedafasdf%'; Empty set (43.27 sec) 事务2,尝试更新表company_info ,发现等待。。。执行了21秒。 mysql>update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000'; +----------------------------------+--------------+ | company_id | company_name | +----------------------------------+--------------+ | 4028809f60bf40fd0160bf4678be0000 | liuhehhe | +----------------------------------+--------------+ Query OK, 0 rows affected(21.98 sec) Rows matched: 1 Changed: 0 Warnings: 0 再打开一个窗口,可以看到,事务2确实在等待一个表级别的锁: mysql> show processlist; +----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+ | 14 | root | localhost | liuwenhe | Sleep | 4506 | | NULL | | 15 | root | localhost | liuwenhe | Query | 1 | Sending data | select company_id from company_info where company_name like '%liluwedafasdf%' | | 16 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| update company_info set company_name='liuhehhe' where company_id='4028809f60bf40fd0160bf4678be0000 | | 17 | root | localhost | NULL | Query | 0 | init | show processlist | +----+------+-----------+----------+---------+------+------------------------------+------------------------------------------------------------------------------------------------------+ 4 rows in set (0.00 sec) 然后再开启一个窗口,执行查询操作(事务3):发现事务1还没有执行完,事务3就执行完了,说明事务1不会阻塞事务3; mysql> select company_name from company_info where company_id='4028809f60bf40fd0160bf4678be0000'; +--------------+ | company_name | +--------------+ | liuhehhe | +--------------+ 1 row in set (2.10 sec) 实验一证明:事务1对表A加上S锁,则事务1可以读表A但不能修改表A,其他事务只能再对表A加S锁,而不能加X锁,直到T释放A上的S 锁。也就是说我读的时候你不能写,但是你可以读; 实验二:我写的时候,你不能读,也不能写; 事务1:执行更新一个表的一个字段。 mysql> update company_info set company_name='liuhehhe' where company_name like '%liuwehe%'; Query OK, 0 rows affected (1.95 sec) Rows matched: 0 Changed: 0 Warnings: 0 事务2尝试查询这个表,发现等待。。 mysql> select count(*) from company_info; +----------+ | count(*) | +----------+ | 1818708 | +----------+ 1 row in set (1.11 sec) 再开启一个窗口,查看进程,发现事务2确实在等待一个表级别的锁; mysql> show processlist; +----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+ | 19 | root | localhost | liuwenhe | Query | 1 | updating | update company_info set company_name='liuhehhe' where company_name like '%liuwehe%' | | 20 | root | localhost | liuwenhe | Query | 1 |Waiting for table level lock| select count(*) from company_info | | 21 | root | localhost | NULL | Query | 0 | init | show processlist | +----+------+-----------+----------+---------+------+------------------------------+----------------------------------------------------------------------------------------+ 3 rows in set (0.00 sec) 实验二证明:mysql的myisam引擎下,更新表的一行数据,也会上一个表级别的锁排他锁,不允许其他事务读取该表的数据,当然也不允许其他事务去写这个表,也就是说:我写的时候,你不能读,也不能写; mysql myisam的锁小结: MyISAM的读操作和写操作,以及写操作之间是串行的!MyISAM在执行读写操作的时候会自动给表加相应的锁(也就是说不用显示的使用lock table命令,然后注意是表级别的锁),MyISAM总是一次获得SQL语句所需要的全部锁,这也是MyISAM不会出现死锁的原因.区别于mysql innodb的锁机制,innodb的一般的select 是不会加任何锁的,接下来会介绍innodb的锁机制,请看下一篇文章
0