MySQL死锁问题的相关知识是本文我们主要要介绍的内容,接下来我们就来一一介绍这部分内容,希望能够对您有所帮助。
1、MySQL常用存储引擎的锁机制
MyISAM和MEMORY采用表级锁(table-level locking)
BDB采用页面锁(page-level locking)或表级锁,默认为页面锁
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
2、各种锁特点
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
3、各种锁的适用场景
表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用
行级锁则更适合于有大量按索引条件并发更新数据,同时又有并发查询的应用,如一些在线事务处理系统
4、死锁
是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
表级锁不会产生死锁。所以解决死锁主要还是针对于最常用的InnoDB。
5、死锁举例分析
在MySQL中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking。
例如,一个表db。tab_test,结构如下:
id:主键;
state:状态;
time:时间;
索引:idx_1(state,time)
出现死锁日志如下:
?***(1) TRANSACTION:
?TRANSACTION 0 677833455, ACTIVE 0 sec, process no 11393, OSthread id 278546 starting index read
?mysql tables in use 1, locked 1
?LOCK WAIT 3 lock struct(s), heap size 320
?MySQL thread id 83, query id 162348740 dcnet03 dcnet Searching rows for update
?update tab_test set state=1064,time=now() where state=1061 and time < date_sub(now(), INTERVAL 30 minute) (任务1的sql语句)
?***(1) WAITING FOR THIS LOCK TO BE GRANTED: (任务1等待的索引记录)
?RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0 677833455 _mode X locks rec but not gap waiting
?Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; compact format; info bits 0
?0: len 8; hex 800000000097629c; asc b ;; 1: len 6; hex 00002866eaee; asc (f ;; 2: len 7; hex 00000d40040110; asc @ ;; 3: len 8; hex 80000000000050b2; asc P ;; 4: len 8; hex 800000000000502a; asc P*;; 5: len 8; hex 8000000000005426; asc T&;; 6: len 8; hex 800012412c66d29c; asc A,f ;; 7: len 23; hex 8616e642e706870; asc xxx.com/;; 8: len 8; hex 800000000000042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 8000000000004e24; asc N$;;
?*** (2) TRANSACTION:
?TRANSACTION 0 677833454, ACTIVE 0 sec, process no 11397, OS thread id 344086 updating or deleting, thread declared inside InnoDB 499
?mysql tables in use 1, locked 1
?3 lock struct(s), heap size 320, undo log entries 1
?MySQL thread id 84, query id 162348739 dcnet03 dcnet Updating update tab_test set state=1067,time=now () where id in (9921180) (任务2的sql语句)
?*** (2) HOLDS THE LOCK(S): (任务2已获得的锁)
?RECORD LOCKS space id 0 page no 849384 n bits 208 index `PRIMARY` of table `db/tab_test` trx id 0 677833454 lock_mode X locks rec but not gap
?Record lock, heap no 92 PHYSICAL RECORD: n_fields 11; compact format; info bits 0
?0: len 8; hex 800000000097629c; asc b ;; 1: len 6; hex 00002866eaee; asc (f ;; 2: len 7; hex 00000d40040110; asc @ ;; 3: len 8; hex 80000000000050b2; asc P ;; 4: len 8; hex 800000000000502a; asc P*;; 5: len 8; hex 8000000000005426; asc T&;; 6: len 8; hex 800012412c66d29c; asc A,f ;; 7: len 23; hex 8616e642e706870; asc uploadfire.com/hand.php;; 8: len 8; hex 800000000000042b; asc +;; 9: len 4; hex 474bfa2b; asc GK +;; 10: len 8; hex 8000000000004e24; asc N$;;
?*** (2) WAITING FOR THIS LOCK TO BE GRANTED: (任务2等待的锁)
?RECORD LOCKS space id 0 page no 843102 n bits 600 index `idx_1` of table `db/tab_test` trx id 0 677833454 lock_mode X locks rec but not gap waiting
?Record lock, heap no 395 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
?0: len 8; hex 8000000000000425; asc %;; 1: len 8; hex 800012412c66d29c; asc A,f ;; 2: len 8; hex 800000000097629c; asc b ;;
?*** WE ROLL BACK TRANSACTION (1)
?(回滚了任务1,以解除死锁)
原因分析:
当“update tab_test set state=1064,time=now() where state=1061 and time < date_sub(now(), INTERVAL 30 minute)”执行时,MySQL会使用idx_1索引,因此首先锁定相关的索引记录,因为idx_1是非主键索引,为执行该语句,MySQL还会锁定主键索引。
假设“update tab_test set state=1067,time=now () where id in (9921180)”几乎同时执行时,本语句首先锁定主键索引,由于需要更新state的值,所以还需要锁定idx_1的某些索引记录。
这样第一条语句锁定了idx_1的记录,等待主键索引,而第二条语句则锁定了主键索引记录,而等待idx_1的记录,这样死锁就产生了。
6、解决办法
拆分第一条sql,先查出符合条件的主键值,再按照主键更新记录:
?select id from tab_test where state=1061 and time < date_sub(now(), INTERVAL 30 minute);
?update tab_test state=1064,time=now() where id in(......);
Ⅱ SQL中的共享锁分析及如何解锁
-- Note we use tempdb for testing.USE tempdb-- Create datatable in tempdb.CREATE TABLE DlTable1 (DL1Id INT, DL1Name VARCHAR(20))CREATE TABLE DlTable2 (DL2Id INT, DL2Name VARCHAR(20))-- Insert multiple data into DlTable1 and DlTable2 in SQL Server 2005.INSERT INTO DlTable1
SELECT 1, 'Deadlock'UNION ALL
SELECT 2, 'JKhuang'UNION ALL
SELECT 3, 'Test'
GOINSERT INTO DlTable2
SELECT 1, 'Deadlock'UNION ALL
SELECT 2, 'JacksonHuang'UNION ALL
SELECT 3, 'Test'
GO-- Insert multiple data into DlTable1 and DlTable2 in SQL Server 2008.INSERT INTO DlTable1 VALUES (1, 'Deadlock'), (2, 'JKhuang'), (3, 'Test')INSERT INTO DlTable2 VALUES (1, 'Deadlock'), (2, 'JacksonHuang'), (3, 'Test')
Ⅲ sql数据库如何解锁呢
你先查一下你的数据表示不是锁表了。
select sess.sid,
sess.serial#,
lo.oracle_username,
lo.os_user_name,
ao.object_name,
lo.locked_mode
from v$locked_object lo,
dba_objects ao,
v$session sess
where ao.object_id = lo.object_id and lo.session_id = sess.sid
通过以上sql就可以知道哪个进程、序列,oracle用户名、操作系统用户名、表名、锁表模式几个字段
下面一步就是将改锁表的进程和序列杀掉了,执行下面的语句即可。
alter system kill session '1020,38953' --(1020,就是执行第一步语句得到的sid字段值,38953就是serial#字段值)
详细的请参照:网页链接
Ⅳ C#winform怎么对sqlserver2008r2表进行加锁解锁
这个和C# 没有关系,是数据库锁层面的原因,你只要执行的SQL 语句发出明确的带锁指令即可。
SQL Server 锁类型(与粒度相对应)
1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。
2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。
3. PAGLOCK:指定添加页锁(否则通常可能添加表锁)。
4. READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。
5. READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。
6. READUNCOMMITTED:等同于NOLOCK。
7. REPEATABLEREAD:设置事务为可重复读隔离性级别。
8. ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。
9. SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。
10. TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。
11. TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。
12. UPDLOCK :指定在读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。
下面的示例 为
--锁表(其它事务不能读、更新、删除)
SELECT * FROM <表名> WITH(TABLOCKX);
Ⅳ 怎样用SQL给SQL2880特定表加锁解锁
加锁的语句如下:
SELECT*FROM表名WITH(TABLOCK);
这里没有解锁的概念,只有不加锁的概念,语句如下:
SELECT*FROM表名WITH(NOLOCK);
加锁的解释:
TABLOCK(表锁)
此选项被选中时,SQLServer将在整个表上置共享锁直至该命令结束。这个选项保证其他进程只能读取而不能修改数据。
不加锁的解释:
NOLOCK(不加锁)
此选项被选中时,SQLServer在读取或修改数据时不加任何锁。在这种情况下,用户有可能读取到
Ⅵ 怎么解决sql server数据库死锁
1
编程的时候对死锁多加注意,相应增加代码解决
2
实际使用时,可以手工从sql管理器里面解锁
3
因为页面级锁第一个程序打开页面操作,马上就关闭的话,后面再打开就不会引起锁定了。所以主要是程序编写不完善出现的,SQL语句造成的少之又少。
Ⅶ sql server 2008 并发 锁定行的难题~
1、如果是为了提高查询效率的话就没必要这么做,如果数据量大了导致查询慢的话可以采用表分区或者建立索引。
2、如果是业务上有这种要求的话,你可以采用ROW_NUMBER函数根据主键列排号,不同的线程使用不同的号段,分别插入数据库。这样可以避免加锁操作,从而避免死锁。
3、尽量去使用INSERT INTO 表(字段) SELECT 字段 FROM 表语句。
4、所有线程执行完毕之后使用TRUNCATE TABLE去清理数据比较好。
Ⅷ sql server怎样给一个数据库加锁和解锁
加锁的语句如下:
1
SELECT * FROM 表名 WITH (TABLOCK);
这里没有解锁的概念,只有不加锁的概念,语句如下:
1
SELECT * FROM 表名 WITH (NOLOCK);
加锁的解释:
TABLOCK(表锁)
此选项被选中时,SQL Server 将在整个表上置共享锁直至该命令结束。 这个选项保证其他进程只能读取而不能修改数据。
不加锁的解释:
NOLOCK(不加锁)
此选项被选中时,SQL Server 在读取或修改数据时不加任何锁。 在这种情况下,用户有可能读取到
Ⅸ MySQL数据库如何锁定和解锁数据库表
第一步,创建数据库表writer和查看表结构,利用SQL语句:
create table writer(
wid int(10),
wno int(10),
wname varchar(20),
wsex varchar(2),
wage int(2)
第二步,向数据库表writer插入五条数据,插入后查看表里数据
第三步,利用锁定语句锁定数据库表writer,利用SQL语句:
lock table writer read;
让数据库表只读不能进行写
第四步,为了验证锁定效果,可以查看数据库表数据,利用SQL语句:
select * from writer;
第五步,利用update语句对id=5进行更新,SQL语句为:
update writer set wname = '胡思思' where id = 5;
第六步,利用unlock进行解锁,SQL语句为:
unlock tables;