sequel 5.83.0 → 5.84.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +8 -3
- data/lib/sequel/database/schema_methods.rb +2 -0
- data/lib/sequel/extensions/pg_json_ops.rb +328 -1
- data/lib/sequel/sql.rb +8 -5
- data/lib/sequel/version.rb +1 -1
- metadata +2 -236
- data/CHANGELOG +0 -1393
- data/README.rdoc +0 -936
- data/doc/advanced_associations.rdoc +0 -884
- data/doc/association_basics.rdoc +0 -1859
- data/doc/bin_sequel.rdoc +0 -146
- data/doc/cheat_sheet.rdoc +0 -255
- data/doc/code_order.rdoc +0 -104
- data/doc/core_extensions.rdoc +0 -405
- data/doc/dataset_basics.rdoc +0 -96
- data/doc/dataset_filtering.rdoc +0 -222
- data/doc/extensions.rdoc +0 -77
- data/doc/fork_safety.rdoc +0 -84
- data/doc/mass_assignment.rdoc +0 -98
- data/doc/migration.rdoc +0 -660
- data/doc/model_dataset_method_design.rdoc +0 -129
- data/doc/model_hooks.rdoc +0 -254
- data/doc/model_plugins.rdoc +0 -270
- data/doc/mssql_stored_procedures.rdoc +0 -43
- data/doc/object_model.rdoc +0 -563
- data/doc/opening_databases.rdoc +0 -439
- data/doc/postgresql.rdoc +0 -611
- data/doc/prepared_statements.rdoc +0 -144
- data/doc/querying.rdoc +0 -1070
- data/doc/reflection.rdoc +0 -120
- data/doc/release_notes/5.0.0.txt +0 -159
- data/doc/release_notes/5.1.0.txt +0 -31
- data/doc/release_notes/5.10.0.txt +0 -84
- data/doc/release_notes/5.11.0.txt +0 -83
- data/doc/release_notes/5.12.0.txt +0 -141
- data/doc/release_notes/5.13.0.txt +0 -27
- data/doc/release_notes/5.14.0.txt +0 -63
- data/doc/release_notes/5.15.0.txt +0 -39
- data/doc/release_notes/5.16.0.txt +0 -110
- data/doc/release_notes/5.17.0.txt +0 -31
- data/doc/release_notes/5.18.0.txt +0 -69
- data/doc/release_notes/5.19.0.txt +0 -28
- data/doc/release_notes/5.2.0.txt +0 -33
- data/doc/release_notes/5.20.0.txt +0 -89
- data/doc/release_notes/5.21.0.txt +0 -87
- data/doc/release_notes/5.22.0.txt +0 -48
- data/doc/release_notes/5.23.0.txt +0 -56
- data/doc/release_notes/5.24.0.txt +0 -56
- data/doc/release_notes/5.25.0.txt +0 -32
- data/doc/release_notes/5.26.0.txt +0 -35
- data/doc/release_notes/5.27.0.txt +0 -21
- data/doc/release_notes/5.28.0.txt +0 -16
- data/doc/release_notes/5.29.0.txt +0 -22
- data/doc/release_notes/5.3.0.txt +0 -121
- data/doc/release_notes/5.30.0.txt +0 -20
- data/doc/release_notes/5.31.0.txt +0 -148
- data/doc/release_notes/5.32.0.txt +0 -46
- data/doc/release_notes/5.33.0.txt +0 -24
- data/doc/release_notes/5.34.0.txt +0 -40
- data/doc/release_notes/5.35.0.txt +0 -56
- data/doc/release_notes/5.36.0.txt +0 -60
- data/doc/release_notes/5.37.0.txt +0 -30
- data/doc/release_notes/5.38.0.txt +0 -28
- data/doc/release_notes/5.39.0.txt +0 -19
- data/doc/release_notes/5.4.0.txt +0 -80
- data/doc/release_notes/5.40.0.txt +0 -40
- data/doc/release_notes/5.41.0.txt +0 -25
- data/doc/release_notes/5.42.0.txt +0 -136
- data/doc/release_notes/5.43.0.txt +0 -98
- data/doc/release_notes/5.44.0.txt +0 -32
- data/doc/release_notes/5.45.0.txt +0 -34
- data/doc/release_notes/5.46.0.txt +0 -87
- data/doc/release_notes/5.47.0.txt +0 -59
- data/doc/release_notes/5.48.0.txt +0 -14
- data/doc/release_notes/5.49.0.txt +0 -59
- data/doc/release_notes/5.5.0.txt +0 -61
- data/doc/release_notes/5.50.0.txt +0 -78
- data/doc/release_notes/5.51.0.txt +0 -47
- data/doc/release_notes/5.52.0.txt +0 -87
- data/doc/release_notes/5.53.0.txt +0 -23
- data/doc/release_notes/5.54.0.txt +0 -27
- data/doc/release_notes/5.55.0.txt +0 -21
- data/doc/release_notes/5.56.0.txt +0 -51
- data/doc/release_notes/5.57.0.txt +0 -23
- data/doc/release_notes/5.58.0.txt +0 -31
- data/doc/release_notes/5.59.0.txt +0 -73
- data/doc/release_notes/5.6.0.txt +0 -31
- data/doc/release_notes/5.60.0.txt +0 -22
- data/doc/release_notes/5.61.0.txt +0 -43
- data/doc/release_notes/5.62.0.txt +0 -132
- data/doc/release_notes/5.63.0.txt +0 -33
- data/doc/release_notes/5.64.0.txt +0 -50
- data/doc/release_notes/5.65.0.txt +0 -21
- data/doc/release_notes/5.66.0.txt +0 -24
- data/doc/release_notes/5.67.0.txt +0 -32
- data/doc/release_notes/5.68.0.txt +0 -61
- data/doc/release_notes/5.69.0.txt +0 -26
- data/doc/release_notes/5.7.0.txt +0 -108
- data/doc/release_notes/5.70.0.txt +0 -35
- data/doc/release_notes/5.71.0.txt +0 -21
- data/doc/release_notes/5.72.0.txt +0 -33
- data/doc/release_notes/5.73.0.txt +0 -66
- data/doc/release_notes/5.74.0.txt +0 -45
- data/doc/release_notes/5.75.0.txt +0 -35
- data/doc/release_notes/5.76.0.txt +0 -86
- data/doc/release_notes/5.77.0.txt +0 -63
- data/doc/release_notes/5.78.0.txt +0 -67
- data/doc/release_notes/5.79.0.txt +0 -28
- data/doc/release_notes/5.8.0.txt +0 -170
- data/doc/release_notes/5.80.0.txt +0 -40
- data/doc/release_notes/5.81.0.txt +0 -31
- data/doc/release_notes/5.82.0.txt +0 -61
- data/doc/release_notes/5.83.0.txt +0 -56
- data/doc/release_notes/5.9.0.txt +0 -99
- data/doc/schema_modification.rdoc +0 -679
- data/doc/security.rdoc +0 -443
- data/doc/sharding.rdoc +0 -286
- data/doc/sql.rdoc +0 -648
- data/doc/testing.rdoc +0 -204
- data/doc/thread_safety.rdoc +0 -15
- data/doc/transactions.rdoc +0 -250
- data/doc/validations.rdoc +0 -558
- data/doc/virtual_rows.rdoc +0 -265
data/doc/sharding.rdoc
DELETED
@@ -1,286 +0,0 @@
|
|
1
|
-
= Primary/Replica Configurations and Database Sharding
|
2
|
-
|
3
|
-
Sequel has support for primary/replica configurations (writable primary
|
4
|
-
database with read only replicas databases), as well as database sharding (where you can
|
5
|
-
pick a server to use for a given dataset). Support for both
|
6
|
-
features is database independent, and should work for all database adapters
|
7
|
-
that ship with Sequel.
|
8
|
-
|
9
|
-
== The :servers Database option
|
10
|
-
|
11
|
-
Sharding and read_only support are both enabled via the :servers database
|
12
|
-
option. Using the :servers database option makes Sequel use a connection pool
|
13
|
-
class that supports sharding, and the minimum required to enable sharding
|
14
|
-
support is to use the empty hash:
|
15
|
-
|
16
|
-
DB=Sequel.connect('postgres://primary_server/database', servers: {})
|
17
|
-
|
18
|
-
In most cases, you are probably not going to want to use an empty hash. Keys in the server hash are
|
19
|
-
not restricted to type, but the general recommendation is to use a symbol
|
20
|
-
unless you have special requirements. Values in the server hash should be
|
21
|
-
either hashes or procs that return hashes. These hashes are merged into
|
22
|
-
the Database object's default options hash to get the connection options
|
23
|
-
for the shard, so you don't need to override all options, just the ones
|
24
|
-
that need to be modified. For example, if you are using the same user,
|
25
|
-
password, and database name and just the host is changing, you only need
|
26
|
-
a :host entry in each shard's hash.
|
27
|
-
|
28
|
-
Note that all servers should have the same schema for all
|
29
|
-
tables you are accessing, unless you really know what you are doing.
|
30
|
-
|
31
|
-
== Primary and Replica Database Configurations
|
32
|
-
|
33
|
-
=== Single Primary, Single Replica
|
34
|
-
|
35
|
-
To use a single, read-only replica that handles SELECT queries, the following
|
36
|
-
is the simplest configuration:
|
37
|
-
|
38
|
-
DB=Sequel.connect('postgres://primary_server/database',
|
39
|
-
servers: {read_only: {host: 'replica_server'}})
|
40
|
-
|
41
|
-
This will use the replica_server for SELECT queries and primary_server for
|
42
|
-
other queries. The :read_only key in the :servers hash is special in that
|
43
|
-
it sets the default database for Dataset methods that use SELECT queries
|
44
|
-
(which are generally read queries that do not modify the database).
|
45
|
-
|
46
|
-
If you want to ensure your queries are going to a specific database, you
|
47
|
-
can force this for a given query by using the .server method and passing
|
48
|
-
the symbol name defined in the connect options. For example:
|
49
|
-
|
50
|
-
# Force the SELECT to run on the primary server
|
51
|
-
DB[:users].server(:default).all
|
52
|
-
|
53
|
-
# Force the DELETE to run on the read-only replica
|
54
|
-
DB[:users].server(:read_only).delete
|
55
|
-
|
56
|
-
=== Single Primary, Multiple Replicas
|
57
|
-
|
58
|
-
Let's say you have 4 replica servers with names replica_server0,
|
59
|
-
replica_server1, replica_server2, and replica_server3.
|
60
|
-
|
61
|
-
num_read_only = 4
|
62
|
-
read_only_host = rand(num_read_only)
|
63
|
-
read_only_proc = proc do |db|
|
64
|
-
{host: "replica_server#{(read_only_host+=1) % num_read_only}"}
|
65
|
-
end
|
66
|
-
DB=Sequel.connect('postgres://primary_server/database',
|
67
|
-
servers: {read_only: read_only_proc})
|
68
|
-
|
69
|
-
This will use one of the replica servers for SELECT queries and use the
|
70
|
-
primary server for other queries. It's also possible to pick a random host
|
71
|
-
instead of using the round robin approach presented above, but that can result
|
72
|
-
in less optimal resource usage.
|
73
|
-
|
74
|
-
=== Multiple Primary, Multiple Replicas
|
75
|
-
|
76
|
-
This involves the same basic idea as the multiple replicas, single primary, but
|
77
|
-
it shows that the primary database is named :default. So for 4 primary servers and
|
78
|
-
4 replica servers:
|
79
|
-
|
80
|
-
num_read_only = 4
|
81
|
-
read_only_host = rand(num_read_only)
|
82
|
-
read_only_proc = proc do |db|
|
83
|
-
{host: "replica_server#{(read_only_host+=1) % num_read_only}"}
|
84
|
-
end
|
85
|
-
num_default = 4
|
86
|
-
default_host = rand(num_default)
|
87
|
-
default_proc = proc do |db|
|
88
|
-
{host: "primary_server#{(default_host+=1) % num_default}"}
|
89
|
-
end
|
90
|
-
DB=Sequel.connect('postgres://primary_server/database',
|
91
|
-
servers: {default: default_proc, read_only: read_only_proc})
|
92
|
-
|
93
|
-
== Sharding
|
94
|
-
|
95
|
-
There is specific support in Sequel for handling primary/replica database
|
96
|
-
combinations, with the only necessary setup being the database configuration.
|
97
|
-
However, since sharding is always going to be implementation dependent, Sequel
|
98
|
-
supplies the basic infrastructure, but you have to tell it which server to use
|
99
|
-
for each dataset. Let's assume a simple scenario, a distributed rainbow
|
100
|
-
table for SHA-1 hashes, sharding based on the first hex character (for a total
|
101
|
-
of 16 shards). First, you need to configure the database:
|
102
|
-
|
103
|
-
servers = {}
|
104
|
-
(('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
|
105
|
-
servers[hex.to_sym] = {host: "hash_host_#{hex}"}
|
106
|
-
end
|
107
|
-
DB=Sequel.connect('postgres://hash_host/hashes', servers: servers)
|
108
|
-
|
109
|
-
This configures 17 servers, the 16 shard servers (/hash_host_[0-9a-f]/), and 1
|
110
|
-
default server which will be used if no shard is specified ("hash_host"). If
|
111
|
-
you want the default server to be one of the shard servers (e.g. hash_host_a),
|
112
|
-
it's easiest to do:
|
113
|
-
|
114
|
-
DB=Sequel.connect('postgres://hash_host_a/hashes', servers: servers)
|
115
|
-
|
116
|
-
That will still set up a second pool of connections for the default server,
|
117
|
-
since it considers the default server and shard servers independent. Note that
|
118
|
-
if you always set the shard on a dataset before using it in queries, it will
|
119
|
-
not attempt to connect to the default server. Sequel may use the default
|
120
|
-
server in queries it generates itself, such as to get column names or table
|
121
|
-
schemas, so you should always have a default server that works.
|
122
|
-
|
123
|
-
To set the shard for a given query, you use the Dataset#server method:
|
124
|
-
|
125
|
-
DB[:hashes].server(:a).where(hash: /31337/)
|
126
|
-
|
127
|
-
That will return all matching rows on the hash_host_a shard that have a hash
|
128
|
-
column that contains 31337.
|
129
|
-
|
130
|
-
Rainbow tables are generally used to find specific hashes, so to save some
|
131
|
-
work, you might want to add a method to the dataset that automatically sets
|
132
|
-
the shard to use. This is fairly easy using a Sequel::Model:
|
133
|
-
|
134
|
-
class Rainbow < Sequel::Model(:hashes)
|
135
|
-
dataset_module do
|
136
|
-
def plaintext_for_hash(hash)
|
137
|
-
raise(ArgumentError, 'Invalid SHA-1 Hash') unless /\A[0-9a-f]{40}\z/.match(hash)
|
138
|
-
server(hash[0...1].to_sym).where(hash: hash).get(:plaintext)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
Rainbow.plaintext_for_hash("e580726d31f6e1ad216ffd87279e536d1f74e606")
|
144
|
-
|
145
|
-
=== :servers_hash Option
|
146
|
-
|
147
|
-
The connection pool can be further controlled to change how it handles attempts
|
148
|
-
to access shards that haven't been configured. The default is
|
149
|
-
to assume the :default shard. However, you can specify a
|
150
|
-
different shard using the :servers_hash option when connecting
|
151
|
-
to the database:
|
152
|
-
|
153
|
-
DB = Sequel.connect('postgres://...', servers_hash: Hash.new(:some_shard))
|
154
|
-
|
155
|
-
You can also use this feature to raise an exception if an
|
156
|
-
unconfigured shard is used:
|
157
|
-
|
158
|
-
DB = Sequel.connect('postgres://...', servers_hash: Hash.new{raise 'foo'})
|
159
|
-
|
160
|
-
If you specify a :servers_hash option to raise an exception for non configured
|
161
|
-
shards you should also explicitly specify a :read_only entry in your :servers option
|
162
|
-
for the case where a shard is not specified. In most cases it is sufficient
|
163
|
-
to make the :read_only entry the same as the :default shard:
|
164
|
-
|
165
|
-
servers = {read_only: {}}
|
166
|
-
(('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
|
167
|
-
servers[hex.to_sym] = {host: "hash_host_#{hex}"}
|
168
|
-
end
|
169
|
-
DB=Sequel.connect('postgres://hash_host/hashes', servers: servers,
|
170
|
-
servers_hash: Hash.new{raise "Invalid Server"})
|
171
|
-
|
172
|
-
=== Sharding Plugin
|
173
|
-
|
174
|
-
Sequel comes with a sharding plugin that makes it easy to use sharding with model objects.
|
175
|
-
It makes sure that objects retrieved from a specific shard are always saved back to that
|
176
|
-
shard, allows you to create objects on specific shards, and even makes sure associations
|
177
|
-
work well with shards. You just need to remember to set to model to use the plugin:
|
178
|
-
|
179
|
-
class Rainbow < Sequel::Model(:hashes)
|
180
|
-
plugin :sharding
|
181
|
-
end
|
182
|
-
|
183
|
-
Rainbow.server(:a).first(id: 1).update(plaintext: 'VGM')
|
184
|
-
|
185
|
-
If all of your models are sharded, you can set all models to use the plugin via:
|
186
|
-
|
187
|
-
Sequel::Model.plugin :sharding
|
188
|
-
|
189
|
-
=== server_block Extension
|
190
|
-
|
191
|
-
By default, you must specify the server/shard you want to use for every dataset/action,
|
192
|
-
or Sequel will use the default shard. If you have a group of queries that should use the
|
193
|
-
same shard, it can get a bit redundant to specify the same shard for all of them.
|
194
|
-
|
195
|
-
The server_block extension adds a Database#with_server method that scopes all database
|
196
|
-
access inside the block to the given shard by default:
|
197
|
-
|
198
|
-
DB.extension :server_block
|
199
|
-
DB.with_server(:a) do
|
200
|
-
# this SELECT query uses the "a" shard
|
201
|
-
if r = Rainbow.first(hash: /31337/)
|
202
|
-
r.count += 1
|
203
|
-
# this UPDATE query also uses the "a" shard
|
204
|
-
r.save
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
The server_block extension doesn't currently integrate with the sharding plugin, as it
|
209
|
-
ties into the Dataset#server method. This shouldn't present a problem in practice as
|
210
|
-
long as you just access the models inside the with_server block, since they will use
|
211
|
-
the shard set by with_server by default. However, you will probably have issues if
|
212
|
-
you retrieve the models inside the block and save them outside of the block. If you
|
213
|
-
need to do that, call the server method explicitly on the dataset used to retrieve the
|
214
|
-
model objects.
|
215
|
-
|
216
|
-
The with_server method also supports a second argument for the default read_only server
|
217
|
-
to use, which can be useful if you are mixing sharding and primary/replica servers:
|
218
|
-
|
219
|
-
DB.extension :server_block
|
220
|
-
DB.with_server(:a, :a_read_only) do
|
221
|
-
# this SELECT query uses the "a_read_only" shard
|
222
|
-
if r = Rainbow.first(hash: /31337/)
|
223
|
-
r.count += 1
|
224
|
-
# this UPDATE query also uses the "a" shard
|
225
|
-
r.save
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
=== arbitrary_servers Extension
|
230
|
-
|
231
|
-
By default, Sequel's sharding support is designed to work with predefined shards. It ships
|
232
|
-
with Database#add_servers and Database#remove_servers methods to modify these predefined
|
233
|
-
shards on the fly, but it is a bit cumbersome to work with truly arbitrary servers
|
234
|
-
(requiring you to call add_servers before use, then remove_servers after use).
|
235
|
-
|
236
|
-
The arbitrary_servers extension allows you to pass a server/shard options hash as the
|
237
|
-
server to use, and those options will be merged directly into the database's default options:
|
238
|
-
|
239
|
-
DB.extension :arbitrary_servers
|
240
|
-
DB[:rainbows].server(host: 'hash_host_a').all
|
241
|
-
# or
|
242
|
-
DB[:rainbows].server(host: 'hash_host_b', database: 'backup').all
|
243
|
-
|
244
|
-
arbitrary_servers is designed to work well in conjunction with the server_block extension:
|
245
|
-
|
246
|
-
DB.with_server(host: 'hash_host_b', database: 'backup') do
|
247
|
-
DB.synchronize do
|
248
|
-
# All queries here default to the backup database on hash_host_b
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
If you are using arbitrary_servers with server_block, you may want to
|
253
|
-
define the following method (or something similar) so that you don't
|
254
|
-
need to call synchronize separately:
|
255
|
-
|
256
|
-
def DB.with_server(*)
|
257
|
-
super{synchronize{yield}}
|
258
|
-
end
|
259
|
-
|
260
|
-
The reason for the synchronize method is that it checks out a connection
|
261
|
-
and makes the same connection available for the duration of the block.
|
262
|
-
If you don't do that, Sequel will probably disconnect from the database
|
263
|
-
and reconnect to the database on each request, since connections to
|
264
|
-
arbitrary servers are not cached.
|
265
|
-
|
266
|
-
Note that this extension only works with the sharded threaded connection
|
267
|
-
pool. If you are using the sharded single connection pool, you need
|
268
|
-
to switch to the sharded threaded connection pool before using this
|
269
|
-
extension. If you are passing the :single_threaded option to
|
270
|
-
the Database, just remove that option. If you are setting:
|
271
|
-
|
272
|
-
Sequel.single_threaded = true
|
273
|
-
|
274
|
-
just remove or comment out that code.
|
275
|
-
|
276
|
-
== JDBC
|
277
|
-
|
278
|
-
If you are using the jdbc adapter, note that it does not handle separate
|
279
|
-
options such as +:host+, +:user+, and +:port+. If you would like to use
|
280
|
-
the +:servers+ option when connecting to a JDBC database, each hash value in
|
281
|
-
the +servers+ option should contain a +:uri+ key with a JDBC connection string
|
282
|
-
for that shard as the value. Example:
|
283
|
-
|
284
|
-
DB=Sequel.connect('jdbc:postgresql://primary_server/database',
|
285
|
-
servers: {read_only: {uri: 'jdbc:postgresql://replica_server/database'}})
|
286
|
-
|