【问题标题】:MYSQL slow performance because of LockingMYSQL 因 Locking 而性能变慢
【发布时间】:2018-10-26 04:24:12
【问题描述】:

我在windows系统上有Mysql5.5。自过去 1 个月以来,它运行缓慢。

这是运行最多的查询:

   begin
     update  roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1
      where  roomlogs.netId = pnetid
        and  roomlogs.`status` = 0
        and  roomlogs.enterTime>=DATE(ptime)
        and  roomlogs.enterTime<DATE(ptime) + interval 1 day;
     INSERT
       into  roomlogs (roomlogs.roomId, roomlogs.netId, roomlogs.enterTime,
                       roomlogs.exitTime, roomlogs.hidden, roomlogs.checkinId)
            value
                (pRoomId, pnetid,ptime, pexit, phidden, pcheckid);
     select  *
       from  roomlogs
       where  roomlogs.roomlogId = LAST_INSERT_ID();
   end

与:

begin
    select  count(*) as total
        from  roomlogs
        where  roomId = proomId
          and  roomlogs.`status` = 0
          AND  roomlogs.enterTime >= CURDATE()
          AND  roomlogs.enterTime  < CURDATE() + INTERVAL 1 DAY
          and  roomlogs.hidden!=1;
end

这里的roomlogs索引是primary(roomlogId), NETID(netid,status,enterTime), ROOMID(roomID,status,enterTime)

当 MySQL 有更多数量的查询(大约 100 个)在服务器中同时运行时,这是我的 InnoDB 状态。

 =====================================
 2018-10-25 17:42:01 1728 INNODB MONITOR OUTPUT
 =====================================
 Per second averages calculated from the last 20 seconds
 -----------------
 BACKGROUND THREAD
 -----------------
 srv_master_thread loops: 148860 srv_active, 0 srv_shutdown, 271514 srv_idle
 srv_master_thread log flush and writes: 420374
 ----------
 SEMAPHORES
 ----------
 OS WAIT ARRAY INFO: reservation count 80056
 OS WAIT ARRAY INFO: signal count 80039
 Mutex spin waits 6920930, rounds 7674964, OS waits 52940
 RW-shared spins 27042, rounds 803211, OS waits 26514
 RW-excl spins 1173, rounds 9109, OS waits 211
 Spin rounds per wait: 1.11 mutex, 29.70 RW-shared, 7.77 RW-excl
 ------------
 TRANSACTIONS
 ------------
 Trx id counter 78706084
 Purge done for trx's n:o < 78706079 undo n:o < 0 state: running but idle
 History list length 2281
 LIST OF TRANSACTIONS FOR EACH SESSION:
 ---TRANSACTION 78705887, not started
 MySQL thread id 3000, OS thread handle 0x8e0, query id 4915274 localhost 127.0.0.1 root cleaning up
