Red*_*ing 12 mysql innodb deadlock ado.net
这几乎可以肯定是我的另一个问题的原因,但我认为值得将两者分开,因为我有一个基于以下日志的假设,我很乐意伪造或验证该假设。
我的假设是另一个死锁实际上是以下查询的结果,根据我的理解隐藏了原始查询,innodb 状态仅显示最近的事务(这是正确的吗?)。
根据日志,我检查了我们的代码,发现依次执行了以下两个查询:
db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
// I have hard coded this query in this snippet to simplify things
db.Execute("UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666");
Run Code Online (Sandbox Code Playgroud)
其中 db.Execute 基本上是在 System.Data DbCommand对象上执行ExecuteNonQuery。
那么这个查询序列会导致死锁吗?我的假设是两个查询中的两个不同的字段顺序导致了问题?我可以将这两个查询包装在一个事务中以解决死锁吗?
------------------------
LATEST DETECTED DEADLOCK
------------------------
110607 11:15:01
*** (1) TRANSACTION:
TRANSACTION 0 45674214, ACTIVE 0 sec, OS thread id 2584 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1216, 2 row lock(s)
MySQL thread id 109, query id 4044915 localhost 127.0.0.1 famdev Searching rows for update
UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id='iphone:<device_id_blah>' AND people_id<>666
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674214 lock_mode X locks rec but not gap waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
0: len 8; hex 8000000000000941; asc A;; 1: len 6; hex 000002b8eedf; asc ;; 2: len 7; hex 00000002801064; asc d;; 3: len 8; hex 80000000000004c6; asc ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc J] };; 13: len 8; hex <data6>; asc J] ;; 14: len 8; hex <data7>; asc ~t g C@;; 15: len 8; hex <data8>; asc G I &S ;; 16: len 2; hex 8042; asc B;; 17: len 8; hex <data9>; asc };; 18: len 4; hex <data10>; asc ;; 19: len 1; hex 81; asc ;; 20: len 8; hex <data11>; asc JL} Z;; 21: len 8; hex <data12>; asc J] M;; 22: len 1; hex 80; asc ;; 23: len 8; hex <data13>; asc ?;; 24: len 9; hex <data14>; asc unplugged;;
*** (2) TRANSACTION:
TRANSACTION 0 45674209, ACTIVE 0 sec, OS thread id 3804 starting index read, thread declared inside InnoDB 500
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1216, 2 row lock(s), undo log entries 1
MySQL thread id 110, query id 4044916 localhost 127.0.0.1 famdev Updating
UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674209 lock mode S locks rec but not gap
Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
0: len 8; hex 8000000000000941; asc A;; 1: len 6; hex 000002b8eedf; asc ;; 2: len 7; hex 00000002801064; asc d;; 3: len 8; hex 80000000000004c6; asc ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc J] };; 13: len 8; hex <data6>; asc J] ;; 14: len 8; hex <data7>; asc ~t g C@;; 15: len 8; hex <data8>; asc G I &S ;; 16: len 2; hex 8042; asc B;; 17: len 8; hex <data9>; asc };; 18: len 4; hex <data10>; asc ;; 19: len 1; hex 81; asc ;; 20: len 8; hex <data11>; asc JL} Z;; 21: len 8; hex <data12>; asc J] M;; 22: len 1; hex 80; asc ;; 23: len 8; hex <data13>; asc ?;; 24: len 9; hex <data14>; asc unplugged;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 4611 n bits 152 index `PRIMARY` of table `family`.`people` trx id 0 45674209 lock_mode X locks rec but not gap waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 25; compact format; info bits 0
0: len 8; hex 8000000000000941; asc A;; 1: len 6; hex 000002b8eedf; asc ;; 2: len 7; hex 00000002801064; asc d;; 3: len 8; hex 80000000000004c6; asc ;; 4: len 3; hex 446164; asc Dad;; 5: len 30; hex <data0>; asc <data1>;...(truncated); 6: SQL NULL; 7: SQL NULL; 8: len 17; hex <data2>; asc <redacted>@gmail.com;; 9: SQL NULL; 10: SQL NULL; 11: len 30; hex <data3>; asc iphone:<data4>;...(truncated); 12: len 8; hex <data5>; asc J] };; 13: len 8; hex <data6>; asc J] ;; 14: len 8; hex <data7>; asc ~t g C@;; 15: len 8; hex <data8>; asc G I &S ;; 16: len 2; hex 8042; asc B;; 17: len 8; hex <data9>; asc };; 18: len 4; hex <data10>; asc ;; 19: len 1; hex 81; asc ;; 20: len 8; hex <data11>; asc JL} Z;; 21: len 8; hex <data12>; asc J] M;; 22: len 1; hex 80; asc ;; 23: len 8; hex <data13>; asc ?;; 24: len 9; hex <data14>; asc unplugged;;
Run Code Online (Sandbox Code Playgroud)
即使这些语句是按顺序执行的,如果它们存在于同一个事务中,您必须在查询之间发出某种检查点或在开始事务之前调整事务隔离级别。
tx_isolation 有四个值:
您可以通过三 (3) 种方式设置事务隔离:
把这个写在/etc/my.cnf 并重启mysql
[mysqld]
autocommit=0
transaction-isolation = READ-UNCOMMITTED
Run Code Online (Sandbox Code Playgroud)
或者您可以在开始任何新事务之前在数据库连接本身中设置它:
db.Execute("SET tx_isolation = 'READ-UNCOMMITTED'");
db.Execute("SET autocommit = 0");
Run Code Online (Sandbox Code Playgroud)
或使用 .NET 协议禁用自动提交(免责声明:我不是 .NET 开发人员)
尽管我倾向于 READ-UNCOMMITTED 以允许“脏读”,但您必须在某个时候尝试其他事务隔离级别,以查看哪一个具有所需的效果。
试一试 !!!
所以事实证明这两个查询至少是我们遇到的问题的一部分。我们已经修改了这两个查询:
db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
db.Execute("UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>', temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com', phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>', iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47', location_lat = <lat>, location_long = <lng>, gps_strength = 66, picture_blob_id = 1661, authority = 1, active = 1, date_created = '2011-03-20 19:18:34', last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55, battery_state = 'unplugged' WHERE people_id = 666");
Run Code Online (Sandbox Code Playgroud)
到:
db.Execute("UPDATE people SET iphone_device_id=NULL WHERE iphone_device_id=@0 AND people_id<>@1", DeviceID, m_User.people_id);
db.Execute("UPDATE people SET iphone_device_id=@0, iphone_device_time=@1, last_login=@1 WHERE people_id=@2", DeviceID, System.DateTime.UtcNow, m_User.people_id);
Run Code Online (Sandbox Code Playgroud)
因此,我们不再更新整个记录(跨多个键),而是以相同的顺序更新字段。自从我们做出改变后,僵局就消失了。
归档时间: |
|
查看次数: |
6490 次 |
最近记录: |