
1。通过线程的互斥来同步 *** 作数据库 2。数据库采用事务处理表中的数据 3。采用共享方式打开数据库,不是以独占方式打开数据库 建立一个mysql连接表加上一个临界区,表结点是这样的(mysqlcon,bool),根据实际情况定大校我用的是10个连接。
以mysql来说,可能出现脏读、不可重复读以及幻读,mysql默认设置是可重复读,即一次事务中不会读取到不同的数据。
可以做如下 *** 作:
1)打开两个客户端,均设置为RR;
2)在一个事务中,查询某个 *** 作查到某份数据;比如是某个字段version=1存在数据;
3)在另一个事务中,删除这份version=1的数据;删除后,在2所属的事务中查询数据是没有变化的,还是存在version=1的数据;
4)当我们在2所属的事务中继续更新数据,那么会发现更新不了,明明我们就看到了这份version=1的数据;
缓存一致性:
缓存一致,与什么一致?是与数据库一致,对外查询每个时刻一致;所以在针对于缓存与数据库之间该先更新哪一个呢?可能有人觉得我先更新数据库,再更新缓存不就行了吗?但是有想过个问题吗?
当用户已经支付成功了,更新到数据库,但是呢?你还在缓存中显示未支付,在用户点击频率很高并且数据库压力过大,来不及同步到缓存时,那你是不是很尴尬,这就是典型的不一致了。此时用户再支付,那你又告诉他已经支付了,那他会把你骂死的
那该怎么来做呢?我们可以这样,先更新缓存再更新数据库,那么存在什么问题呢?
1)缓存更新成功,但是数据库更新失败,而被其它的并发线程访问到
2)缓存淘汰成功,但是数据库更新失败,这也会引发后期数据不一致
你的提问就有问题
当你的程序不管是不是多线程的
获得到一个数据库连接是 数据库会把这个连接标记为繁忙 当其他程序访问时它会返回另外空闲的连接
连接个数是有限的 如果一直不释放连接 数据库就会告诉你连接已经使用完了
这里和线程安全有何关系呢? 线程安全和数据库 *** 作没有直接关系
1共用一个连接就可以 2其实一样可以用lock实现,把数据库 *** 作写成一个函数,函数内加lock。c#会安排他们排队 比如 private static object privateObjectLock = new object(); public static xxoo() { lock(privateObjectLock) { //数据 *** 作语句 } } } 你在一个函数里实现数据库 *** 作。然后线程 *** 作数据库都调用他
以mysql为数据库写的一个粗陋的demo,你参考一下,希望不会因为代码过多被百度吞了——
import javasqlConnection;import javasqlDriverManager;
import javasqlPreparedStatement;
import javasqlResultSet;
import javasqlSQLException;
import javautilArrayList;
import javautilList;
public class Test {
public static void main(String[] args) {
allotThread();
}
/
将100条数据分成10份并启动10个线程分别 *** 作
/
public static void allotThread() {
List<String[]> datas = buildDatas();
for (int i=0; i<100; i+=10) {
List<String[]> tenDatas = datassubList(i, i + 10);
insertData(tenDatas);
}
}
/
创建100条模拟数据
@return
/
public static List<String[]> buildDatas() {
List<String[]> datas = new ArrayList<String[]>();
for (int i=0; i<100; i++) {
String[] data = {"id " + i, "name " + i};
datasadd(data);
}
return datas;
}
/
启动线程进行数据插入 *** 作
@param tenDatas
/
public static void insertData(final List<String[]> tenDatas) {
new Thread(new Runnable() {
public void run() {
String sql = "insert into testtable (id, name) values (, )";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
connsetAutoCommit(false);
pstmt = getPstmt(conn, sql);
for (String[] data : tenDatas) {
pstmtsetString(1, data[0]);
pstmtsetString(2, data[1]);
pstmtaddBatch();
}
pstmtexecuteBatch();
conncommit();
connsetAutoCommit(true);
} catch (SQLException e) {
eprintStackTrace();
rollback(conn);
} catch (ClassNotFoundException e) {
eprintStackTrace();
} finally {
close(pstmt);
close(conn);
}
}
})start();
}
public static Connection getConnection() throws SQLException, ClassNotFoundException {
ClassforName("commysqljdbcDriver");
String dbUrl = "jdbc:mysql://localhost/testuseUnicode=true&characterEncoding=UTF-8";
Connection conn = DriverManagergetConnection(dbUrl, "root", "tooeasy");
return conn;
}
public static PreparedStatement getPstmt(Connection conn, String sql) throws SQLException, ClassNotFoundException {
PreparedStatement pstmt = connprepareStatement(sql);
return pstmt;
}
public static void rollback(Connection conn) {
try {
if (null != conn) {
connrollback();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(Connection conn) {
try {
if (null != conn) {
connclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(PreparedStatement pstmt) {
try {
if (null != pstmt) {
pstmtclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (null != rs) {
rsclose();
}
} catch (SQLException e) {
eprintStackTrace();
}
}
}
首先对数据库(尤其是Access)使用多线程大多不会提高效率(除非SQL中有耗时但不好资源的 *** 作,如T-SQL中休眠之类的语句)。
建议楼主:使用队列,将要执行的SQL语句放入队列中(如:SystemCollectionQueue或ArrayList),然后用一根线程一条一条执行,另外Access不支持事物回滚只有自己想办法实现了。滥用多线程会加大程序开发的难度,以及包括程序的不稳定。
另外:cbyvft的答案“……所有的线程使用同一个连接”
,是严重错误的!!连接对象Connection不能迸发,也就是不能多根线程共享一个连接对象,否则很容易引发异常(报错为:基础对象与RAW分离之类的信息)。
若非要用多线程来做,我可以给你一段代码(我以前开发的项目中一部分),请加我的“百度Hi”并发消息给我,我传给你。
我不在这里帖代码了,因为实现的代码较多,而且比较复杂(使用多线程要考虑很多问题,代码要硕壮通用,所以代码量较大)。
以上就是关于Delphi中如何多线程 *** 作数据库中的数据表全部的内容,包括:Delphi中如何多线程 *** 作数据库中的数据表、如何保证多线程从mysql数据库查询的数据不重复、请教多线程数据库程序如何保证线程安全等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)