**------------ SKIPPING SOME DATA HERE--------------**
 ---TRANSACTION 78701492, not started
 MySQL thread id 15, OS thread handle 0x12c4, query id 4889345 localhost 127.0.0.1 root cleaning up
 ---TRANSACTION 78697207, not started
 MySQL thread id 16, OS thread handle 0x408, query id 4889123 localhost 127.0.0.1 root cleaning up
 ---TRANSACTION 78701491, not started
 MySQL thread id 14, OS thread handle 0x11c8, query id 4889320 localhost 127.0.0.1 root cleaning up
 ---TRANSACTION 78697202, not started
 MySQL thread id 13, OS thread handle 0x10dc, query id 4889098 localhost 127.0.0.1 root cleaning up
 ---TRANSACTION 78706073, ACTIVE 1 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2989, OS thread handle 0x157c, query id 4916082 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 1 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78706073 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78706056, ACTIVE 4 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2942, OS thread handle 0x15e0, query id 4916017 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78706056 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78706045, ACTIVE 5 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2976, OS thread handle 0x125c, query id 4915976 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 5 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78706045 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78706009, ACTIVE 9 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2946, OS thread handle 0xb98, query id 4915824 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 9 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78706009 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78706004, ACTIVE 10 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2995, OS thread handle 0x1234, query id 4915806 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 10 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78706004 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78705997, ACTIVE 12 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2948, OS thread handle 0x1708, query id 4915783 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 12 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78705997 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78705985, ACTIVE 14 sec starting index read
 mysql tables in use 1, locked 1
 LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
 MySQL thread id 2986, OS thread handle 0x1640, query id 4915747 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 ------- TRX HAS BEEN WAITING 14 SEC FOR THIS LOCK TO BE GRANTED:
 RECORD LOCKS space id 1461 page no 6 n bits 328 index `PRIMARY` of table `indoormap_v2_beta4`.`roomlogs` trx id 78705985 lock_mode X waiting
 Record lock, heap no 2 PHYSICAL RECORD: n_fields 10; compact format; info bits 0
  0: len 4; hex 80000011; asc     ;;
  1: len 6; hex 0000028a4fc7; asc     O ;;
  2: len 7; hex c3000001ed0110; asc        ;;
  3: len 7; hex 726f6f6d313038; asc room108;;
  4: len 7; hex 7973756e313032; asc ysun102;;
  5: len 5; hex 999d1f25db; asc    % ;;
  6: len 5; hex 999d1d2a13; asc    * ;;
  7: len 4; hex 80000001; asc     ;;
  8: len 4; hex 80000000; asc     ;;
  9: len 4; hex 7fffffff; asc     ;;

 ------------------
 ---TRANSACTION 78705977, ACTIVE 16 sec fetching rows
 mysql tables in use 1, locked 1
 4610 lock struct(s), heap size 539064, 1001945 row lock(s)
 MySQL thread id 2938, OS thread handle 0x10bc, query id 4915725 localhost 127.0.0.1 root updating
 update roomlogs set roomlogs.exitTime = ptime,roomlogs.`status` = 1  where roomlogs.netId = pnetid and roomlogs.`status` = 0 and
       roomlogs.enterTime>=DATE(ptime) and 
       roomlogs.enterTime<DATE(ptime) + interval 1 day
 --------
 FILE I/O
 --------
 I/O thread 0 state: wait Windows aio (insert buffer thread)
 I/O thread 1 state: wait Windows aio (log thread)
 I/O thread 2 state: wait Windows aio (read thread)
 I/O thread 3 state: wait Windows aio (read thread)
 I/O thread 4 state: wait Windows aio (read thread)
 I/O thread 5 state: wait Windows aio (read thread)
 I/O thread 6 state: wait Windows aio (write thread)
 I/O thread 7 state: wait Windows aio (write thread)
 I/O thread 8 state: wait Windows aio (write thread)
 I/O thread 9 state: wait Windows aio (write thread)
 Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
  ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
 Pending flushes (fsync) log: 0; buffer pool: 0
 23467 OS file reads, 931766 OS file writes, 524775 OS fsyncs
 0.00 reads/s, 0 avg bytes/read, 1.00 writes/s, 1.00 fsyncs/s
 -------------------------------------
 INSERT BUFFER AND ADAPTIVE HASH INDEX
 -------------------------------------
 Ibuf: size 1, free list len 39, seg size 41, 61 merges
 merged operations:
  insert 57, delete mark 5, delete 0
 discarded operations:
  insert 0, delete mark 0, delete 0
 Hash table size 4425293, node heap has 2003 buffer(s)
 30.00 hash searches/s, 19.95 non-hash searches/s
 ---
 LOG
 ---
 Log sequence number 7396884835
 Log flushed up to   7396884835
 Pages flushed up to 7396717673
 Last checkpoint at  7396717673
 0 pending log writes, 0 pending chkp writes
 164342 log i/o's done, 1.00 log i/o's/second
 ----------------------
 BUFFER POOL AND MEMORY
 ----------------------
 Total memory allocated 2197815296; in additional pool allocated 0
 Dictionary memory allocated 2793588
 Buffer pool size   131072
 Free buffers       101935
 Database pages     27102
 Old database pages 9967
 Modified db pages  377
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 498, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 22500, created 4602, written 613885
 0.00 reads/s, 0.10 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 27102, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ----------------------
 INDIVIDUAL BUFFER POOL INFO
 ----------------------
 ---BUFFER POOL 0
 Buffer pool size   16384
 Free buffers       12818
 Database pages     3312
 Old database pages 1240
 Modified db pages  63
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 72, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2713, created 599, written 81358
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3312, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 1
 Buffer pool size   16384
 Free buffers       12809
 Database pages     3319
 Old database pages 1215
 Modified db pages  27
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 15, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2770, created 549, written 78718
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3319, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 2
 Buffer pool size   16384
 Free buffers       12717
 Database pages     3411
 Old database pages 1256
 Modified db pages  28
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 77, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2795, created 616, written 49290
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3411, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 3
 Buffer pool size   16384
 Free buffers       12733
 Database pages     3395
 Old database pages 1246
 Modified db pages  51
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 45, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2780, created 615, written 91680
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3395, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 4
 Buffer pool size   16384
 Free buffers       12812
 Database pages     3318
 Old database pages 1217
 Modified db pages  47
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 108, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2645, created 673, written 95064
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3318, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 5
 Buffer pool size   16384
 Free buffers       12590
 Database pages     3538
 Old database pages 1294
 Modified db pages  51
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 35, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2905, created 633, written 89554
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3538, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 6
 Buffer pool size   16384
 Free buffers       12563
 Database pages     3567
 Old database pages 1307
 Modified db pages  52
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 32, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 3127, created 440, written 56311
 0.00 reads/s, 0.00 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3567, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 ---BUFFER POOL 7
 Buffer pool size   16384
 Free buffers       12893
 Database pages     3242
 Old database pages 1192
 Modified db pages  58
 Pending reads 0
 Pending writes: LRU 0, flush list 0, single page 0
 Pages made young 114, not young 0
 0.00 youngs/s, 0.00 non-youngs/s
 Pages read 2765, created 477, written 71910
 0.00 reads/s, 0.10 creates/s, 0.00 writes/s
 Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
 Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
 LRU len: 3242, unzip_LRU len: 0
 I/O sum[0]:cur[0], unzip sum[0]:cur[0]
 --------------
 ROW OPERATIONS
 --------------
 0 queries inside InnoDB, 0 queries in queue
 1 read views open inside InnoDB
 Main thread id 5080, state: sleeping
 Number of rows inserted 97780, updated 862074, deleted 219, read 468159566176
 1.55 inserts/s, 1.20 updates/s, 0.00 deletes/s, 3363648.47 reads/s
 ----------------------------
 END OF INNODB MONITOR OUTPUT
 ============================

