外键和锁
- - CSDN博客数据库推荐文章使用外键是需要付出代价的,也就是, 即时检查,逐行进行,当然Oracle有个延时检查. 要求每次修改时都要对另外一张表多一次select操作,使用select lock in share mode方式. 意味着需要额外的锁,来确保该记录不会在事务未完成前被删除. 这将导致更多的锁等待,甚至是死锁,因为关联到其他表,死锁很难被爬出.
小测试
Session_A: mysql> begin; Query OK, 0 rows affected (0.00 sec) **加了X锁 mysql> delete from parent where id=5; Query OK, 1 row affected (0.01 sec) Session_B: mysql> begin; Query OK, 0 rows affected (0.00 sec) **想要加S锁,但失败! mysql> insert into child select 5,5; --blocking mysql> select * from information_schema.innodb_locks\G; *************************** 1. row *************************** lock_id: 14694:8:3:5 lock_trx_id: 14694 lock_mode: S lock_type: RECORD lock_table: `test`.`parent` lock_index: PRIMARY lock_space: 8 lock_page: 3 lock_rec: 5 lock_data: 5 *************************** 2. row *************************** lock_id: 14691:8:3:5 lock_trx_id: 14691 lock_mode: X lock_type: RECORD lock_table: `test`.`parent` lock_index: PRIMARY lock_space: 8 lock_page: 3 lock_rec: 5 lock_data: 5 2 rows in set (0.01 sec)
mysql> set foreign_key_checks=0; Query OK, 0 rows affected (0.00 sec) mysql> load data... mysql> set foreign_key_checks=1; Query OK, 0 rows affected (0.00 sec)
SELECT TABLE_NAME, CONSTRAINT_NAME, CNAME1 || NVL2(CNAME2, ',' || CNAME2, NULL) || NVL2(CNAME3, ',' || CNAME3, NULL) || NVL2(CNAME4, ',' || CNAME4, NULL) || NVL2(CNAME5, ',' || CNAME5, NULL) || NVL2(CNAME6, ',' || CNAME6, NULL) || NVL2(CNAME7, ',' || CNAME7, NULL) || NVL2(CNAME8, ',' || CNAME8, NULL) COLUMNS FROM (SELECT B.TABLE_NAME, B.CONSTRAINT_NAME, MAX(DECODE(POSITION, 1, COLUMN_NAME, NULL)) CNAME1, MAX(DECODE(POSITION, 2, COLUMN_NAME, NULL)) CNAME2, MAX(DECODE(POSITION, 3, COLUMN_NAME, NULL)) CNAME3, MAX(DECODE(POSITION, 4, COLUMN_NAME, NULL)) CNAME4, MAX(DECODE(POSITION, 5, COLUMN_NAME, NULL)) CNAME5, MAX(DECODE(POSITION, 6, COLUMN_NAME, NULL)) CNAME6, MAX(DECODE(POSITION, 7, COLUMN_NAME, NULL)) CNAME7, MAX(DECODE(POSITION, 8, COLUMN_NAME, NULL)) CNAME8, COUNT(*) COL_CNT FROM (SELECT SUBSTR(TABLE_NAME, 1, 30) TABLE_NAME, SUBSTR(CONSTRAINT_NAME, 1, 30) CONSTRAINT_NAME, SUBSTR(COLUMN_NAME, 1, 30) COLUMN_NAME, POSITION FROM USER_CONS_COLUMNS) A, USER_CONSTRAINTS B WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND B.CONSTRAINT_TYPE = 'R' GROUP BY B.TABLE_NAME, B.CONSTRAINT_NAME) CONS WHERE COL_CNT > ALL (SELECT COUNT(*) FROM USER_IND_COLUMNS I WHERE I.TABLE_NAME = CONS.TABLE_NAME AND I.COLUMN_NAME IN (CNAME1, CNAME2, CNAME3, CNAME4, CNAME5, CNAME6, CNAME7, CNAME8) AND I.COLUMN_POSITION <= CONS.COL_CNT GROUP BY I.INDEX_NAME);
会话A: mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from t where id=1 for update; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) 会话B: mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from t where id=2 for update; +----+ | id | +----+ | 2 | +----+ 1 row in set (0.00 sec) 会话A: mysql> select * from t where id=2 for update; --被阻塞 会话B: mysql> select * from t where id=1 for update; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction 会话A: +----+ | id | +----+ | 2 | +----+ 1 row in set (16.69 sec)
2013-09-08
good luck