SQLite

Check-in [38dd9b50fe]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem allowing a conflicting transaction to be committed in the case where more than one 32KB shared-memory page has been written to since the transaction was started.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA3-256: 38dd9b50fe260d853cbc2551bc1bb60ddf5752f0456e0da3afe4cbf728c891d8
User & Date: dan 2017-08-11 21:16:23.047
Context
2017-08-15
01:07
Fix a problem allowing a conflicting transaction to be committed in the case where more than one 32KB shared-memory page has been written to since the transaction was started. (check-in: 346a710da4 user: drh tags: begin-concurrent-branch-3.19)
2017-08-12
14:06
Add a more rigorous test case for the bug fixed by the previous commit on this branch. (check-in: 4256072399 user: dan tags: begin-concurrent)
2017-08-11
21:16
Fix a problem allowing a conflicting transaction to be committed in the case where more than one 32KB shared-memory page has been written to since the transaction was started. (check-in: 38dd9b50fe user: dan tags: begin-concurrent)
20:22
Add another PAGERTRACE() macro to show when pages are added to Pager.pAllRead. No impact on production builds. (check-in: 11054cf5e8 user: drh tags: begin-concurrent)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/wal.c.
2896
2897
2898
2899
2900
2901
2902
2903
2904


2905
2906
2907

2908
2909
2910
2911
2912
2913
2914
2896
2897
2898
2899
2900
2901
2902


2903
2904
2905


2906
2907
2908
2909
2910
2911
2912
2913







-
-
+
+

-
-
+







        volatile ht_slot *aHash;
        volatile u32 *aPgno;
        u32 iZero;

        rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
        if( rc==SQLITE_OK ){
          u32 i, iMin, iMax;
          assert( iFirst >= iZero );
          iMin = (iFirst - iZero);
          assert( head.mxFrame>=iZero );
          iMin = (iZero >= iFirst) ? 1 : (iFirst - iZero);
          iMax = (iHash==0) ? HASHTABLE_NPAGE_ONE : HASHTABLE_NPAGE;
          if( iMin<1 ) iMin = 1;
          if( iMax>head.mxFrame ) iMax = head.mxFrame;
          if( iMax>(head.mxFrame-iZero) ) iMax = (head.mxFrame-iZero);
          for(i=iMin; rc==SQLITE_OK && i<=iMax; i++){
            PgHdr *pPg;
            if( aPgno[i]==1 ){
              /* Check that the schema cookie has not been modified. If
              ** it has not, the commit can proceed. */
              u8 aNew[4];
              u8 *aOld = &((u8*)pPage1->pData)[40];
Changes to test/concurrent.test.
552
553
554
555
556
557
558



























































559
560
561
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+



      INSERT INTO t2 VALUES(3, 'three');
    }
  } {}

  do_test 6.$tn.2 {
    list [catch { sql2 { COMMIT } } msg] $msg
  } {1 {database is locked}}
}

do_multiclient_test tn {
  do_test 7.$tn.1 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
      WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100) 
      INSERT INTO t1 SELECT NULL, randomblob(400) FROM s;

      CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
      WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<50000) 
      INSERT INTO t2 SELECT NULL, randomblob(400) FROM s;

      CREATE TABLE t3(a INTEGER PRIMARY KEY, b);
      WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<100) 
      INSERT INTO t3 SELECT NULL, randomblob(400) FROM s;

      CREATE TABLE t4(a INTEGER PRIMARY KEY, b);

      PRAGMA wal_checkpoint;
    }
    set {} {}
  } {}

  do_test 7.$tn.2 {
    sql2 {
      BEGIN CONCURRENT;
        SELECT * FROM t1;
        INSERT INTO t4 VALUES(1, 2);
    }
    set {} {}
  } {}

  do_test 7.$tn.3 {
    sql3 {
      BEGIN CONCURRENT;
        SELECT * FROM t3;
        INSERT INTO t4 VALUES(1, 2);
    }
    set {} {}
  } {}

  do_test 7.$tn.4 {
    sql1 {
      UPDATE t1 SET b=randomblob(400);
      UPDATE t2 SET b=randomblob(400);
      UPDATE t3 SET b=randomblob(400);
    }
  } {}

  do_test 7.$tn.5 {
    csql2 { COMMIT } 
  } {1 {database is locked}}

  do_test 7.$tn.6 {
    csql3 { COMMIT } 
  } {1 {database is locked}}

}

finish_test