所以,在这里您可以看到事务正在等待记录锁,ID 为 78705977 的最后一个事务正在锁定 1001945 行,因为它没有更新那么多行。 另外为什么要花时间来获取像 16 秒这样的行?

这里是创建房间日志表:

CREATE TABLE `roomlogs` (
   `roomId` varchar(200) CHARACTER SET latin1 DEFAULT NULL,
   `netId` varchar(50) CHARACTER SET latin1 DEFAULT NULL,
   `enterTime` datetime DEFAULT NULL,
   `exitTime` datetime DEFAULT NULL,
   `roomlogId` int(11) NOT NULL AUTO_INCREMENT,
   `status` int(11) DEFAULT '0',
   `hidden` int(11) DEFAULT '0',
   `checkinId` int(11) DEFAULT '-1',
   PRIMARY KEY (`roomlogId`),
   KEY `NETID` (`netId`,`status`,`enterTime`),
   KEY `RoomLogIndex` (`roomId`,`status`,`enterTime`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1315726 DEFAULT CHARSET=utf8

【问题讨论】:

  • 堆栈跟踪太多,查询太少。没有看到你的 SQL 代码,我认为你不会在这里得到有意义的答案。
  • 这里我减少堆栈树并提供 SQL 查询。
  • 为什么会有这么多线程并行更改相同netid的roomlogs?
  • 这是通过 autocommit=ON 完成的吗?如果没有,COMMIT 什么时候来?
  • 请提供SHOW INDEXES FROM roomlogs; -- 我想更好地理解netId。当update 运行时,它会改变多少行(通常)?

标签: mysql transactions locking innodb


【解决方案1】:

通常不会发生争用,因为 status - 属性会同时更新。 但是由于 MVCC,不同的事务不承认不再更改记录。因此,他们都会看到相同的记录并锁定它们,即使由于状态已经改变而不必这样做。

我怀疑,对您来说,完成单个更改很重要。

此时,事务 A(例如)根据事务开始时的数据状态锁定所有记录,因为它们似乎已更改。

一旦所有记录都可以被 A 锁定,因为所有在开始时并行运行的事务都已提交,事务 A 锁定并获取这些记录,发现状态已经更改,并对剩余部分进行更改.

在更改之后,最初锁定的记录集被解锁。

剩菜可能不多,但争吵很激烈。

我看到的解决方案: 似乎有许多并行线程更改具有相同 netid 的记录。可以避免吗?

如果没有,我从未尝试过,但也许更改隔离级别会有所帮助:请参阅:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html

【讨论】:

  • 有什么解决办法吗?
  • 我刚刚添加了一个附加问题
  • 您好,@aschoerk,感谢您的回答。这里状态将有一个默认值 0,这个查询将其更改为 1。状态永远不会从 1 变为 0。因此,通过此事务 A 将不会有任何剩余记录,另一个查询已更改,因为它选择了状态。此外,您是否有理由认为 ID 为 78705977 的最后一个事务锁定了 1001945 行?因为通常纽约查询将更新的记录将在 10-15 左右。
  • 您也非常频繁地更改索引,这也可能导致争用。您只对状态为 0 的记录感兴趣,要么不索引状态为 0 的记录(不确定 mysql 是否可能),要么从索引中删除状态。我更喜欢后者。一个netid每天生成多少条记录?
【解决方案2】:

我(还)不明白为什么update 会绊倒自己。但我看到了一些可能会加速其他的事情,从而间接帮助:

第 1 项,更快的选择

 select  *
   from  roomlogs
   where  roomlogs.roomlogId = LAST_INSERT_ID();

可以(也许)被替换为

 SELECT LAST_INSERT_ID(),
        pRoomId, pnetid, ptime, pexit, phidden, pcheckid;

注意:我假设这些是唯一的列,并且顺序是正确的。请提供SHOW CREATE TABLE roomlogs,这样我们就不必猜测了。

第 2 项,涵盖索引

INDEX (roomID, status, enterTime)

-->

INDEX (roomID, status, enterTime, hidden)

这将是一个“覆盖索引”,从而加快SELECT COUNT(*) ...

第 3 项,更好的优化

如果hidden只有值0和1,那么

hidden != 1

-->

hidden = 0

优化器可以比!= 更好地处理=。在这一点上,这是第 2 项的更好索引:

INDEX (roomID, status, hidden, enterTime)

注意:由于!=,我没有在第 2 项中推荐这个。

第 4 项,数据类型:

如果status 不是INT 的某种形式,那么我会有答案。再次,需要SHOW CREATE TABLE roomlogs

【讨论】:

  • 我已经更新了创建表。也因为状态是索引,我们正在更新它,它使更新查询相互等待?
  • @Nilesh - 有效问题。我不知道在这种情况下会被锁定什么。
  • 有没有办法找出来?另外,对于 ID 为 78705977 的最后一个事务是否锁定 1001945 行也需要 16 秒来获取,我没有逻辑推理?因为通常任何查询将更新的记录将在 10-15 左右。
  • @Nilesh - UPDATE 中涉及多少行?听起来像数千??
  • 在更新中评估 where 条件后,应该在 10-15 左右。 P.S.:我目前的隔离级别是 REPEATABLE READ。
【解决方案3】:

尝试一下:

begin
    START TRANSACTION;
        SELECT *
            FROM roomlogs
            WHERE  netId = pnetid
              AND  `status` = 0
              AND  enterTime >= DATE(ptime)
              AND  enterTime  < DATE(ptime) + interval 1 day;
            FOR UPDATE;    -- This might cause different locking action
            -- WHERE clause is equivalent to UPDATE's
        -- The following are as before (or as further optimized):
        UPDATE ...
        INSERT ...
        SELECT ...
    COMMIT;
end;

一个可能的原因:在旧版本的 MySQL 中,UPDATEDELETE 使用了不同的、不太复杂的优化器。因此,升级可能是一个解决方案。

检查错误。您可能会遇到超时或死锁。两者都需要处理。

【讨论】:

  • 这里,在存储过程中,我没有使用事务。那么我现在应该包括交易吗?您可以在问题中看到我的存储过程。从头到尾块!
  • @Nilesh - 我希望你能回答我关于autocommit 的问题。如果它是ON 而您没有START TRANSACTION,那么每个语句本身就是一个事务。一些程序很乐意在这种模式下工作。但是,我认为您的应用需要一些明确的、多状态的事务。是的,这就是我在这个答案中的建议(以及其他一些差异)。特别是,FOR UPDATE 除非在事务中,否则不会产生影响。
  • 目前,我的自动提交已关闭。
  • @Nilesh - 哎呀。这意味着您迟早需要做一个COMMIT。我宁愿从不使用 OFF —— 因为害怕我会忘记COMMIT。相反,我使用BEGIN (START) 来提醒我需要做COMMIT
【解决方案4】:

(是的,我知道这是我的第三个答案。但它的方向不同。)

考虑将status 移出表格。这尤其是因为需要更改多行。此外,因为您有一个日期时间,但状态与日期相关联。

新表会有

roomid ...
status TINYINT UNSIGNED NOT NULL (default 0?)
date  DATE NOT NULL   -- comes from  DATE(enterTime)
PRIMARY KEY(roomid)

当您需要查看状态时,您可以JOIN 到桌子旁。

当您需要更改状态时,您将更新 one 行。而且你不一定会碰另一张桌子。

如果您需要一些行同时处于状态=0 和一些状态=1,这个想法可能会失败。但是,如果只有“旧”行的 =0,那么在表中添加时间会显示“time 之前的状态为 0”。这会使JOIN 更复杂一些,但仍然可行。

请告诉我们status“是什么意思”。并考虑更改列名以反映语义。

【讨论】:

  • (1) status 的默认值为 0,任何查询都会将其从 0 更新为 1。没有查询会将其从 1 更新为 0。 (2) Status 将取决于 netId、roomId 和进入时间。
  • 另外,隔离级别 REPEATABLE READ 会影响锁定系统吗?我应该将其更改为 READ COMMITED 吗?
  • @Nilesh - 也许吧。它可能取决于您是否像以前那样保留“交易”,或者像我在另一个答案中建议的那样。
  • 也许stackoverflow.com/questions/52923678/… 这个问题清楚地表明了 read_committed 对 REPEATABLE_READ 的影响
  • 更改隔离级别是否有助于防止更新查询锁定?根据我的研究,由于更新声明,它可以是 Next-Key Locks。 dev.mysql.com/doc/refman/8.0/en/…dev.mysql.com/doc/refman/8.0/en/innodb-locks-set.html
猜你喜欢
  • 2012-04-01
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 2014-07-29
  • 2014-07-08
  • 2014-07-21
  • 1970-01-01
相关资源
最近更新 更多