Skip to content

Commit 36053f8

Browse files
committed
add test and improve doc
1 parent 83d56b7 commit 36053f8

File tree

3 files changed

+47
-14
lines changed

3 files changed

+47
-14
lines changed

README.md

+14-12
Original file line numberDiff line numberDiff line change
@@ -276,18 +276,20 @@ Default: false
276276
```
277277

278278

279-
RejectreadOnly causes mysql driver to reject read-only connections. This is
280-
specifically for AWS Aurora: During a failover, there seems to be a race
281-
condition on Aurora, where we get connected to the [old master before
282-
failover], i.e. the [new read-only slave after failover].
283-
284-
Note that this should be a fairly rare case, as automatic failover normally
285-
happens when master is down, and the race condition shouldn't happen unless it
286-
comes back up online as soon as the failover is kicked off. But it's pretty
287-
easy to reproduce using a manual failover. In case this happens, we should
288-
reconnect to the Aurora cluster by returning a driver.ErrBadConnection.
289-
290-
tl;dr: Set this if you are using Aurora.
279+
RejectreadOnly causes the driver to reject read-only connections. This is for a
280+
possible race condition during an automatic failover, where the mysql client
281+
gets connected to a read-only replica after the failover.
282+
283+
Note that this should be a fairly rare case, as an automatic failover normally
284+
happens when the primary is down, and the race condition shouldn't happen
285+
unless it comes back up online as soon as the failover is kicked off. On the
286+
other hand, when this happens, an mysql application can get stuck on a
287+
read-only connection until restarted. It is however fairly easy to reproduce,
288+
for example, using a manual failover on AWS Aurora's MySQL-compatible cluster.
289+
290+
If you are not relying on read-only transactions to reject writes that aren't
291+
supposed to happen, setting this on some MySQL providers (such as AWS Aurora)
292+
is safer for failovers.
291293

292294

293295
##### `strict`

driver_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -1949,3 +1949,34 @@ func TestColumnsReusesSlice(t *testing.T) {
19491949
t.Fatalf("expected columnNames to be set, got nil")
19501950
}
19511951
}
1952+
1953+
func TestRejectReadOnly(t *testing.T) {
1954+
runTests(t, dsn, func(dbt *DBTest) {
1955+
// Create Table
1956+
dbt.mustExec("CREATE TABLE test (value BOOL)")
1957+
// Set the session to read-only. We didn't set the `rejectReadOnly`
1958+
// option, so any writes after this should fail.
1959+
dbt.mustExec("SET SESSION TRANSACTION READ ONLY")
1960+
_, err := dbt.db.Exec("DROP TABLE test")
1961+
if err == nil {
1962+
t.Fatalf("writing to DB in read-only session without " +
1963+
"rejectReadOnly did not error")
1964+
}
1965+
// Set the session back to read-write so runTests() can properly clean
1966+
// up the table `test`.
1967+
dbt.mustExec("SET SESSION TRANSACTION READ WRITE")
1968+
})
1969+
1970+
// Enable the `rejectReadOnly` option.
1971+
runTests(t, dsn+"&rejectReadOnly=true", func(dbt *DBTest) {
1972+
// Create Table
1973+
dbt.mustExec("CREATE TABLE test (value BOOL)")
1974+
// Set the session to read only. Any writes after this should error on
1975+
// a driver.ErrBadConn, and cause `database/sql` to initiate a new
1976+
// connection.
1977+
dbt.mustExec("SET SESSION TRANSACTION READ ONLY")
1978+
// This would error, but `database/sql` should automatically retry on a
1979+
// new connection which is not read-only, and eventually succeed.
1980+
dbt.mustExec("DROP TABLE test")
1981+
})
1982+
}

packets.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,8 @@ func (mc *mysqlConn) handleErrorPacket(data []byte) error {
556556
// Oops; we are connected to a read-only connection, and won't be able
557557
// to issue any write statements. Since RejectReadOnly is configured,
558558
// we throw away this connection hoping this one would have write
559-
// permission. This is specifically for an AWS Aurora behavior during
560-
// failover. See README.md for more.
559+
// permission. This is specifically for a possible race condition
560+
// during failover (e.g. on AWS Aurora). See README.md for more.
561561
//
562562
// We explicitly close the connection before returning
563563
// driver.ErrBadConn to ensure that `database/sql` purges this

0 commit comments

Comments
 (0)